# 安全生产移动应用

## 技术栈：[vue3](https://cn.vuejs.org/guide/introduction.html) + [vite](https://cn.vitejs.dev/config/) + [pinia](https://pinia.vuejs.org/zh/introduction.html) + [uni-ui](https://uniapp.dcloud.net.cn/component/uniui/uni-ui.html)

## Node版本 >=16.14.0，建议使用`16.19.1`

可使用`nvm`管理node版本，方便老项目维护

## 全局安装pnpm: `npm install pnpm@8.12.0 -g`

✔️需要使用 `pnpm`命令来启动项目和管理npm包
❌禁止使用 `npm`来管理包

安装依赖：`pnpm install`
     `pnpm install --registry=http://10.244.130.144:8082/repository/npm/`

启动项目：`pnpm dev:h5`

添加依赖：`pnpm add XXX`
     `pnpm add XXX -D`

删除依赖：`pnpm remove XXX`

## 推荐使用VSCode编辑器开发

使用VSCode开发需要安装的插件，插件离线包已下载至 `vscode_plugin`文件夹（[离线安装插件教程](https://blog.csdn.net/weixin_43304253/article/details/129632949)）

* uni-create-view
* uni-helper
* uniapp小程序扩展
* volar
* eslint
* EditorConfig
* prettier

## 开发注意事项

* css 单位使用`rpx`，不使用`px`，蓝湖设计图 -> 选择开发平台 -> 微信小程序
* 项目引入并使用了`AutoImport`，所以vue相关的变量不需要引入和声明
* 接口请求方式只允许大写`GET`和`POST`，其他会有平台兼容问题

## husky 验证 git 提交规范

⚠️项目安装完依赖后会自动初始化`husky`，也可以手动运行`pnpm prepare`初始化，git提交信息需以 以下一条 `英文+冒号+空格` 开头
对于`Linux`和`Mac`系统中，可能出现`因为没有将钩子 '.husky/pre-commit' 设置为可执行 钩子被忽略。`的错误。这是因为当前的文件没有执行权限，只需要执行`chmod +x .husky/pre-commit`和`chmod +x .husky/commit-msg`更改文件为可执行即可。

build: 📦编译相关的修改，例如发布版本、对项目构建或者依赖的改动

chore: 🚀其他修改, 比如改变构建流程、或者增加依赖库、工具等

ci: 👷持续集成修改

docs: ✏️文档修改

feat: ✨新特性、新功能

fix: 🐛修改 bug

perf: ⚡优化相关，比如提升性能、体验

refactor: ♻️代码重构

revert: ⏪回滚到上一个版本

style: 💄代码格式修改, 注意不是 css 修改

test: ✅测试用例修改

## 使用`iconfont`字体图标库

[邀请链接，失效请单独联系获取](https://www.iconfont.cn/invite?type=project&token=ihmbxNoY7NzRcmEe)

## 不支持 `IE11`以下

## 培训内容（方便快速上手和一些代码规范）

### vue

为提高代码的易读性、简洁性，规范代码内容书写，建议按照下面页面顺序书写代码

```javascript
<template>
  <view>
    <view>div</view>
    <text>span</text>
    <image src="img" />
    <text class="iconfont icon-arrow-right self-style"></text> // iconfont字体图标
    // 其他uni内置组件和uni-ui扩展组件均为自动引入，直接使用，无需手动引入
  </view>
</template>

<script setup> // setup语法糖不能少，否则需要将变量导出后，template才可用
import XXX from 'XXX'
import { onReady } from '@dcloudio/uni-app' // uni-app页面周期
import { throttle } from 'lodash' // 工具库，提供了防抖，节流，deepClone等方法
import dayjs from 'dayjs' // 时间操作的工具库
import { useUserStore } from '@/store/modules/user'

const userStore = useUserStore() // pinia store固定用法

const { proxy } = getCurrentInstance() // vue示例，相当于vue2页面中的this

// 组件传值接收
const props = defineProps({
  // 多少毫秒移动1像素
  speed: {
    type: Number,
    default: 100,
  },
})

let a = ref(1) // Number Boolean String Array Object

const b = ref([]) // 建议所有类型都通过ref来定义

const c = reactive([]) // 只可以定义 Array Object

// toRef 和 toRefs 感兴趣可自行了解

const isHundred = computed(() => props.speed === 100 ? true : false)

function demo() {
  a.value = 2 // 易错，需要注意
  b.value.push(1)
  c.push(1)
}

// watch 和 watchEffect 感兴趣可自行了解
watch(() => {})
watchEffect(() => {})

// ---------------------- vue 提供 ----------------------
// 组件挂载前
onBeforeMount(() => {})
// 组件挂载完成
onMounted(() => {})
// 组件卸载之前
onBeforeUnmount(() => {})
// 组件卸载完成
onUnmounted(() => {})
// 数据更新前
onBeforeUpdate(() => {})
// 数据更新后
onUpdated(() => {})

// ---------------------- uni-app提供 ----------------------
// 页面周期函数--监听页面加载 类比 vue2 created
onLoad(() => {})
// 页面周期函数--监听页面初次渲染完成 类比 vue2 mounted
onReady(() => {})
// 页面周期函数--监听页面显示(not-nvue)
onShow(() => {})
// 页面周期函数--监听页面隐藏
onHide(() => {})
// 页面周期函数--监听页面卸载
onUnload(() => {})
// 页面处理函数--监听用户下拉动作
// onPullDownRefresh(() => { uni.stopPullDownRefresh() })
// 页面处理函数--监听用户上拉触底
// onReachBottom(() => {})
// 页面处理函数--监听页面滚动(not-nvue)
// onPageScroll((event) => {})
// 页面处理函数--用户点击右上角分享
// onShareAppMessage((options) => {})

// 页面生命周期仅在page页面有效，而单独封装的组件中【页面周期无效】，但是Vue的生命周期依然有效 【Vue的生命周期在任何地方都是有效的】

// 组件要暴漏出去的方法，暴漏后通过父组件$ref才可以调用
defineExpose({
  demo,
})

</script>

<style lang="scss" scoped>
  // src/uni.scss 中定义的变量会自动注入，每个页面都可使用这些变量

  // 全局变量的使用 --window-top 和 --window-bottom
  padding-top: calc(var(--window-top) + 372rpx);
  padding-bottom: var(--window-bottom);
</style>
```

### 页面跳转

* uni.navigateTo() 保留当前页面，跳转到应用内的某个页面，使用uni.navigateBack可以返回到原页面。
* uni.redirectTo() 关闭当前页面，跳转到应用内的某个页面。
* uni.reLaunch() 关闭所有页面，打开到应用内的某个页面。
* uni.switchTab() 跳转到 tabBar 页面，并关闭其他所有非 tabBar 页面。跳转tabBar页面时只能用switchTab，使用navigateTo跳不过去

### 页面模块定义

* 页面需要在`src/pages.json`的`pages`数组中定义，记住`path`路径
* 登录PC端，在`系统配置/权限管理/模块管理`的对应模块功能中配置移动端链接地址为 '/' + `path`

### 常用功能参考示例

* 分页列表加载（页面触底加载下一页） 参考功能：`我的/版本更新`(代码地址：`src/pages/main/personal/version.vue`)
* 表单提交以及验证  参考功能：`我的/修改密码`(代码地址：`src/pages/main/personal/password.vue`)
* 图片上传  参考功能：`我的/基本信息`点击头像上传(代码地址：`src/pages/main/personal/info.vue`)

# IHN+扫一扫帮助说明
## 安生移动应用基于IHN+扫一扫二维码实现原理
### 应用外部调用
  IHN+扫码会根据二维码url跳转对应功能页面，同时校验url中域名是否可信，页面收到请求后验证必要参数，同时追加自动登录信息后跳转autologin页面，登录验证通过后根据配置的跳转path访问最终功能数据；
### 应用内部调用
  调用IHN+JSSDK的wx.scanQRCode()方法，方法会返回识别的url字符串，内部应用根据url的参数判断进行定向跳转即可；\
  具体方法参照https://hncoact.chng.com.cn:10443/api/doc#18019 \
  说明：安卓版本返回与API有些许出入，开发时请根据API实际返回进行处理；
## 1、生成二维码说明
以外包工器具二维码为例：\
生成的二维码内容（url字符串）为：
String qrContent = mobileUrl + "#/pages/main/a?g=" + gqjid;
 \
 其中：mobiuleUrl为常量配置里面的MOBILE_SERVICE_URL；（获取常量时注意最后是否有“/”，没有则需要手动添加，保证url正常）\
#/pages/main/a? 为固定值； \
g为标识位，各模块实际开发时需与陈勇成确认标识，避免出现重复； \
gqjid为需要查询的工器具数据主键； \

## 2、移动端扫码说明
1)提供上述1中的标识字段；\
2)提供扫码跳转业务的路径，即移动前端代码中pages.json的path;\
3)业务功能页面实现参数接收、展示、返回等功能；\
其中1）2）提交给陈勇成；3）自行实现。