项目简介

lxs 71f4e3eb10 2021/03/22 3 năm trước cách đây
readme.md 71f4e3eb10 2021/03/22 3 năm trước cách đây

readme.md

项目文档

大卫博士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 : []
	}
}
<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 目录

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

下单H5目前正和微店项目整合, 具体功能请期待整合完毕后添加

需特别注意

  1. H5项目代码里有些地方, 导航切换使用mixin, 请注意, 例如: pages/my-invite/my-invite

地址

大卫博士争霸赛小程序

争霸赛小程序代码存在大量冗余, 请注意一些问题

  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. 由于最初代码使用自定义导航栏, 所以页面代码中会出现如下代码:

    <custom-nav :title="pageTitle"></custom-nav>
    

    这种可直接使用原生导航栏, 即:设置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: 上传正式代码,请注释以上代码

地址

大卫博士争霸赛小程序-重构版

重构版争霸赛小程序未进行大量测试, 如要上线请先对照原版小程序就行完整测试

具体请点击地址查看项目 重构版-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个部分

  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()
      }
      <input
      	type="text"
      	ref="qrcode_text"
      	v-model="qrcode"
      	@focus="preventKeyBord"
      	@blur="onBlur"
      	@input="onInput"
      />
      
    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: 打包时请注意安卓证书, 如果证书丢失请自行生成安卓证书在线生成工具

地址

大卫博士手机扫码应用

手机版扫码应用同扫码枪应用相似, 请参考扫码枪应用

Ps: 手机版打包发行同样需要安卓证书

地址

大卫博士授权查询web

Ps: 此项目非常简单, 具体请查看代码

地址

大卫博士授权查询Pc

Ps: 此项目非常简单, 具体请查看代码

地址

瞳年小程序

Ps: 瞳年小程序由争霸赛小程序复制而来, 详情请参考争霸赛小程序

地址

瞳年后台

瞳年后台由大卫博士app后台拷贝修改而来, 具体请参考app后台

地址

田知花小程序(书画绘画小程序)

田知花小程序是在果酱社区开源小程序基础上修改的小程序

项目运行

  1. npm run dev
  2. 打开微信开发者工具->小程序->导入项目-> 选择src 文件夹

Ps: 本地测试请勿关闭 npm run dev

项目打包 npm run build

Ps: 此项目非常简单, 具体请查看源代码

地址

缴纳党费小程序

Ps: 此项目非常简单, 具体请查看源代码

地址