lxs 71f4e3eb10 2021/03/22 | 3 tahun lalu | |
---|---|---|
readme.md | 3 tahun lalu |
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 : [] } }
<el-button v-permit="1" :roles-permit="roles">财务审核</el-button> <el-button v-permit="[0,1,2]" :roles-permit="roles">导出</el-button>
在 directive/permission/permission.js 中定义 自定义指令 v-permit
判断路由meta中是否包含v-permit值, 来显示或隐藏元素
Ps: root角色同样具有所有权限指令
pages目录为主要修改目录, 具体功能请翻阅代码
大卫博士争霸赛后台与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: '' } } <el-form-item label="按钮权限"> <el-checkbox v-model="BP1">/上传管理[上传成功] / 调整数据 按钮</el-checkbox> <el-checkbox v-model="BP2">/报名管理 / 退款 按钮</el-checkbox> <el-checkbox v-model="BP3">/报名管理 / 取消比赛资格 按钮</el-checkbox> <el-checkbox v-model="BP4">/兑换管理 / 清除兑换记录 按钮</el-checkbox> </el-form-item> 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后台类似, 具体请翻阅代码
实战营后台与争霸赛后台使用相同模板, 具体功能参考争霸赛后台
下单H5目前正和微店项目整合, 具体功能请期待整合完毕后添加
接口封装调用, 请参考 common/js/ajax 和 pages/index/index 查看使用方法
页面代码中可能会同时使用 created/mounted/onLoad/onShow, 请注意
页面代码中会出现一些$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()
})
关于检测用户信号代码, 也请勿修改, 可能会出现问题, 如下
// App.vue
uni.onNetworkStatusChange(({ networkType, isConnected }) => {})
// pages/index/index
if ('wifi2g3g4g'.indexOf(this.networkType) !== -1) {}
由于最初代码使用自定义导航栏, 所以页面代码中会出现如下代码:
<custom-nav :title="pageTitle"></custom-nav>
这种可直接使用原生导航栏, 即:设置pages.json中style的属性 Ps: pages/course/list 页面比较特殊, 由于需要监听导航栏返回, 所以必须使用自定义导航栏
可能有些页面会出现以下代码
this.$scrollViewHeight('.content') //设置页面内 scroll view 的高度
这种写法请勿参考, 请使用flex布局
由于代码中根据人物等级判断较多, 请设置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: 上传正式代码,请注释以上代码
重构版争霸赛小程序未进行大量测试, 如要上线请先对照原版小程序就行完整测试
具体请点击地址查看项目 重构版-readme.md文件
实战营小程序参与较少, 这里只介绍实战营登录过程
实战营登录在原有基础上有 pages/index/index 登录页变为 pages/login/login
登录过程分为4类, 定义了 loginStatus, 0: 将要微信授权 , 1: 定位授权 , 2: 服务器登录 , 3: 服务器登录时判断需要手机号验证
<template v-if="!loginStatus"> <button open-type="getUserInfo" class="activityBtn" @getuserinfo="toGetUserInfo" > 登录查看详情 </button> </template> <template v-else> <view class="activityBtn" @click="toLoginProgress">登录查看详情</view> </template> 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)() } }
具体请翻阅代码
项目有原生HTML开发
项目分为4个部分
登录 index.html
用户登录,获取token,localStorage缓存token
商品信息 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为包含所属人信息对象
发货扫码 qrcode.html
发货扫码页面需要注意
因为保持连续扫码, 且扫码结果是填充input值的形式(onInput监听值), 所以需要是 input 一直保持焦点
onFocus() { this.$nextTick(() => { this.$refs.qrcode_text.focus() }) } onBlur() { this.onFocus() } <input type="text" ref="qrcode_text" v-model="qrcode" @focus="preventKeyBord" @blur="onBlur" @input="onInput" />
在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: 具体请结合页面效果查看代码切换商品所属人 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: 打包时请注意安卓证书, 如果证书丢失请自行生成安卓证书在线生成工具
手机版扫码应用同扫码枪应用相似, 请参考扫码枪应用
Ps: 手机版打包发行同样需要安卓证书
Ps: 此项目非常简单, 具体请查看代码
Ps: 此项目非常简单, 具体请查看代码
Ps: 瞳年小程序由争霸赛小程序复制而来, 详情请参考争霸赛小程序
瞳年后台由大卫博士app后台拷贝修改而来, 具体请参考app后台
田知花小程序是在果酱社区开源小程序基础上修改的小程序
Ps: 本地测试请勿关闭 npm run dev
Ps: 此项目非常简单, 具体请查看源代码
Ps: 此项目非常简单, 具体请查看源代码