# 项目文档
## 大卫博士app后台
### 项目运行
1. npm run dev 项目启动
2. npm run build:prod 项目打包
### 项目解构
1. vue.config.js 本地测试proxy 修改项目地址
2. .env.production 正式打包接口地址
3. src
### src 目录
1. api 文件夹 接口地址
2. assets 静态资源地址
3. components 组件
4. directive vue 自定义指令 v-directive
5. filterRouter 动态加载权限路由, PS: 重要,一般情况用不到
6. filters 公共方法 和 过滤器文件合集
7. icons 主要用于右侧操作栏图标
8. layout 后台框架 PS: 重要, 一般情况不会修改
9. pages 文件页面 PS: 重要
10. router 路由文件 PS: 重要
11. store 状态存储文件 PS: 重要
12. styles 样式文件 css / scss 文件
13. utils 公共方法
14. vendor excel 文件导出js
15. App.vue
16. main.js
17. permission.js 动态路由验证js PS: 重要 一般路由出错,在这里测试
18. setting.js 配置信息js
### 项目路由加载过程
> pages/backstage/role.vue 创建角色
> > 加载 router/auth.js 中 asyncRoutes import { asyncRoutes } from '@/router/auth'
> > 根据 asyncRoutes 进行深度遍历, 转换 生成 tree
> > 获取选择的路由, 上传服务器保存
> pages/backstage/account.vue 添加账户
> > 账户选择角色
> store/modules/user.js 用户登录
> > __getInfo()__ 方法获取用户信息, 包含角色信息, 路由信息
> > 将获取的权限路由 合并 router/auth.js 中 普通路由(defaultRoutes) 和 开发者路由(developerRoutes)
> permission.js
> > 将合并路由生成路由树进行页面加载
> > import { filterRouter } from '@/filterRouter'
> > accessRoutes = filterRouter(routes)
> > router.addRoutes(accessRoutes)
__Ps: 本质是将本地路由文件和服务器保存的路由进行比对加载__
__Ps: 一般路由报错结果均为本地路由和服务器路由不一致造成__
__Ps: store/modules/user.js 中 getInfo() 里,根据角色名判断:root角色直接使用本地路由__
__Ps: 所以出现路由错误时请登录root角色账户,修改错误角色账户__
### 按钮权限判断
> 根据 router/auth.js 中定义 meta 属性值 authList 和 buttonAuthList判断
```
mete: { authList: [ { name: '客服审核', value: 0 }, { name: '财务审核', value: 1 } ], buttonAuthList: [] }
```
> 进行路由加载相同过程, 唯一区别为: 在创建角色中, 选择authList中权限, 赋值 buttonAuthList 中
> > 例: 选择为财务审核权限, 即
```
buttonAuthList = [1]
```
> buttonAuthList 值为 authList 中 value 值构成的数组
> 在页面中添加权限判断, 具体请参考: pages/order/list.vue
```
data() {
return {
roles: this.$route.meta.buttonAuthList ? this.$route.meta.buttonAuthList : []
}
}
```
```
财务审核
导出
```
> 在 directive/permission/permission.js 中定义 自定义指令 v-permit
> > 判断路由meta中是否包含v-permit值, 来显示或隐藏元素
__Ps: root角色同样具有所有权限指令__
### pages 目录
__pages目录为主要修改目录, 具体功能请翻阅代码__
[地址](http://git.web.ximengnaikang.com:3000/daweiboshi-app/appadmin.git)
## 大卫博士争霸赛后台
__大卫博士争霸赛后台与H5后台使用相同后台模板, 具有相似性__
### 项目路由加载过程
__争霸赛后台路由加载和H5后台过程基本相同, 仅有部分区别__
> 在permission.js中
>> 争霸赛后台代码为:
```
const { routes } = await store.dispatch('user/getInfo')
const accessRoutes = await store.dispatch('permission/generateRoutes', routes)
router.addRoutes(accessRoutes)
```
>> H5后台为
```
const { routes } = await store.dispatch('user/getInfo')
import { filterRouter } from '@/filterRouter'
accessRoutes = filterRouter(routes)
```
> 其中争霸赛后台调用 store/modules/permission.js 里 generateRoutes 方法
> H5 后台为加载 filterRouter/index.js 里 filterRouter 方法
### 按钮权限
> 争霸赛按钮权限设置在 views/role.vue 下手动定义 4个值 BP1 - BP4, 并在上传时在 路由中push了一个数组
```
data() {
return {
BP1: '',
BP2: '',
BP3: '',
BP4: ''
}
}
/上传管理[上传成功] / 调整数据 按钮
/报名管理 / 退款 按钮
/报名管理 / 取消比赛资格 按钮
/兑换管理 / 清除兑换记录 按钮
routes.push([this.BP1 ? 'BP1' : '', this.BP2 ? 'BP2' : '', this.BP3 ? 'BP3' : '', this.BP4 ? 'BP4' : ''])
```
__routes为选择的路由数组__
> 在获取用户信息是将值赋值个 store.user.BP, 代码在 store/modules/user
```
const mutations = {
SET_BP(state, BP) {
state.BP = BP
}
}
commit('SET_BP', data.routes.some(e => Array.isArray(e)) ? data.routes.pop() : ['*'])
```
> 使用时判断值是否存在, 代码如: (上传权限) views/UploadManage.vue
```
v-if="$store.state.user.BP.includes('BP1') || $store.state.user.BP.includes('*')"
```
__其他功能与H5后台类似, 具体请翻阅代码__
[地址](http://git.web.ximengnaikang.com:3000/daweiboshi/admin.git)
## 大卫博士实战营后台
__实战营后台与争霸赛后台使用相同模板, 具体功能参考争霸赛后台__
[地址](http://git.web.ximengnaikang.com:3000/daweiboshi_szy/weappadmin.git)
## 大卫博士下单微信H5
__下单H5目前正和微店项目整合, 具体功能请期待整合完毕后添加__
### 需特别注意
1. H5项目代码里有些地方, 导航切换使用mixin, 请注意, 例如: pages/my-invite/my-invite
[地址](http://git.web.ximengnaikang.com:3000/daweiboshi-app/web-app.git)
## 大卫博士争霸赛小程序
### 争霸赛小程序代码存在大量冗余, 请注意一些问题
1. 接口封装调用, 请参考 common/js/ajax 和 pages/index/index 查看使用方法
2. 页面代码中可能会同时使用 created/mounted/onLoad/onShow, 请注意
3. 页面代码中会出现一些$on事件传递, 最好不要进行修改, 可能出现问题, 如下
```
// pages/index/index
uni.$on('MESSAGE', (m, d, p) => { //m 要提示的文字信息 d 文字信息出现的时常 p 文字信息出现的位置
this.$refs.toast.hover(m, d, p)
})
uni.$on('HIDEMESSAGE', () => { // 隐藏 文字提示
this.$refs.toast.hide()
})
```
4. 关于检测用户信号代码, 也请勿修改, 可能会出现问题, 如下
```
// App.vue
uni.onNetworkStatusChange(({ networkType, isConnected }) => {})
// pages/index/index
if ('wifi2g3g4g'.indexOf(this.networkType) !== -1) {}
```
5. 由于最初代码使用自定义导航栏, 所以页面代码中会出现如下代码:
```
```
__这种可直接使用原生导航栏, 即:设置pages.json中style的属性__
__Ps: pages/course/list 页面比较特殊, 由于需要监听导航栏返回, 所以必须使用自定义导航栏__
6. 可能有些页面会出现以下代码
```
this.$scrollViewHeight('.content') //设置页面内 scroll view 的高度
```
__这种写法请勿参考, 请使用flex布局__
7. 由于代码中根据人物等级判断较多, 请设置store.js模拟
```
// payload.cha_nickname = 'TEST1211313123'
// payload.signuped = false
// payload.score = 5000
// payload.type = 3
// payload.level_name = '代理公司'
// payload.money = 1
// payload.status = 1
```
__Ps: 上传正式代码,请注释以上代码__
[地址](http://git.web.ximengnaikang.com:3000/daweiboshi/weapp.git)
## 大卫博士争霸赛小程序-重构版
__重构版争霸赛小程序未进行大量测试, 如要上线请先对照原版小程序就行完整测试__
__具体请点击地址查看项目 [重构版-readme.md](http://git.web.ximengnaikang.com:3000/caokai/xcx_zhengbasai_reset/src/master/readme.md)文件__
[地址](http://git.web.ximengnaikang.com:3000/caokai/xcx_zhengbasai_reset.git)
## 大卫博士实战营小程序
__实战营小程序参与较少, 这里只介绍实战营登录过程__
### 实战营登录
> 实战营登录在原有基础上有 pages/index/index 登录页变为 pages/login/login
> 登录过程分为4类, 定义了 loginStatus, 0: 将要微信授权 , 1: 定位授权 , 2: 服务器登录 , 3: 服务器登录时判断需要手机号验证
```
登录查看详情
data() {
return {
loginStatus: 0
}
}
watch: {
// 简单登陆进度状态变化
loginStatus(s) {
this.toLoginProgress(s)
},
}
methods:{
toGetUserInfo() {}, // 获取微信授权, 成功时: ++this.loginStatus 0 -> 1
toGetUserLocation() {}, // 获取位置, 成功时: ++this.loginStatus 1 -> 2
toServerWxLogin() {}, // 服务器的登录, 根据返回code判断 code === 300 时, ++this.loginStatus 2 -> 3
toLoginProgress() {
let m = new Map([
[1, this.toGetUserLocation],
[2, this.toServerWxLogin],
[3, () => this.phoneLogin = true]
])
let s = this.loginStatus
return m.get(s)()
}
}
```
__具体请翻阅代码__
[地址](http://git.web.ximengnaikang.com:3000/daweiboshi_szy/weapp-online.git)
## 大卫博士扫码枪应用
__项目有原生HTML开发__
__项目分为4个部分__
> 1. 登录 index.html
> > 用户登录,获取token,localStorage缓存token
> 2. 商品信息 product.html
> > 扫描商品码获取商品信息
> > 此页面需要注意修改所属人时, 通过合并session缓存
```
checkSelectUser() {
let data = sessionStorage.getItem("user")
if(data) {
let user = JSON.parse(data)
this.productInfo = Object.assign(this.productInfo, user)
sessionStorage.removeItem("user")
this.$forceUpdate()
}
}
```
__Ps: this.productInfo为包含所属人信息对象__
> 3. 发货扫码 qrcode.html
> > 发货扫码页面需要注意
> > 1. 因为保持连续扫码, 且扫码结果是填充input值的形式(onInput监听值), 所以需要是 input 一直保持焦点
> >
```
onFocus() {
this.$nextTick(() => {
this.$refs.qrcode_text.focus()
})
}
onBlur() {
this.onFocus()
}
```
> > 2. 在onInput中解析值, 因为获取的值会包含上次输入值, 所以需要解析并转化
> >
```
onInput(e) {
let checkUrl = "fangw.jiuweiyun.cn"
let val = e.target.value // val: http://fangw.jiuweiyun.cn/d20210318xxx 格式
if(val.indexOf(checkUrl) === -1){ // 过滤非checkUrl网站的码
window.ELEMENT.Message.error('无效防伪码,已自动过滤')
return false
}
let _a = val.split('/')
let _v = _a[_a.length - 1]
if(!_v) { // 分割后如果不存在防伪码值, 结束
return false
}
this.old_code.push(_v) // 记录所有扫到的码
let i = this.filter_old_code.findIndex(v => v === _v) // 此防伪码是否只存在1个
if(i !== -1) { // 已经存在防伪码
this.filter_old_code.splice(i, 1) // 删除原来的
this.filter_code_type.splice(i, 1) // 删除原来的
Object.keys(this.goosQrcodeSelect).forEach(k => { // 查找在其他分类下(老人版. 简约版等)存不存在, 自己分类存不存在重复
let _i = this.goosQrcodeSelect[k].includes(_v) ? this.goosQrcodeSelect[k].findIndex(tv => tv === _v) : -1;
if(_i !== -1) {
if(+k !== this.good_select_id) { // 如果其他分类里有, 将其转换成当前分类
window.ELEMENT.Message.error(`防伪码由${this.goodList.find(({ id }) => +id === +k).good_name}替换为${this.goodList.find(({ id }) => +id === +this.good_select_id).good_name}`)
} else { // 如果当前分类有, 提示
window.ELEMENT.Message.error('此类型下防伪码已存在')
}
this.goosQrcodeSelect[k].splice(_i, 1) // 重原分类删除
}
})
}
this.goosQrcodeSelect[String(this.good_select_id)].push(_v) // 添加进新分类
this.filter_old_code.push(_v) // 添加到过滤码中
this.filter_code_type.push(this.goodList.find(_g => +_g.id === +this.good_select_id).good_name.replace('大卫博士', '')) // 添加到过滤类型中
this.qrcode = _v // input 显示当前码的值
}
```
>> __Ps: filter_old_code 和 filter_code_type相互对应, 如果新增就同时新增,如果删除就同时删除__
>> __Ps: 具体请结合页面效果查看代码__
> 4. 切换商品所属人 search.html
> > 通过页面参数id, 获取用户信息(参数可以为空)
> > 此页面需要注意: 选择的所属人将会转换成固定格式缓存进 session, 并返回 product.html 执行合并
```
let user = {
belong_user_mobile: data.phone,
belong_user_nickname: data.nickname,
belong_user_id: data.id,
belong_user_avatar: data.avatar
}
sessionStorage.setItem('user', JSON.stringify(user))
window.history.back()
```
__Ps: 因为合并执行 Object.assign(), 随意需要时user属性和 product.html 中 this.productInfo 属性保持一致__
__Ps: 打包时请注意安卓证书, 如果证书丢失请自行生成[安卓证书在线生成工具](http://www.appuploader.net/appuploader/keystore.php)__
[地址](http://git.web.ximengnaikang.com:3000/caokai/saomaqiang.git)
## 大卫博士手机扫码应用
__手机版扫码应用同扫码枪应用相识, 请参考扫码枪应用__
__Ps: 手机版打包发行同样需要安卓证书__
[地址](http://git.web.ximengnaikang.com:3000/caokai/saoma_mobile_app.git)
## 大卫博士授权查询web
__Ps: 此项目非常简单, 具体请查看代码__
[地址](http://git.web.ximengnaikang.com:3000/caokai/dwbs_chaxunshouquan.git)
## 大卫博士授权查询Pc
__Ps: 此项目非常简单, 具体请查看代码__
[地址](http://git.web.ximengnaikang.com:3000/caokai/shouquanchaxun_pc.git)
## 瞳年小程序
__Ps: 瞳年小程序由争霸赛小程序复制而来, 详情请参考争霸赛小程序__
[地址](http://git.web.ximengnaikang.com:3000/tongnian/weapp.git)
## 瞳年后台
__瞳年后台由大卫博士app后台拷贝修改而来, 具体请参考app后台__
[地址](http://git.web.ximengnaikang.com:3000/tongnian/admin-tongnian.git)
## 田知花小程序(书画绘画小程序)
__田知花小程序是在[果酱社区开源小程序](https://github.com/guojiangclub/miniprogram-ecommerce-open-source.git)基础上修改的小程序__
### 项目运行
1. npm run dev
2. 打开微信开发者工具->小程序->导入项目-> 选择src 文件夹
__Ps: 本地测试请勿关闭 npm run dev__
### 项目打包 npm run build
__Ps: 此项目非常简单, 具体请查看源代码__
[地址](http://git.web.ximengnaikang.com:3000/xmnk/course-weapp.git)
## 缴纳党费小程序
__Ps: 此项目非常简单, 具体请查看源代码__
[地址](http://git.web.ximengnaikang.com:3000/caokai/jiaonadangfei.git)