git 初始化

This commit is contained in:
陈昱达
2025-07-03 14:54:37 +08:00
parent deb57e7325
commit b54233b8a0
74 changed files with 15883 additions and 0 deletions

2
.browserslistrc Normal file
View File

@@ -0,0 +1,2 @@
> 1%
last 2 versions

6
.env Normal file
View File

@@ -0,0 +1,6 @@
# env
NODE_ENV = 'dev' // 如果是生产环境请记得切换为production
# flag
VUE_APP_FLAG='dev'
VUE_APP_ADMIN='http://192.168.1.1:7006/'

6
.env.dat Normal file
View File

@@ -0,0 +1,6 @@
# env
NODE_ENV = 'dat' // 如果是生产环境请记得切换为production
# flag
VUE_APP_FLAG='dat'
VUE_APP_ADMIN=

6
.env.dev Normal file
View File

@@ -0,0 +1,6 @@
# env
NODE_ENV = 'dev' // 如果是生产环境请记得切换为production
# flag
VUE_APP_FLAG='dev'
VUE_APP_ADMIN='http://192.168.1.1:7006/'

4
.eslintignore Normal file
View File

@@ -0,0 +1,4 @@
public
dist
node_modules
src/assets/js/utils/ebizTrack.es.js

27
.eslintrc.js Normal file
View File

@@ -0,0 +1,27 @@
const { endsWith } = require("core-js/core/string")
module.exports = {
root: true,
env: {
node: true
},
extends: ['plugin:vue/essential', '@vue/prettier'],
rules: {
//'off'或'0':关闭 'warn'或'1':警告 "error"或者"2":报错
// 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'error',
'no-console': 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'error',
'prettier/prettier': ['error',
{
singleQuote: true, //单引号
semi: false, //分号
printWidth: 120, //一行的字符数如果超过会进行换行默认为80
trailingComma: 'none', //是否使用尾逗号,有三个可选值"<none|es5|all>"
endOfLine: 'auto' //结尾是 \n \r \n\r auto win 和 mac 不一致
}
]
},
parserOptions: {
parser: 'babel-eslint'
}
}

31
.gitignore vendored Normal file
View File

@@ -0,0 +1,31 @@
.DS_Store
node_modules
package-lock.json
/dist
/target
/generate
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.settings
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*
*.iml
.classpath
.project
*.log
/sale
*.zip

7
.prettierrc Normal file
View File

@@ -0,0 +1,7 @@
{
"tabWidth": 2,
"semi": false,
"singleQuote": true,
"printWidth": 160,
"endOfLine": "auto"
}

1
.python-version Normal file
View File

@@ -0,0 +1 @@
2.7.18

183
README.md
View File

@@ -0,0 +1,183 @@
# basic-h5
## 介绍
- UI 框架使用[Vant](https://youzan.github.io/vant/#/zh-CN/intro),它是轻量、可靠的移动端 Vue 组件库
- 组件导入方式和 viewport 适配参考:[快速上手](https://youzan.github.io/vant/#/zh-CN/quickstart)
### 技术栈
Vue2 + Vue-Router + Axios + Vuex + Vant + Vue-Loader + Vue-Cli3.0 + ...
### 命名规范
- 组件名:大驼峰
- 方法名:小驼峰
- class 类名:连字符(a-b)
- 常量(const):全大写
- 变量(let):小驼峰
- 文件夹命名: 一律小写(只允许小写字母、中横杠-a-b)
- Vue 文件命名: 大驼峰式命名法,即每个单词的首字母大写 CamelCase.vue
- css,js,image 等文件命名:一律小写(css/js 文件使用中横杆-image 使用下划线\_)第三方除外
- 如条件允许: import 进来的变量名及 export 都采用大驼峰形式命名,如 import VueRouter from 'vue-router' 及 export default Common
```javascript
//什么叫“如条件允许”:比如我们需要
import routes from './routers/router'
const router = new VueRouter({
routes
})
//这种情况下routes可以用小写事实上上面的范例可以换一种写法
import Routes from './routers/router'
const router = new VueRouter({
routes: Routes
})
```
## wiki 文档
[wiki 参考文档](http://114.215.252.122:8090/pages/viewpage.action?pageId=13960243)
## 目录结构
```
.
├── node_modules // npm/yarn安装的项目依赖模块
├── public // 静态资源目录
│   ├── webViewBridge.js //跳转文件 与原生交互js
├── src // 源码目录
│   ├── api // 网络请求文件
│   │   ├── app // 基础工程网络请求文件
│   │   │   ├── user.js // 用户模块api请求
│   │   ├── example
│   │   │   └── *** // 示例模块api请求
│   ├── assets // 资源目录
│   │   ├── fonts // 字体文件
│   │   ├── images // 图片文件
│   │   | ├── app // 基础工程图片
│   │   | ├── 404_img // 404图片
│   │   ├── js
│   │   | ├── utils //工具类js
│   │   | | ├── get-url.js //根据设置获取请求url
│   │   | | ├── premission.js //权限控制
│   │   | | ├── request.js //拦截器
│   │   | | ├── validate.js //表单校验
│   │   | ├── vendor //第三方js
│   │   | ├── common.js //全局js方法
│   │   | ├── business-common.js //业务相关全局js方法
│   │   ├── sass
│   │   | └── common.scss // 样式出口文件
│   │   | └── vant-ui.scss // vant样式
│   │   | └── minix.scss // 样式配置
│   │   | └── transition.scss // 动画样式
│   │   | └── utils.scss // 工具样式
│   │   | └── variables.scss // 变量文件
│   ├── components // 全局组件
│   | ├── common //公共组件
│   │   | └── Jump // 跳转组件
│   ├── config // 配置文件
│   | ├── index.js // 环境配置
│   | ├── urlMap.js // api url配置
│   ├── filters
│   | ├── index.js // 过滤器
│   ├── router
│   | ├── app // 基础工程路由
│   | ├── example // 示例路由
│   | ├── index.js // 路由配置
│   ├── store
│   | ├── modules // 状态模块
│   | ├── getters.js // 配置getters
│   | ├── index.js // 引用vuex创建store
│   ├── views
│   | ├── app // 基础工程页面
│   | | ├── layout // layout导航栏、侧边栏、主窗口等
│   | | ├── login // 登录页面
│   | | ├── 404.vue // 404页面
│   | | ├── home.vue // 首页
│   | ├── example // 示例页面,不一一列举
│   ├── App.vue // 页面入口文件
│   ├── main.js // 程序入口文件,加载各种公共组件
├── tests // 测试相关文件
├── .env.dev // 开发环境配置
├── .env.test // 测试环境配置
├── .env.uat // 回归环境配置
├── .env.prd // 生产环境配置
├── .env.staging // staging环境配置
├── .eslintrc.js // eslint配置
├── babel.config.js // 转码配置
├── .prettierrc // prettier配置
├── jest.config.js // 测试配置
├── package.json // 安装包列表文件
├── postcss.config.js // 样式配置
├── vue.config.js // vue工程配置
.
```
## 项目运行
```bash
git clone http://112.124.100.131/base/ebiz-base-vue-h5.git
cd ebiz-base-vue-h5
yarn install推荐使用yarn
yarn serve开发环境
```
## 项目打包
```bash
# 测试环境打包
yarn run build:envName测试环境打包
# 线上环境打包
yarn run build:prd线上环境打包
```
## 预发环境打包预览、文件检查等
```bash
# 代码检查
yarn run lint
# 代码检查修复
yarn run lint:fix
#代码格式化
yarn run format
```
## 快速开始项目
1、src>>api 目录下创建项目所需 http 请求文件夹
2、src>>assets 目录下创建项目所需的 js image 文件夹,以及 scss 文件
3、src>>router 目录下创建所需路由文件夹
4、src>>store>>modules 目录下创建所需状态管理文件
##### [注:项目开始前请先配置 vscode 代码检查、格式化](http://115.29.19.195:8090/pages/viewpage.action?pageId=13960404)
## 主要功能点介绍
- http 请求文件
- 模块划分app 为基础工程模块、其他项目需另建文件夹
- 拦截器:超时设置、请求头加 token、统一处理异常、token 异常重新登录等
- mock 数据
- [工具 rap2](http://rap2.taobao.org/) 、[参考链接](http://115.29.19.195:8090/display/VUE/mock)
- 通过 config 文件夹下 urlMap.js配置 mock 接口请求
- 环境配置
- 在 config 文件夹下 index.js通过 process.env.NODE_ENV 对环境进行配置
- 在以下根目录env.xxx文件内配置相关环境变量
- env.dev 开发环境
- env.test 测试环境
- env.uat 回归环境
- env.prd 生产环境
- 跨域问题可通过后台解决,也可设置前端代理 proxy
- router
- 模块划分
- 路由拦截
- 路由懒加载
- 权限控制
- 可在 permission.js 里设置黑白名单

14
babel.config.js Normal file
View File

@@ -0,0 +1,14 @@
module.exports = {
presets: [['@vue/app', { useBuiltIns: 'entry' }]],
plugins: [
[
'import',
{
libraryName: 'vant',
libraryDirectory: 'es',
style: true
},
'vant'
]
]
}

16
jest.config.js Normal file
View File

@@ -0,0 +1,16 @@
module.exports = {
moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
transform: {
'^.+\\.vue$': 'vue-jest',
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
'^.+\\.jsx?$': 'babel-jest'
},
transformIgnorePatterns: ['/node_modules/'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1'
},
snapshotSerializers: ['jest-serializer-vue'],
testMatch: ['**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'],
testURL: 'http://localhost/',
watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-typeahead/testname']
}

56
package.json Normal file
View File

@@ -0,0 +1,56 @@
{
"name": "basic-h5",
"version": "1.0.0",
"description": "h5 basic",
"author": "ebiz-digits",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"build:dev": "vue-cli-service build --mode dev",
"dev": "vue-cli-service serve --mode dev",
"build:dat": "vue-cli-service build --mode dat",
"dat": "vue-cli-service serve --mode dat",
"lint": "vue-cli-service lint",
"lint:fix": "eslint --fix --ext .js,.vue src",
"format": "prettier --config ./.prettierrc --write \"src/**/*.js\" \"src/**/*.vue\"",
"test:unit": "vue-cli-service test:unit"
},
"dependencies": {
"@better-scroll/core": "^2.5.1",
"axios": "^0.19.0",
"core-js": "^2.6.5",
"eruda": "^2.11.3",
"fastclick": "^1.0.6",
"sass": "^1.69.3",
"v-viewer": "^1.6.4",
"vant": "^2.12.54",
"vue": "^2.6.10",
"vue-pdf": "^4.3.0",
"vue-quill-editor": "^3.0.6",
"vue-router": "^3.5.2",
"vuex": "^3.0.1",
"swiper": "^5.4.5",
"svg-sprite-loader": "^6.0.11",
"weixin-js-sdk": "^1.4.0-test"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.9.0",
"@vue/cli-plugin-eslint": "^3.9.0",
"@vue/cli-plugin-unit-jest": "^3.9.0",
"@vue/cli-service": "^3.9.0",
"@vue/eslint-config-prettier": "^4.0.1",
"@vue/test-utils": "1.0.0-beta.29",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "^10.0.1",
"babel-jest": "^23.6.0",
"babel-plugin-import": "^1.12.0",
"eslint": "^5.16.0",
"eslint-plugin-prettier": "^3.1.0",
"eslint-plugin-vue": "^5.0.0",
"postcss-px-to-viewport": "^1.1.1",
"sass-loader": "^7.1.0",
"vue-template-compiler": "^2.6.10",
"vee-validate": "^2.0.0-rc.25"
}
}

5
postcss.config.js Normal file
View File

@@ -0,0 +1,5 @@
module.exports = {
plugins: {
autoprefixer: {}
}
}

212
public/css/pdfh5.css Normal file

File diff suppressed because one or more lines are too long

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

24
public/index.html Normal file
View File

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<script>
this.globalThis || (this.globalThis = this)
</script>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta name="ccbpi" content="ebiz" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<link rel="stylesheet" href="css/pdfh5.css" />
</head>
<body>
<noscript>
<strong>We're sorry but h5-standard doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
<script>
</script>

68
src/App.vue Normal file
View File

@@ -0,0 +1,68 @@
<template>
<div id="app">
<!--实现路由切换动画-->
<transition :name="transitionName">
<RouterView />
</transition>
</div>
</template>
<script>
export default {
data() {
return {
transitionName: ''
}
},
watch: {
$route(to, from) {
//首次加载去除动画
if (!from.name) return
//动画方式
if (to.meta.index > from.meta.index) {
this.transitionName = 'slide-left'
} else if (to.meta.index === from.meta.index) {
this.transitionName = ''
} else {
this.transitionName = 'slide-right'
}
}
}
}
</script>
<style lang="scss">
@import '@/assets/sass/common.scss';
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
font-size: 14px;
}
.slide-left-leave-active,
.slide-left-enter-active,
.slide-right-leave-active,
.slide-right-enter-active {
position: absolute !important;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 99;
transition: all 0.2s ease;
}
.slide-left-enter,
.slide-right-leave-to {
transform: translateX(100%);
}
.slide-left-enter-to,
.slide-left-leave,
.slide-right-enter-to,
.slide-right-leave {
transform: translateX(0);
}
.slide-left-leave-to,
.slide-right-enter {
transform: translateX(-100%);
}
</style>

View File

@@ -0,0 +1,16 @@
import request from '@/assets/js/utils/request'
import getUrl from '@/assets/js/utils/get-url'
export default {
//
getUserInfo(data) {
return request({
url: getUrl('/api/userInfo', 'admin'),
method: 'get',
params: data,
headers: {
撒旦: '是说',
撒大苏打: window,
}
})
},
}

BIN
src/assets/images/404.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 871 KiB

View File

@@ -0,0 +1,14 @@
/*
* 业务公用js根据app具体场景写公用方法
*/
// 截取地址栏的参数值
function getUrlParam(data, href) {
let hrefUrl = href ? href : window.location.href
const reg = new RegExp('(^|&)' + data + '=([^&]*)(&|$)')
var r = hrefUrl.substr(1).match(reg)
if (r != null) {
return decodeURIComponent(r[2])
}
return ''
}
export default getUrlParam

492
src/assets/js/common.js Normal file
View File

@@ -0,0 +1,492 @@
/**
* @desc 扩展对象继承
* @param {Object} out 一个或多个对象
* @return {Object} 对象
*/
Object.extend = function(out) {
out = out || {}
for (var i = 1; i < arguments.length; i++) {
if (!arguments[i]) continue
for (var key in arguments[i]) {
if (arguments[i].hasOwnProperty(key)) out[key] = arguments[i][key]
}
}
return out
}
/**
* 对Date的扩展将 Date 转化为指定格式的String
* 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符,
* 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
* 例子:
* (new Date()).format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
* (new Date()).format("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18
*/
Date.prototype.format = function(format) {
let args = {
'M+': this.getMonth() + 1,
'd+': this.getDate(),
'h+': this.getHours(),
'm+': this.getMinutes(),
's+': this.getSeconds(),
'q+': Math.floor((this.getMonth() + 3) / 3), // quarter
S: this.getMilliseconds()
}
if (/(y+)/.test(format)) format = format.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length))
for (var i in args) {
var n = args[i]
if (new RegExp('(' + i + ')').test(format))
format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? n : ('00' + n).substr(('' + n).length))
}
return format
}
export default {
/**
* @desc 判断对象是否为空
* @param {Object} o 对象
* @return {Boolean}
*/
isEmptyObject(o = {}) {
let flag = true
for (let k in o) {
if (k) {
flag = false
break
}
}
return flag
},
//获取当前url的所有参数
getParams() {
let url = location.href.split('?')[1]
if (!url) {
return {}
}
let params = {}
let arr = url.indexOf('&') != -1 ? url.split('&') : [url]
arr.map(item => {
params[item.split('=')[0]] = item.split('=')[1]
})
return params
},
// 时间格式转化
formatDate(date, fmt) {
date = date == undefined ? new Date() : date
date = typeof date == 'number' ? new Date(date) : date
fmt = fmt || 'yyyy-MM-dd HH:mm:ss'
var obj = {
y: date.getFullYear(), // 年份注意必须用getFullYear
M: date.getMonth() + 1, // 月份注意是从0-11
d: date.getDate(), // 日期
q: Math.floor((date.getMonth() + 3) / 3), // 季度
w: date.getDay(), // 星期注意是0-6
H: date.getHours(), // 24小时制
h: date.getHours() % 12 == 0 ? 12 : date.getHours() % 12, // 12小时制
m: date.getMinutes(), // 分钟
s: date.getSeconds(), // 秒
S: date.getMilliseconds() // 毫秒
}
var week = ['天', '一', '二', '三', '四', '五', '六']
for (var i in obj) {
fmt = fmt.replace(new RegExp(i + '+', 'g'), function(m) {
var val = obj[i] + ''
if (i == 'w') return (m.length > 2 ? '星期' : '周') + week[val]
for (var j = 0, len = val.length; j < m.length - len; j++) val = '0' + val
return m.length == 1 ? val : val.substring(val.length - m.length)
})
}
return fmt
},
/**
* @description 去除前后空格
* @param {String} 值
* @return {String}
*/
trim(val) {
return val.replace(/(^\s*)|(\s*$)/g, '')
},
/**
* @desc 获取 cookie
* @param {String}
* @return {*}
*/
getCookie(name) {
let rs = ''
var nameStr = name + '='
var ca = document.cookie.split(';')
for (var i = 0; i < ca.length; i++) {
var c = ca[i]
while (c.charAt(0) == ' ') {
c = c.substring(1)
}
if (c.indexOf(nameStr) != -1) {
rs = this._string2json(c.substring(nameStr.length, c.length))
}
}
return rs
},
/**
* @desc 设置 cookie
* @param {String} name 名称
* @param {*} value 值
* @param {Number} hours 时长
*/
setCookie(name, value, hours) {
let str = name + '=' + this._json2string(value)
if (hours && hours > 0) {
var date = new Date()
date.setTime(date.getTime() + hours * 3600 * 1000)
str += '; expires=' + date.toUTCString()
}
document.cookie = str
},
/**
* @desc 清除 cookie
* @param {String} 名称
*/
delCookie(name) {
var date = new Date()
date.setTime(date.getTime() - 10000)
document.cookie = name + '=a; expires=' + date.toGMTString()
},
/**
* @desc 获取 localStorage 中指定的变量
* @param {String} name 名称
* @return {*} rs
*/
getStorage(name) {
return this._string2json(window.localStorage[name])
},
/**
* @desc 设置或添加 localStorage 中指定的变量
* @param {String} name 名称
*/
setStorage(name, value) {
window.localStorage[name] = this._json2string(value)
},
/**
* @desc 删除 localStorage 中指定的变量
* @param {String} name 名称
*/
delStorage(name) {
window.localStorage.removeItem(name)
},
/**
* @desc json转string
* @param {*} value 值
* @return {*} value 值
*/
_json2string(value) {
return JSON.stringify(value)
},
/**
* @desc string转json
* @param {*} value 值
* @return {*} value 值
*/
_string2json(value) {
try {
value = JSON.parse(value)
} catch (e) {
//console.log(e)
}
return value
},
/**
*@desc 只能输入单词字符
*@param { String } value
*/
character(value) {
if (value) {
value = value.replace(/[^A-Za-z0-9]/g, '')
}
return value
},
// 保留小数位替代Number.toFixed()方法针对于某些数据16.455)不能做到四舍五入
toFixed(value, num = 0) {
let pos = value.toString().indexOf('.')
let decimalPlaces = value.toString().length - pos - 1
let intValue = value * Math.pow(10, decimalPlaces)
let divisor1 = Math.pow(10, decimalPlaces - num)
let divisor2 = Math.pow(10, num)
return Math.round(intValue / divisor1) / divisor2
},
/**
* 如果是小数则保留小数位,默认两位
* @param {[type]} value [description]
* @param {Number} num [description]
* @return {[type]} [description]
*/
toFloatFixed(value, num = 2) {
let values = Number(value)
if (values) {
if (/^\d+\.\d+/.test(values)) {
return this.toFixed(values, num)
} else {
return this.toFixed(values)
}
}
return value
},
/**
* 获取设备类型
*/
device() {
let ua = navigator.userAgent
return {
isChrome: ua.match(/Chrome\/([\d.]+)/) || ua.match(/CriOS\/([\d.]+)/),
isAndroid: ua.match(/(Android);?[\s/]+([\d.]+)?/),
isIphone: ua.indexOf('iPhone') != -1,
isWeixin: ua.match(/MicroMessenger/i)
//isTraining: ua.match(/training/i) //当前app标识按照项目来定
}
},
isIOS() {
var u = navigator.userAgent
var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) //ios终端
return isiOS
},
/**
* 设置title
*/
setTitle(title) {
let device = this.device()
if (device.isIphone && device.isWeixin) {
document.title = title
var i = document.createElement('iframe')
i.src = '/favicon.ico'
i.style.display = 'none'
i.onload = function() {
setTimeout(function() {
i.remove()
}, 9)
}
document.body.appendChild(i)
} else {
document.title = title
}
},
// 字符省略
ellipsis(value = '', num = -1) {
if (value) {
let str = ''
if (num > 0 && value.length > num) {
str = '...'
}
return value.slice(0, num) + str
}
return value
},
/**
* 替换字符串具体位置字符
* @param {String} str 目标字符串
* @param {String} char 字符
* @param {Number} start 数组开始索引
* @param {Number} end 数组结束索引
* @return {[type]} [description]
*/
replaceChar(str = '', char = '*', start = 0, end) {
let list = []
if (str) {
list = str.split('')
let len = list.length
start = start > 0 ? (start <= len ? start : len) : 0
end = end ? (end > start ? end : start) : len
for (let i = 0; i < len; i++) {
if (i >= start && i < end) {
list[i] = char
}
}
}
return list.join('')
},
/**
* @desc只能输入整数
* @param
value 操作数值
max 最大值
**/
intOnly(value, max = Infinity, min = 0) {
if (value) {
let regular0 = /^0{1,}$/
if (regular0.test(value)) {
// 如果输入1个0以上去除掉
value = value.replace(/^0{1,}$/, '')
}
if (/[^0-9]*$/.test(value)) {
value = value.replace(/\D/g, '')
} else {
if (value > max) value = value.substr(0, value.length - 1)
if (value < min) value = min
}
}
return value
},
// 数组去重
unrepeat(arr) {
if (arr instanceof Array) {
let hash = {}
let rsArr = []
let len = arr.length
// eslint-disable-next-line no-unused-vars
let type = ''
for (let i = 0; i < len; i++) {
if (typeof arr[i] == 'string') {
type = 'string'
}
if (!hash[arr[i]]) {
hash[arr[i]] = arr[i]
rsArr.push(arr[i])
}
}
return rsArr
}
},
// 一层对象数组去重
unrepeatObj(arr, key) {
if (arr instanceof Array) {
let hash = {}
let rsArr = []
let len = arr.length
// eslint-disable-next-line no-unused-vars
let type = ''
for (let i = 0; i < len; i++) {
if (typeof arr[i] == 'string') {
type = 'string'
}
if (!hash[arr[i][key]]) {
hash[arr[i][key]] = arr[i]
rsArr.push(arr[i])
}
}
return rsArr
}
},
//距离转换
m2km(value) {
if (value < 1000) return value + 'm'
else if (value >= 1000 && value <= 20000) return (value / 1000).toFixed(1) + 'km'
else if (value >= 2000) return '>20km'
return value
},
/**
* 获取App信息
*/
detectApp() {
var ua = navigator.userAgent
//RegExp.$1; RegExp.$2; RegExp.$3;
//var info = ua.match(/(CarmeApp)\s*[v]*(\d+\.\d+\.\d+)\s*\/\s*(IOS|Android)/i)
ua.match(/(CarmeApp)\s*[v]*(\d+\.\d+\.\d+)\s*\/\s*(IOS|Android)/i)
return {
appName: RegExp.$1,
appVersion: RegExp.$2,
appOS: RegExp.$3
}
},
/**
* 手机号脱敏
* @param {String} phoneNo
* @returns
*/
desensitizePhoneNo(phoneNo) {
if (!phoneNo || phoneNo.length !== 11) {
return 'Invalid phone number'
}
return phoneNo.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
},
/**
* 证件号码脱敏
* @param {String} idType 证件类型 B0101:, 其他:其他
* @param {String} idNo 证件号码
* @return {String} 脱敏后的证件号码 身份证号显示前6位、后3位其余用*代替其余账号显示第1位后3位其余用*代替
*/
desensitizeIdNo(idType, idNo) {
if (!idNo) {
return 'Invalid id number'
}
console.log('idType', idType)
if (this.isIdCard(idType)) {
// 身份证号显示前6位、后3位其余用*代替
return idNo.replace(/^(.{6})(?:\w+)(.{3})$/, '$1********$2')
} else {
// 其余账号显示第1位后3位其余用*代替
return idNo.replace(/^(.)(?:\w+)(.{3})$/, '$1********$2')
}
},
/**
* 证件类型是否是身份证
* @param {String} idType
* @return {Boolean}
*/
isIdCard(idType) {
return idType === 'B0101'
},
/**
* 证件类型是否是户口簿
* @param {String} idType
* @return {Boolean}
*/
isHouseholdRegistration(idType) {
return idType === 'B0200'
},
/**
* @desc 获取url中的参数
* @param {String} url
* @return {Object} 参数对象
*/
getParamsFromUrl(url) {
console.log('getParamsFromUrl url', url)
let params = {}
if (!url) {
return params
}
if (url.indexOf('?') == -1) {
return params
}
if (url.indexOf('?') == url.length - 1) {
return params
}
let arr = url.split('?')[1].split('&')
console.log('getParamsFromUrl', arr)
arr.map(item => {
params[item.split('=')[0]] = item.split('=')[1]
})
return params
}
}

View File

@@ -0,0 +1,34 @@
export default {
formatLabelFun: (value, dir) => {
let sexDataMaps = [{ label: '男', value: '0' }, { label: '女', value: '1' }]
let arr = eval(`${dir}DataMaps`)
let filterData = arr.filter(item => item.value == value)[0]
if (filterData) {
return filterData.label
} else {
return value
}
},
formatList: (dir) => {
let maps = {}
maps['sex'] = [{ label: '男', value: '0' }, { label: '女', value: '1' }]
return maps[dir];
},
// formatOptionsFun 固定生成
// 用于转换list 增加自己想要的字段
formatOptionsFun: function (array = [{label: 'name', formatLabel: 'label'}], data) {
return data.map(item => {
array.map(format => {
if (item[format.label]) {
item[format.formatLabel ? format.formatLabel : 'label'] = item[format.label]
}
if (item.children && item.children.length > 0) {
item.children = this.formatOptionsFun(array, item.children)
}
})
return item
})
}
}

View File

@@ -0,0 +1,44 @@
export default {
// 默认存在的校验
mobile: () => {
return {
message: () => {
return '请输入正确的手机号'
},
validator: (value) => {
return value.length === 11 && /^((12|13|14|15|16|17|18|19)[0-9]{1}\d{8})$/.test(value)
}
}
},
required: () => {
return {
message: (file) => {
return file + '不能为空'
},
validator: (value) => {
return value ? true : false
}
}
},
idNo: () => {
return {
message: () => {
return "身份证号码错误,请重新填写"
},
validator: (value) => {
let id = /^[1-9][0-9]{5}(19|20)[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}([0-9]|x|X)$/;
return id.test(value)
}
}
},
phone: () => {
return {
message: () => {
return "手机号不正确"
},
validator: (value) => {
return value.length === 11 && /^((12|13|14|15|16|17|18|19)[0-9]{1}\d{8})$/.test(value)
}
}
},
}

View File

@@ -0,0 +1,24 @@
import Vue from 'vue'
import VeeValidate, { Validator } from 'vee-validate'
import zh_CN from 'vee-validate/dist/locale/zh_CN'
import validateItem from './generatedValidateItem'
// 解决fileds重复定义报错的问题
// 解决fileds重复定义报错的问题
const config = {
errorBagName: 'errorBags', // change if property conflicts.
fieldsBagName: 'fieldBags'
}
Vue.use(VeeValidate, config)
Validator.locale = 'zh_CN'
Validator.localize('zh_CN', {
messages: zh_CN.messages
})
/*自定义校验规则*/
for (let item in validateItem) {
console.log(item)
Validator.extend(item, {
getMessage: validateItem[item]().message,
validate: validateItem[item]().validator
})
}

View File

@@ -0,0 +1,22 @@
//在组件销毁时应当删除订阅的事件,避免挂载多个事件
class Bus {
constructor() {
this.callback = {}
}
on(name, val) {
this.callback[name] = this.callback[name] || []
this.callback[name].push(val)
}
async emit(name, args) {
if (this.callback[name]) {
return await Promise.all(this.callback[name].map(cb => cb(args)))
}
}
off(name) {
if (this.callback[name]) {
delete this.callback[name]
}
}
}
export default Bus

View File

@@ -0,0 +1,24 @@
import FastClick from 'fastclick'
//解决ios移动端input调软键盘问题
let isIphone = navigator.userAgent.indexOf('iPhone') != -1
if (isIphone) {
FastClick.prototype.focus = function(targetElement) {
let length
if (
isIphone &&
targetElement.setSelectionRange &&
targetElement.type.indexOf('date') !== 0 &&
targetElement.type !== 'time' &&
targetElement.type !== 'month' &&
targetElement.type !== 'email'
) {
length = targetElement.value.length
targetElement.setSelectionRange(length, length)
/*修复bug ios 11.3不弹出键盘,这里加上聚焦代码,让其强制聚焦弹出键盘*/
targetElement.focus()
} else {
targetElement.focus()
}
}
}

View File

@@ -0,0 +1,9 @@
import config from '@/config'
import urlMap from '@/config/urlMap'
export default function getUrl(url, domainType = 'admin') {
let domain = ''
if (domainType === 'admin') {
domain = config.admin
} return domain + url
}

View File

@@ -0,0 +1,24 @@
//权限控制
import router from '@/router'
export function permission() {
router.beforeEach(async (to, from, next) => {
document.title = to.meta.title
//判断是否登录
let token = localStorage.token
if (!token) {
localStorage.token = ''
//无token判断是否需要登录
if (to.meta.auth) {
next(`/login?redirect=${to.path}`)
} else {
next()
}
} else {
if (to.path === '/login') {
next({ path: '/' })
} else {
next()
}
}
})
}

View File

@@ -0,0 +1,72 @@
import axios from 'axios'
import { Dialog, Toast } from 'vant'
// 创建axios实例
const service = axios.create({
timeout: 66666666 // 请求超时时间
})
// request拦截器
service.interceptors.request.use(
config => {
Toast.loading()
config.headers['token'] = window.localStorage.getItem('token')
return config
},
error => {
Toast.loading().clear()
// Do something with request error
Promise.reject(error)
}
)
// respone拦截器
service.interceptors.response.use(
response => {
Toast.loading().clear()
const res = response.data
if (typeof res.sts !== 'undefined') {
return res
}
if (res.code === '000' || res.code === '999') {
return res
}
console.log('response', res)
if (res.content && res.content.code != 0) {
// if(!)
//noFail 表示不需要统一处理错误提示,需要给调用接口返回
if (!response.config.noFail) {
if (res.content.code == 40001) {
Dialog.confirm({
confirmButtonText: '重新登录',
message: '你已被登出,可以取消继续留在该页面,或者重新登录'
}).then(() => {
//eslint-disable-next-line
EWebBridge.webCallAppInJs('bridge', { flag: 'login' })
})
} else {
console.log('res.content.message', res.content.message)
Toast(res.content.message ? res.content.message : '未知异常')
}
return Promise.reject(res)
} else {
return res.content
}
} else {
Toast.clear()
if (res.content) {
return res.content
} else {
Toast({
icon: 'warning-o',
message: '接口服务异常'
})
}
}
},
error => {
Toast(error.message ? error.message : '未知异常')
return Promise.reject(error)
}
)
export default service

View File

@@ -0,0 +1,50 @@
@import './variables.scss';
@import './vant-ui.scss';
@import './mixin.scss';
@import './utils.scss';
@import './transition.scss';
@import './public.scss';
* {
margin: 0;
padding: 0;
touch-action: pan-y;
}
body {
min-height: 100%;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
background-color: rgb(245, 245, 245);
}
html {
height: 100%;
}
a,
a:focus,
a:hover {
cursor: pointer;
color: inherit;
outline: none;
text-decoration: none;
}
// 宽度设置
@include set-width($width-list);
// 宽度设置
@include set-height($width-list);
// 间距设置
@include set-distance($distance-class-list, $distance-list);
//圆角弧度设置
@include set-radius($radius);
//透明度设置
@include set-opacity($opacity);
//字体设置
@include set-fontSize($font-size-list);
//间距设置遍历间距class 和 倍数, 用于padding和margin
//@include set-distance($spacing-class-list, $spacing-multiple-list);

353
src/assets/sass/mixin.scss Normal file
View File

@@ -0,0 +1,353 @@
@mixin clearfix {
&:after {
content: "";
display: table;
clear: both;
}
}
@mixin scrollBar {
&::-webkit-scrollbar-track-piece {
background: #d3dce6;
}
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: #99a9bf;
border-radius: 20px;
}
}
@mixin relative {
position: relative;
width: 100%;
height: 100%;
}
// 设置宽度
@mixin set-width($width-list) {
@each $size in $width-list {
.w#{$size} {
width: #{$size}px !important;
}
}
}
// 设置宽度
@mixin set-fontSize($font-size-list) {
@each $size in $font-size-list {
.fs#{$size} {
font-size: #{$size}px !important;
}
}
}
// 设置高度
@mixin set-height($width-list) {
@each $size in $width-list {
.h#{$size} {
height: #{$size}px !important;
}
}
}
// 设置字体宽度
@mixin set-height($font-weight-list) {
@each $size in $font-weight-list {
.fw#{$size} {
font-weight: #{$size}px !important;
}
}
}
// 设置圆角弧度
@mixin set-radius($radius) {
@each $size in $radius {
.radius#{$size} {
border-radius: #{$size}px !important;
}
}
}
// 设置透明度
@mixin set-opacity($opacity) {
@each $size in $opacity {
.opacity#{$size*10} {
opacity: #{$size} !important;
}
}
}
// 外边距
@mixin margin($size) {
margin: $size !important;
}
@mixin margin-vertical($size) {
margin-top: $size !important;
margin-bottom: $size !important;
}
@mixin margin-horizontal($size) {
margin-left: $size !important;
margin-right: $size !important;
}
@mixin margin-top($size) {
margin-top: $size !important;
}
@mixin margin-left($size) {
margin-left: $size !important;
}
@mixin margin-bottom($size) {
margin-bottom: $size !important;
}
@mixin margin-right($size) {
margin-right: $size !important;
}
// 内边距
@mixin padding($size) {
padding: $size !important;
}
@mixin padding-vertical($size) {
padding-top: $size !important;
padding-bottom: $size !important;
}
@mixin padding-horizontal($size) {
padding-left: $size !important;
padding-right: $size !important;
}
@mixin padding-top($size) {
padding-top: $size !important;
}
@mixin padding-left($size) {
padding-left: $size !important;
}
@mixin padding-bottom($size) {
padding-bottom: $size !important;
}
@mixin padding-right($size) {
padding-right: $size !important;
}
@mixin top($size) {
top: $size !important;
}
@mixin left($size) {
left: $size !important;
}
@mixin right($size) {
right: $size !important;
}
@mixin bottom($size) {
bottom: $size !important;
}
// 设置内外边距
@mixin set-distance($distance-class-list, $distance-list) {
@each $class-name in $distance-class-list {
@each $size in $distance-list {
.#{$class-name}#{$size} {
@if $class-name == m {
@include margin(#{$size}px);
}
@if $class-name == mv {
@include margin-vertical(#{$size}px);
}
@if $class-name ==mh {
@include margin-horizontal(#{$size}px);
}
@if $class-name ==mt {
@include margin-top(#{$size}px);
}
@if $class-name ==ml {
@include margin-left(#{$size}px);
}
@if $class-name ==mr {
@include margin-right(#{$size}px);
}
@if $class-name ==mb {
@include margin-bottom(#{$size}px);
}
@if $class-name ==p {
@include padding(#{$size}px);
}
@if $class-name ==pv {
@include padding-vertical(#{$size}px);
}
@if $class-name ==ph {
@include padding-horizontal(#{$size}px);
}
@if $class-name ==pt {
@include padding-top(#{$size}px);
}
@if $class-name ==pl {
@include padding-left(#{$size}px);
}
@if $class-name ==pr {
@include padding-right(#{$size}px);
}
@if $class-name ==pb {
@include padding-bottom(#{$size}px);
}
@if $class-name ==top {
@include top(#{$size}px);
}
@if $class-name ==left {
@include left(#{$size}px);
}
@if $class-name ==right {
@include right(#{$size}px);
}
@if $class-name ==bottom {
@include bottom(#{$size}px);
}
}
}
}
}
//// 设置内外边距
//@mixin set-distance($class-list, $multiple-list){
// @each $class in $class-list {
// @each $multiple in $multiple-list {
// @include generate-spacing($class, $multiple);
// }
// }
//}
//
//// 根据倍数设置内外间距 class可以为 m, mv, mh, mt, ml, mr, mb, p, pv, ph, pt, pl, pr, pb
//@mixin generate-spacing($class, $multiple) {
// $property: null;
// $directions: (
// );
//
//// 根据class首字母判断是margin还是padding
//@if str-index($class, 'm') {
// $property: margin;
//}
//
//@else if str-index($class, 'p') {
// $property: padding;
//}
//
//@if str-index($class, 'v') {
// $directions: (
// top,
// bottom
// );
//}
//
//@else if str-index($class, 'h') {
// $directions: (
// left,
// right
// );
//}
//
//@else if str-index($class, 't') {
// $directions: (
// top
// );
//}
//
//@else if str-index($class, 'b') {
// $directions: (
// bottom
// );
//}
//
//@else if str-index($class, 'l') {
// $directions: (
// left
// );
//}
//
//@else if str-index($class, 'r') {
// $directions: (
// right
// );
//}
//
//@else {
// $directions: (
// top,
// right,
// bottom,
// left
// );
//}
//
//// 生成对应的 class
//@each $direction in $directions {
// .#{$class}-#{str-replace($multiple + 'x', '.', '_')} {
// #{$property}-#{$direction}: $base-spacing * $multiple;
// }
//}
//}
// 把间距class中名字中带 . 的替换成 _避免class名字带点引起歧义和风险
@function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
@if($index) {
@return str-slice($string, 1, $index - 1)+'_'+str-slice($string, $index + 1);
}
@return $string;
}
//单行省略
@mixin text-overflow() {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
@mixin horizontal-margin($size) {
margin-left: $size ;
margin-right: $size
}
@mixin border-radius($radius) {
border-radius: $radius;
}
@mixin btn-sizes($btn-height, $font-size) {
height: $btn-height;
font-size: $font-size;
//@include border-radius($btn-height/2);
}

View File

@@ -0,0 +1,36 @@
body{
background-color: #EEEEEE!important;
}
.van-cell-group--inset{
margin:0 10px!important;
}
.van-cell-group__title--inset{
padding:15px 15px 5px 15px!important;
}
.button-group-container{
display: flex;
align-items: center;
justify-content: space-between;
}
#app .van-col{
margin: 5px 0;
}
#app .button-group-container{
margin: 5px!important;
.van-button{
margin: unset;
}
}
#app .van-button + .van-button{
margin-left: 5px;
}
#app .van-cell__title{
color: #646566;
}
.flexPrice{
display: flex; justify-content: space-between; justify-items: center; align-items: center; width: 100%
}
.van-tag+.van-tag{margin-left: 5px;}

View File

@@ -0,0 +1,48 @@
// global transition css
/* fade */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.28s;
}
.fade-enter,
.fade-leave-active {
opacity: 0;
}
/* fade-transform */
.fade-transform-leave-active,
.fade-transform-enter-active {
transition: all .5s;
}
.fade-transform-enter {
opacity: 0;
transform: translateX(-30px);
}
.fade-transform-leave-to {
opacity: 0;
transform: translateX(30px);
}
/* breadcrumb transition */
.breadcrumb-enter-active,
.breadcrumb-leave-active {
transition: all .5s;
}
.breadcrumb-enter,
.breadcrumb-leave-active {
opacity: 0;
transform: translateX(20px);
}
.breadcrumb-move {
transition: all .5s;
}
.breadcrumb-leave-active {
position: absolute;
}

665
src/assets/sass/utils.scss Normal file
View File

@@ -0,0 +1,665 @@
//浮动、清除浮动
.clearfix {
@include clearfix;
}
.fl {
float: left;
}
.fr {
float: right;
}
//字体相关
.fs12 {
font-size: $font-size-small;
}
.fs14 {
font-size: $font-size-base;
}
.fs16 {
font-size: $font-size-large;
}
.fs18 {
font-size: $font-size-xl;
}
.fw600 {
font-weight: 600 !important;
}
.fwb {
font-weight: bold !important;
}
.ffP {
font-family: PingFangSC-Regular, PingFang SC;
;
}
// 宽度
.w36 {
width: 36px;
}
//布局定位
.relative {
position: relative;
}
.absolute {
position: absolute;
}
.fixed {
position: fixed;
}
.mh-auto {
margin-left: auto;
margin-right: auto;
}
.hide {
visibility: hidden !important;
}
.hidden {
display: none !important;
}
.flex {
display: -webkit-flex !important;
display: flex !important;
}
.flex1 {
flex: 1;
}
.inline-flex {
display: -webkit-inline-flex;
display: inline-flex;
}
.inline-b {
display: inline-block !important;
}
.justify-content-c {
justify-content: center;
}
.justify-content-a {
justify-content: space-around;
}
.justify-content-e {
justify-content: space-evenly;
}
.justify-content-fs {
justify-content: flex-start;
}
.justify-content-fe {
justify-content: flex-end;
}
.justify-content-b {
justify-content: space-between;
}
.align-items-c {
align-items: center;
}
.flex-c {
display: flex;
align-items: center;
justify-content: center;
}
.flex-column {
display: flex;
flex-direction: column;
}
.flex-column-b {
@extend .flex-column;
justify-content: space-between;
height: 100vh;
}
.flex-column-c {
@extend .flex-column;
align-items: center;
}
.flex-row {
display: flex;
flex-direction: row;
}
.flex-row-c {
@extend .flex-row;
align-items: center;
}
.flex-row-e {
@extend .flex-row;
//justify-content: flex-end;
//align-items: center;
}
.flex-row-b {
@extend .flex-row;
align-items: center;
justify-content: space-between;
}
// 常用文字颜色
.c-gray-base {
color: $gray-base !important;
}
.c-gray-dark {
color: $gray-dark !important;
}
.c-gray-darker {
color: $gray-darker !important;
}
.gray-darker-cell {
color: $gray-darker-cell !important;
}
// 文字位置设置
.text-left {
text-align: left !important;
.van-field__control {
text-align: left !important;
}
}
.text-right {
text-align: right !important;
}
.text-center {
text-align: center !important;
}
.text-underline {
text-decoration: underline;
}
.text-indent {
text-indent: 20px;
}
// 垂直方向对齐方式
.v-top {
vertical-align: top !important;
}
.v-middle {
vertical-align: middle !important;
}
.v-bottom {
vertical-align: bottom !important;
}
.v-baseline {
vertical-align: baseline !important;
}
//单行省略
.ellipsis {
@include text-overflow;
}
//颜色
.green {
color: $green !important;
}
.red {
color: $red !important;
}
.reddish {
color: #E8443C !important;
}
.yellow {
color: $yellow !important;
}
.gray {
color: $gray !important;
}
.white {
color: $white !important;
}
.orange {
color: $orange !important;
}
.blue {
color: $blue !important;
}
.bg-black {
background: $black !important;
}
.bg-white {
background: $white !important;
}
.bg-orange {
background-color: $orange !important;
}
.bg-none {
background-color: transparent !important;
}
.bg-primary {
background-color: $primary-color !important;
}
.bg-header-notice {
background-color: $bg-color-header-notice;
}
.van-toast--text {
padding: 12px 20px !important;
.van-toast__text {
margin-top: 1px;
}
}
.van-toast {
padding: 20px;
.van-loading__spinner {
width: 50px;
height: 50px;
margin-bottom: 5px;
}
.van-icon {
font-size: 50px;
margin-bottom: 5px;
}
//.van-toast__text{
// margin-top: 16px;
//}
}
.cancelDialog {
.van-dialog__footer {
.van-button {
color: #7f3208 !important;
}
}
}
// 页面横向边距 16px
// 横向间距 horizontal-spacing 16px
.h-spacing {
margin-left: 2 * $base-spacing;
margin-right: 2 * $base-spacing;
}
// 纵向间距 vertical-spacing 12px
.v-spacing {
margin-top: 1.5 * $base-spacing;
}
// 主信息背景-如投保结果页-订单信息
.bg-text-main {
padding: 1.5 * $base-spacing 2 * $base-spacing;
background-color: $bg-color-main;
border-radius: $base-spacing;
}
// 重要信息背景-如我的保险信息
.bg-text-gradient {
background: linear-gradient(to right, $bg-color-gradient-start, $bg-color-gradient-end);
border-radius: 2 * $base-spacing;
}
/* ====================
文字
==================== */
// 辅助信息(次级信息)的正文内容 12px #333 400
.text-auxiliary {
font-size: $font-size-auxiliary;
color: $font-color-regular;
font-weight: $font-weight-regular;
}
.text-auxiliary-info {
@extend .text-auxiliary;
line-height: 1.5;
}
// 辅助信息(次级信息)的辅助信息正文内容 12px #999 400
.text-auxiliary-auxiliary-info {
@extend .text-auxiliary-info;
color: $font-color-auxiliary;
}
// 主信息的正文内容 14px #333 400
.text-main {
font-size: $font-size-main;
color: $font-color-regular;
font-weight: $font-weight-regular;
line-height: $font-size-main;
}
// 主信息的次级内容 14px #666 400
.text-main-secondary {
@extend .text-main;
color: $font-color-secondary;
}
// 文字大小 14sp
.text-size-main {
font-size: $font-size-main;
}
// 文字大小 18sp
.text-size-primary {
font-size: $font-size-primary-title;
}
// 主题字体颜色
.text-color-primary {
color: $font-color-primary !important;
}
// 字体颜色 666
.text-color-secondary {
color: $font-color-secondary !important;
}
// tag 文字
.text-tag {
font-size: $font-size-tag-text !important;
}
.text-color-white {
color: $reverse-white-color-regular !important;
}
// 字重 400
.text-weight-regular {
font-weight: $font-weight-regular !important;
}
// 字重 500
.text-weight-medium {
font-weight: $font-weight-medium !important;
}
// 字重 600
.text-weight-semi-bold {
font-weight: $font-weight-semi-bold !important;
}
// 主信息的次级内容 14px #FA6B4B 500
.text-main-primary {
@extend .text-main;
@extend .text-color-primary;
font-weight: $font-weight-medium;
}
// 主信息的辅助内容 14px #999 400
.text-main-auxiliary {
@extend .text-main;
color: $font-color-auxiliary;
}
// 主信息的正文内容反白颜色 14px #fff 400
.text-main-reverse-white {
@extend .text-main;
color: $reverse-white-color-regular;
}
// 二级标题 16px #333 500
.text-secondary-title {
font-size: $font-size-secondary-title;
color: $font-color-regular;
font-weight: $font-weight-medium;
}
// 二级标题 16px #333 400
.text-secondary-rugular-title {
@extend .text-secondary-title;
font-weight: $font-weight-regular;
}
// 二级标题文字大小 16sp
.text-size-secondary-title {
font-size: $font-size-secondary-title;
}
// 第一层级内容的标题 18px #333 500
.text-primary {
font-size: $font-size-primary-title;
color: $font-color-regular;
font-weight: $font-weight-medium;
}
// 二级金额 20px #fff 600
.text-secondary-amount {
font-size: $font-size-prominent-title;
color: $reverse-white-color-regular;
font-weight: $font-weight-semi-bold;
}
// 常规金额 28px #333 600
.text-main-amount {
font-size: $font-size-regular-amount;
color: $font-color-regular;
font-weight: $font-weight-semi-bold;
}
.text-main-amount__white {
@extend .text-main-amount;
color: $reverse-white-color-regular;
}
// 常规金额 28px #fff 600
.text-regular-amount {
font-size: $font-size-regular-amount;
color: $reverse-white-color-regular;
font-weight: $font-weight-semi-bold;
}
// 辅助颜色 14px #1677FF 500
.text-accessory-secondary {
font-size: $font-size-main;
font-weight: $font-weight-medium;
color: $accessory-color-secondary;
}
.text-top-spacing {
margin-top: $font-spacing;
}
.text-left-spacing {
margin-left: $font-spacing;
}
.text-line-height {
line-height: 1.3;
}
// 辅助信息背景-如保单详情-状态
.text-bg-accessory {
display: flex;
justify-content: center;
align-items: center;
min-width: 60px;
height: 3 * $base-spacing;
border-radius: 0.5 * $base-spacing;
background: rgba(94, 152, 255, 0.08);
}
/* ====================
按钮
==================== */
.btn {
// 基础样式
display: flex;
align-items: center;
justify-content: center;
&--primary {
background: linear-gradient(90deg, $btn-primary-bg-color-start 0%, $btn-primary-bg-color-end 100%);
border: none;
color: $btn-font-color-primary;
font-weight: $font-weight-medium;
&:active,
&:focus {
background: linear-gradient(90deg, darken($btn-primary-bg-color-start, 10%) 0%, darken($btn-primary-bg-color-end, 10%) 100%);
}
}
&--secondary {
min-width: 88px;
background-color: $btn-secondary-bg-color;
border: 1px solid $btn-secondary-border-color;
color: $btn-font-color-secondary;
font-weight: $font-weight-regular;
&:active,
&:focus {
background-color: $btn-secondary-pressed-bg-color;
}
}
&--disabled {
pointer-events: none;
opacity: $btn-disabled-opacity;
cursor: not-allowed;
}
&--large {
@include btn-sizes($btn-height-large, $btn-font-size-large);
}
&--medium {
@include btn-sizes($btn-height-middle, $btn-font-size-middle);
}
&--small {
@include btn-sizes($btn-height-small, $btn-font-size-small);
}
&--extra-small {
@include btn-sizes($btn-height-extra-small, $btn-font-size-extra-small);
}
// 是否为块级元素
&--block {
flex: 1;
}
}
/* ====================
边框
==================== */
.border-top {
border-top: $border-width-regular solid $border-color-regular;
}
.border-bottom {
border-bottom: $border-width-regular solid $border-color-regular
}
/* ====================
图标
==================== */
// 大图标 宽高 48px
.icon-large {
width: 4 * $base-spacing;
height: 4 * $base-spacing;
}
// 中图标 宽高 24px
.icon-medium {
width: 3 * $base-spacing;
height: 3 * $base-spacing;
}
// 右边按钮图标 宽高 16px
.icon-arrow-right {
width: 2 * $base-spacing;
height: 2 * $base-spacing;
}
/* ====================
容器
==================== */
// 容器外边距 mh:16px mt:12px
.container-margin {
margin: 1.5 * $base-spacing 2 * $base-spacing 0;
}
// 容器内边距 ph:32px pt:16px
.container-padding {
padding: 2 * $base-spacing 4 * $base-spacing;
}
// 白色容器 mh:16px mt:12px ph:32px pv:16px radius: 12px
.white-containerr1_5x {
@extend .container-margin;
@extend .bg-white;
@extend .radius-1_5x;
border: 1px solid #F1F1F1;
}
// 白色块
.white-container-r1x {
@extend .container-margin;
@extend .bg-white;
border-radius: $base-spacing;
}
/* ====================
圆角
==================== */
.radius-1x {
border-radius: 1 * $base-spacing;
}
.radius-1_5x {
border-radius: 1.5 * $base-spacing;
}
.radius-2x {
border-radius: 2 * $base-spacing;
}

View File

@@ -0,0 +1,272 @@
// 修改 van-cell-group 的底部边框样式
// 修改 hairline 边框样式
[class*=van-hairline]::after {
border-color: $border-color-regular;
}
// 修改 van-cell-group hairline 边框位置,并只保留上边框
.van-cell-group.van-hairline--top-bottom::after {
border-width: $border-width-regular 0 0;
}
.van-field__error-message {
text-align: right;
}
.van-field--error .van-field__control,
.van-field--error .van-field__control::placeholder {
color: red !important;
}
.van-cell-group {
background-color: transparent;
.van-cell::after {
@extend .border-bottom;
}
}
.van-tabs__line {
background: $orange;
}
// Field 组件,更改 pading 和字体颜色、大小
.van-field {
padding: 1.5 * $base-spacing 2 * $base-spacing;
font-size: $font-size-secondary-title;
.van-field__label {
color: $font-color-secondary;
}
.van-field__control {
@extend .flex-row-e;
//text-align: right;
color: $font-color-regular;
}
}
.van-cell {
padding: 13px 2 * $base-spacing;
line-height: 22px;
font-size: $font-size-secondary-title;
color: $font-color-secondary;
// .van-cell__title{
// flex: 1 0 auto;
// }
.van-cell__value {
margin-left: 2 * $base-spacing;
color: $font-color-regular;
}
}
// 折叠面板,更改 padding使用 cell 的padding
.van-collapse-item__content {
padding: 0;
background-color: transparent;
}
// 弹框背景蒙层
.van-overlay {
background-color: $bg-color-overlay;
}
// popup 组件,更改圆角
.van-popup--bottom.van-popup--round {
border-radius: 1.5 * $base-spacing 1.5 * $base-spacing 0 0;
}
// Picker 组件,更改 pading 和字体颜色、大小
.van-picker {
// 标题栏高度
$van-picker-toolbar-height: 50px;
// 选项高度
$van-picker-item-height: 5 * $base-spacing;
// 标题栏
.van-picker__toolbar {
@extend .border-bottom;
height: $van-picker-toolbar-height;
font-size: $font-size-secondary-title;
font-weight: $font-weight-regular;
// 取消按钮
.van-picker__cancel {
padding: 0 2 * $base-spacing;
font-size: $font-size-secondary-title;
color: $font-color-regular;
}
// 标题
.van-picker__title {
color: $font-color-regular;
font-size: $font-size-secondary-title;
font-weight: $font-weight-medium;
}
// 确认按钮
.van-picker__confirm {
padding: 0 2 * $base-spacing;
font-size: $font-size-secondary-title;
color: $primary-color;
}
}
.van-picker__columns {
// 高度
// height: $grid-column-count * $van-picker-item-height !important;
// 选项
.van-picker-column__item {
// height: $van-picker-item-height !important;
font-size: $font-size-primary-title;
font-weight: $font-weight-regular;
color: $font-color-secondary;
}
// 选中项
.van-picker-column__item--selected {
font-size: $font-size-prominent-title;
font-weight: $font-weight-semi-bold;
color: $font-color-regular;
}
// 选项高度
// .van-picker__frame {
// height: $van-picker-item-height !important;
// }
}
}
// 数字步进器
.van-stepper--round {
$btn-size: 3 * $base-spacing;
$btn-color: #FF5505;
// 加减按钮大小
.van-stepper__minus,
.van-stepper__plus {
width: $btn-size;
height: $btn-size;
}
// 减按钮颜色
.van-stepper__minus {
border-color: $btn-color;
color: $btn-color;
}
// 加按钮颜色
.van-stepper__plus {
background-color: $btn-color;
}
// 输入框
.van-stepper__input {
margin-left: 1 * $base-spacing;
margin-right: 1 * $base-spacing;
width: 5 * $base-spacing;
font-size: $font-size-main;
font-weight: $font-weight-regular;
color: $font-color-regular;
}
}
.van-pull-refresh {
min-height: 100vh;
display: flex;
flex-direction: column;
.van-pull-refresh__track {
flex: 1;
}
}
.van-tabs {
// tab 高度
.van-tabs__wrap {
height: 44px;
}
// tab 字体
.van-tab {
font-size: $font-size-secondary-title;
font-weight: $font-weight-regular;
color: $font-color-secondary;
}
// tab 选中字体
.van-tab--active {
color: $primary-color;
font-weight: $font-weight-medium;
}
// tab 下划线
.van-tabs__line {
width: 3 * $base-spacing;
height: 3px;
background: linear-gradient(to right, $bg-color-gradient-start, $bg-color-gradient-end);
}
}
// 弹框
.van-dialog {
border-radius: $base-spacing;
.van-dialog__header {
padding-top: 3 * $base-spacing;
font-size: $font-size-primary-title;
font-weight: $font-weight-semi-bold;
color: rgba(51, 51, 51, 0.9);
}
.van-dialog__content {
padding: 0 3 * $base-spacing;
font-size: $font-size-main;
font-weight: $font-color-regular;
color: $font-color-secondary;
.van-dialog__message {
padding: 1.5 * $base-spacing 0 2.5 * $base-spacing;
}
}
.van-dialog__footer {
font-size: $font-size-main;
.van-dialog__confirm {
color: $font-color-primary;
}
}
}
// 密码输入框
.van-password-input {
margin: 0;
&__security {
height: 40px;
&::after {
border-radius: $base-spacing;
}
}
.van-hairline--surround {
&::after {
border-width: $border-width-regular;
border-color: #999;
}
}
.van-hairline--left:after {
border-left-width: 0.5px;
border-color: #999;
}
}

View File

@@ -0,0 +1,174 @@
//颜色
$white: #fff !default;
$green: #5ebc75 !default;
$red: #ff0000 !default;
$yellow: #f2c44d !default;
$orange: #fa6b4b !default;
$gray: #b1b1b1 !default;
$black: #000 !default;
$blue: #1989fa !default;
$gray-base: #999 !default;
$gray-dark: #666 !default;
$gray-darker: #333 !default;
$gray-darker-cell: #969799 !default;
$font-size-base: 14px !default;
$font-size-large: 16px !default;
$font-size-small: 12px !default;
$font-size-xl: 18px !default;
//文字列表
$font-size-list: 12 13 14 16 18 20 22 24 26;
// 宽度列表
$width-list: 16 20 22 30 32 40 50 56 60 70 80 86 100 110 120 140 150 155 160 180 192 200 220 260 280 315 325 350 400 440 445 450 550 700 1340;
// 宽度列表
$font-weight-list: 100 200 300 400 500 600 700 800 900 1000;
// 内外边距列表
$distance-list: 0 1 2 5 6 8 9 10 12 15 16 20 24 25 28 30 35 38 33 40 45 48 50 60 65 70 80 86 90 100 110 120 130 140 150 160 170 180 190 200;
$distance-class-list: m, mv, mh, mt, ml, mr, mb, p, pv, ph, pt, pl, pr, pb, top,
left, right, bottom;
// 新内外边距
$spacing-multiple-list: 0 0.5 1 1.5 2 2.5 3 3.5 4 4.5 6 8 9 10 12 15 16 20 24 25 28 30 35 38 33 40 45 48 50 60 65 70 80 86 90 100 110 120 130 140 150 160 170 180 190 200;
$spacing-class-list: m, mv, mh, mt, ml, mr, mb, p, pv, ph, pt, pl, pr, pb, top,
left, right, bottom;
//圆角弧度
$radius: 1 2 3 4 5 6 7 8 9 10 12 15 18 20 50 100;
//透明度
$opacity: 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9;
// ==================== UI 规范 ====================
/* ====================
颜色
==================== */
// 主题色主要用于按钮、icon、文字、输入框、边框、背景等
$primary-color: #FA6B4B;
// 辅助色主要用于icon、页面点缀以及相应的功能色辅助色和弱打扰的颜色可自定义。
$accessory-color-regular: #FFA200; // 常规辅助色
$accessory-color-secondary: #1677FF; // 次要辅助色
$accessory-color-distraction-weak: #5C74B8; // 弱打扰
$accessory-color-error-warning: #FF4019; // 错误/警示色
$accessory-color-success-safe: #00B33B; // 成功/安全色
// 文字颜色定义
$font-color-primary: $primary-color; // 主要文字颜色
$font-color-regular: #333; // 常规文字颜色
$font-color-secondary: #666; // 次要文字颜色
$font-color-auxiliary: #999; // 辅助文字颜色
$font-color-reverse-gray: #BDBDBD; // 灰底反显文字颜色
$font-color-reverse-white: #CCC; // 白底反显文字颜色
$font-color-placeholder: $font-color-reverse-white; // 输入框提示文字颜色
// 背景颜色定义
$bg-color-overlay: rgba(0, 0, 0, 0.4); // 弹框背景蒙层 40%透明度
$bg-color-regular: #F5F5F5; // 常规背景色
$bg-color-hint: #FFF3D7; // 提示语背景
$bg-color-warning: #FFE8E3; // 警示语背景
$bg-color-main: #F8F8F8; // 常规文字背景
$bg-color-backup-blue: #ADCBFF; // 备用背景-蓝
$bg-color-backup-purple: #CFC3FE; // 备用背景-紫
// 分割线颜色
$border-color-regular: #F1F1F1; // 常规分割线颜色
$border-color-weak: #F0F0F0; // 弱分割线颜色
// 反白颜色
$reverse-white-color-regular: #FFF; // 常规反白颜色
$reverse-white-color-secondary: rgba(255, 255, 255, 0.8); // 次要反白颜色透明度80%
/* ====================
文字
==================== */
/* 字体手机银行UI界面中的字体使用系统自带字体
iOS: 中/英字体 苹方/Helvetica Neue
Android: 中/英字体 思源黑体/Roboto
备选:中/英字体 微软雅黑/Noto Sans */
// 字号
$font-size-base: 16px; // 基础字号
// 常规字号:用于界面中各个层级的文本内容,
$font-size-tag-text: 10px; // 标签文字
$font-size-auxiliary: 12px; // 辅助信息;次级信息的正文
$font-size-main: 14px; // 主要信息的正文
$font-size-highlighted: 15px; // 突出显示的正文内容
$font-size-secondary-title: 16px; // 次级内容标题;页面主流程操作
$font-size-main-process: 16px; // 页面主流程操作
$font-size-primary-title: 18px; // 导航栏标题;第一层级内容的标题
// 特殊数字或图形化字符:字号较大,通常用于数字的输入,或需要着重强调的内容
$font-size-prominent-title: 20px; // 醒目的内容大标题
$font-size-name-card: 24px; // 名片的姓名显示
$font-size-regular-amount: 28px; // 常规的金额数字显示
$font-size-graphic-decoration: 32px; // 图形化装饰性字符
// 行高倍数:建议单行文本的行高倍数=1如弹框标题多行文本的行高倍数=1.4,英文的行高倍数=1.2如正文选取行高时尽量选取基本单位8的增量或相邻偶数。
$font-line-height-single: 1; // 单行文本
$font-line-height-multi-chinese: 1.4; // 多行文本-中文
$font-line-height-multi-english: 1.2; // 多行文本-英文
// 字重
$font-weight-regular: 400; // 常规
$font-weight-medium: 500; // 中黑
$font-weight-semi-bold: 600; // 中粗
/* ====================
按钮
==================== */
// 按钮文字颜色
$btn-font-color-primary: #FFFFFF;
$btn-font-color-secondary: $primary-color;
// 按钮背景渐变色
$btn-primary-bg-color-start: #FF8850;
$btn-primary-bg-color-end: #FF5505;
$btn-secondary-bg-color: #FFFFFF;
$btn-secondary-border-color: $primary-color;
$btn-secondary-pressed-bg-color: rgba(250, 107, 75, 0.1);
$btn-disabled-opacity: 0.2;
// 按钮高度
$btn-height-large: 44px;
$btn-height-middle: 40px;
$btn-height-small: 28px;
$btn-height-extra-small: 22px;
// 按钮文字
$btn-font-size-large: 16px;
$btn-font-size-middle: 14px;
$btn-font-size-small: 12px;
$btn-font-size-extra-small: 12px;
/* ====================
栅格布局
==================== */
/* 用户追求高效、便捷,所以栅格的设置不能太拥挤也不能太松散,因此使用经典的栏式网格更符合手机银行的整体调性
界面中的间距应尽量以基本单位「8」整数倍的增量来定义以保证界面清晰有秩序的层次结构。特殊情况下可使用0.5或1.5等倍数定义间距。*/
$base-spacing: 8px; // 最小单位/基础间距:
$grid-column-count: 6; // 栅格栏数
// ==================== 自定义 start ====================
// 边框宽度
$border-width-regular: 1px;
// 背景色-我的
$bg-color-gradient-start: #FF9E59;
$bg-color-gradient-end: $primary-color;
$bg-color-header-notice: #FFF6F4;
// 文字间距
$font-spacing: 1 * $base-spacing;
// 高度
$height-cell-regular: 50px;
$height-cell-title: 44px;

View File

@@ -0,0 +1,86 @@
<template>
<div class="m-swiper-container swiper-container" ref="swiper">
<div class="swiper-wrapper">
<slot>
<div class="swiper-slide">
<van-empty />
</div>
<div class="swiper-slide"><img src="https://img01.yzcdn.cn/vant/cat.jpeg" alt="" /></div>
<div class="swiper-slide"><img src="https://img01.yzcdn.cn/vant/cat.jpeg" alt="" /></div>
</slot>
</div>
<div class="swiper-pagination" v-if="showPagination"></div>
<div class="swiper-button-next" v-if="showNextBtb"></div>
<div class="swiper-button-prev" v-if="showNextBtb"></div>
</div>
</template>
<script>
import Swiper from 'swiper'
import 'swiper/css/swiper.min.css'
import { Empty } from 'vant'
export default {
name: 'm-swiper',
data() {
return {
swiper: '',
defaultOptions: {
initialSlide: 0, //初始展示索引
direction: 'horizontal', //水平/垂直展示
speed: 300, //切换速度
grabCursor: false, //拖动时显示手势 鼠标覆盖Swiper 时指针会变成手掌形状,拖动时指针会变成抓手形状
watchSlidesProgress: true, // 子元素的活动进程
setWrapperSize: false, // Swiper使用flexbox布局(display: flex)开启这个设定会在Wrapper上添加等于slides相加的宽或高在对flexbox布局的支持不是很好的浏览器中可能需要用到。
virtualTranslate: false, // 滑动锁定
width: undefined, //宽度
height: undefined, //高度
breakpoints: '', //响应式设置
autoHeight: false, //自动高度。设置为 true 时wrapper 和container 会随着当前slide 的高度而发生变化。
loop: true,
autoplay: {
delay: 3000
},
}
}
},
props: {
options: {
type: Object,
default: () => {
return {}
}
},
showPagination: {
type: Boolean,
default: false
},
showNextBtb: {
type: Boolean,
default: false
}
},
watch: {},
components: {
[Empty.name]: Empty
},
filters: {},
methods: {},
created() {
let newOptions = Object.assign({}, this.defaultOptions, this.options)
this.$nextTick(() => {
console.log(newOptions)
this.swiper = new Swiper(this.$refs.swiper, newOptions)
})
},
mounted() {}
}
</script>
<style scoped lang="scss">
.m-swiper-container {
height: 200px;
img {
width: 100%;
height: 100%;
}
}
</style>

View File

@@ -0,0 +1,49 @@
<template>
<svg :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName"></use>
<title v-if="!!title">{{title}}</title>
</svg>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String
},
title: {
type: String,
default: ''
}
},
computed: {
iconName() {
return `#icon-${this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
}
}
}
</script>
<style lang="scss" scoped>
.svg-icon {
width: 1.1em;
height: 1.1em;
margin-left: 0.35em;
margin-right: 0.35em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>

6
src/config/index.js Normal file
View File

@@ -0,0 +1,6 @@
let envInfo = process.env
let [admin] = [envInfo.VUE_APP_ADMIN]
export default {
admin,
}

9
src/config/urlMap.js Normal file
View File

@@ -0,0 +1,9 @@
/**
* @desc 远程接口地址和本地mock地址映射表
* key接口地址
* value本地地址
*/
const mockBaseUrl = 'http://rap2.ebiz-digits.com:8083/app/mock/67/'
export default {
mockBaseUrl
}

View File

@@ -0,0 +1,16 @@
/**
* @describe // 全局防重复点击
* @example v-no-more-click="1000"
*/
export default {
inserted(el, binding) {
el.addEventListener('click', () => {
el.classList.add('is-disabled')
el.disabled = true
setTimeout(() => {
el.disabled = false
el.classList.remove('is-disabled')
}, binding.value || 1000)
})
}
}

102
src/filters/index.js Normal file
View File

@@ -0,0 +1,102 @@
import Common from '@/assets/js/common'
/*
* 把其他filter放到index.js里面一起引入
*/
export default {
m2km(value) {
return Common.m2km(value)
},
/**
* 除法
* @param {Number} dividend 被除数
* @param {Number} divisor 除数
* @return {Number} 值
*/
divide(dividend, divisor) {
return Common.divide(dividend, divisor)
},
/**
* 保留小数位替代Number.toFixed()方法针对于某些数据16.455)不能做到四舍五入
* @param {[type]} value 数值
* @param {[type]} num 几位小数
* @return {[type]} 值
*/
toFixed(value, num) {
return Common.toFixed(value, num)
},
/**
* 如果是小数则保留小数位,默认两位
* @param {[type]} value 数值
* @param {Number} num 几位小数
* @return {[type]} 值
*/
toFloatFixed(value, num) {
Common.toFloatFixed(value, num)
},
/**
* 转化成工作时间
* @param {[type]} value 值
* @return {[type]} [description]
*/
businessHour(value) {
let time = ''
if (value) {
const arr = value.split(';')
time =
'星期' +
Common.getWeek(arr[0]) +
' ~ 星期' +
Common.getWeek(arr[1]) +
' ' +
Common.getTime(arr[2]) +
':' +
Common.getTime(arr[3]) +
' ~ ' +
Common.getTime(arr[4]) +
':' +
Common.getTime(arr[5])
}
return time
},
isEmptyObject(o) {
return Common.isEmptyObject(o)
},
wan(value) {
const isNumber = typeof value === 'number'
return isNumber && value / 10000
},
// 除以100保留小数位
divide100(value, num = 2, isFill) {
let values = Number(value)
const regular = /^\d+\.\d+/
if (values) {
values = values / 100
if (regular.test(values)) {
return Common.toFixed(values, num)
} else {
return Common.toFixed(values)
}
} else {
if (isFill) {
// 是否需要填充
value = 0
}
}
return value
},
discount(value, position = 0) {
let ret = value.split('.')
if (position == 0) {
ret = ret[0]
} else if (position == 1) {
ret = ret[1]
}
return ret
}
}

View File

@@ -0,0 +1,7 @@
const requireComponent = require.context('./', true, /\w+\.vue$/) //遍历当前目录和子目录
let comps = {}
requireComponent.keys().map(fileName => {
let comp = requireComponent(fileName).default;
comps[comp.name] = comp
})
export default comps

View File

@@ -0,0 +1,11 @@
//使用混淆模式直接在当前js 注册事件与vue 开发一致,
// vue 文件与js 文件之间的周期函数互通都可以使用this直接调用
export default {
methods: {
//当前函数是前端规则校验
validates() {
let rule_state = false
return rule_state
}
}
}

View File

@@ -0,0 +1,97 @@
<!--
Codes Generated By ebiz-lowcode:
http://www.ebiz-interactive.com/
-->
<template>
<div class="container">
<van-form class="generatedForm " label-align="left" label-width="80px" ref="vForm">
<van-cell :border="false" is-link center>
<template #icon>
<svg-icon icon-class="address-icon" style="margin-right: 10px"></svg-icon>
</template>
<template #label>
<div>
<div class="van-address-item__address">
<span>4545</span>
<span style="margin-left: 10px; color: #cecece">13116065013</span>
</div>
</div>
</template>
<template #title>
<div class="van-address-item__name ellipsis">天津市西青区中北镇新城市中心写字楼A座11层</div>
</template>
</van-cell>
</van-form>
</div>
</template>
<script>
import sa_fun from './sa.js'
// 按需引入
import {
Field
}
from 'vant'
export default {
name: 'sa',
components: {
// 按需引入的组件部分
[Field.name]: Field,
},
props: {
props26238: {
type: String,
}
},
mixins: [sa_fun],
data() {
return {
formData: {},
//
}
},
computed: {},
watch: {},
created() {},
mounted() {},
methods: {
// H5提交函数
submitForm() {
this.$validator.validate().then((ev) => {
if (!ev) {
this.$toast(this.$validator.errors.all()[0]);
return false
}
//通过逻辑部分
})
},
}
}
</script>
<style lang="scss">
</style>
<style lang="scss" scoped>
.ellipsis {
display: block;
max-width: 300px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.generatedForm {
background: #eeeeee;
padding: 5px
}
</style>

View File

@@ -0,0 +1,11 @@
//使用混淆模式直接在当前js 注册事件与vue 开发一致,
// vue 文件与js 文件之间的周期函数互通都可以使用this直接调用
export default {
methods: {
//当前函数是前端规则校验
validates() {
let rule_state = false
return rule_state
}
}
}

View File

@@ -0,0 +1,316 @@
<!--
Codes Generated By ebiz-lowcode:
http://www.ebiz-interactive.com/
-->
<template>
<div class="container">
<van-form class="generatedForm " label-align="left" label-width="80px" ref="vForm">
<van-cell-group title="投保人" inset>
<van-form ref="msubform28085">
<van-field label="姓名" input-align="right" v-model="msubform28085.appntName" type="text" clearable>
</van-field>
<van-field :value="$generatedFormat.formatLabelFun(msubform28085.appntSex,'sex')" label="性别"
input-align="right" @click="appntSex_show = true" readonly is-link />
<van-popup v-model="appntSex_show" round position="bottom">
<van-picker show-toolbar :columns="appntSexOptions" @confirm="appntSexOk" value-key="label"
ref="appntSex_pickerRef">
</van-picker>
</van-popup>
</van-form>
</van-cell-group>
<van-cell-group title="被保人" inset>
<van-form ref="msubform26325">
<van-field label="姓名" input-align="right" v-model="msubform26325.insuredName" type="text" clearable>
</van-field>
</van-form>
</van-cell-group>
<div class="map-form-container" v-for="(item,index) in benfList" :key="index">
<van-cell-group title="受益人" inset>
<van-field label="姓名" input-align="right" v-model="benfList[index].name" type="text" clearable
v-validate="'required'" name="姓名" required>
</van-field>
<van-field class="undefined" input-align="right" label="性别" label-align="left">
<template #input>
<van-radio-group v-model="benfList[index].sex" direction="horizontal">
<van-radio v-for="(item, index) in sexOptions" :key="index" :name="item.value" icon-size="20px">
{{item.label}}</van-radio>
</van-radio-group>
</template>
</van-field>
<van-field right-icon="arrow" label="年龄" input-align="right" v-model="benfList[index].ageLabel"
:readonly="true" type="text" clearable @click="(event)=>{showAgePicker(index)}">
</van-field>
<van-field right-icon="arrow" label="出生日期" input-align="right" v-model="benfList[index].birthday"
:readonly="true" type="text" clearable @click="(event)=>{showBirthday(index)}">
</van-field>
<van-field right-icon="arrow" label="职业" input-align="right" v-model="benfList[index].occLabel"
:readonly="true" type="text" clearable @click="(event)=>{openOcc(index)}">
</van-field>
<van-row>
<van-col :span="24" class="grid-cell text-center">
<van-button type="danger" size="small" plain round icon="delete"
@click="(event)=>{del_benf(index)}" class="sdsd">删除受益人</van-button>
</van-col>
</van-row>
</van-cell-group>
</div>
<van-row>
<van-col :span="24" class="grid-cell text-center pd10">
<van-button type="warning" size="normal" round @click="add_benf">增加受益人</van-button>
</van-col>
</van-row>
<van-button type="warning" size="large" :disabled="true" @click="submitForm">下一步</van-button>
<van-popup v-model="occPopup" :round="true" position='bottom'>
<van-cascader :options="mpopupcascader18663Options"
:field-names='{text: "label", value: "value", children: "children"}' :closeable="false"
@finish="chooseOcc">
</van-cascader>
</van-popup>
<van-popup v-model="birthdayPicker" :round="true" position='bottom'>
<van-datetime-picker type="date" v-model="vForm.mpopupdate77520" :visible-item-count="6"
:formatter="foramterDate" @confirm="saveBir"></van-datetime-picker>
</van-popup>
<van-popup v-model="agePicker" :duration="0.3" :round="true" position='bottom'>
<van-picker show-toolbar :columns="agePickerOptions" @confirm="ageConfirm" value-key="label"
ref="agePicker_pickerRef">
</van-picker>
</van-popup>
</van-form>
</div>
</template>
<script>
import insuranceInfo_fun from './insuranceInfo.js'
// 按需引入
import {
Field,
Search,
Popup,
Picker,
Checkbox,
Form,
CellGroup,
Radio,
RadioGroup,
Button,
Col,
Row,
Cascader,
Tag,
DatetimePicker
}
from 'vant'
export default {
components: {
// 按需引入的组件部分
[Field.name]: Field,
[Search.name]: Search,
[Popup.name]: Popup,
[Picker.name]: Picker,
[Checkbox.name]: Checkbox,
[Form.name]: Form,
[CellGroup.name]: CellGroup,
[Radio.name]: Radio,
[RadioGroup.name]: RadioGroup,
[Button.name]: Button,
[Col.name]: Col,
[Row.name]: Row,
[Cascader.name]: Cascader,
[Tag.name]: Tag,
[DatetimePicker.name]: DatetimePicker,
},
props: {},
mixins: [insuranceInfo_fun],
data() {
return {
vForm: {
mpopupcascader18663: [2],
mpopupdate77520: null,
agePicker: false,
},
//
msubform28085: {
appntName: "",
appntSex: 1,
appntSex_label: '',
},
msubform26325: {
insuredName: "",
},
appntSexOptions: [{
"label": "男",
"value": "0"
}, {
"label": "女",
"value": "1"
}],
sexOptions: [{
"label": "男",
"value": 1
}, {
"label": "女",
"value": 2
}],
mpopupcascader18663Options: [{
"children": [{
"label": "child 1",
"value": 11
}, {
"label": "child 2",
"value": 12
}],
"label": "select 1",
"value": 1
}, {
"label": "select 2",
"value": 2
}, {
"label": "select 3",
"value": 3
}],
agePickerOptions: [{
"label": "1周岁",
"value": "1"
}, {
"label": "2周岁",
"value": 2
}, {
"label": "3周岁",
"value": 3
}, {
"label": "4周岁",
"value": 4
}],
benfList: [{
"name": "",
"sex": "",
"age": "",
"ageLabel": "",
"birthday": "",
"occLabel": "",
"occCode": ""
}],
occPopup: false,
birthdayPicker: false,
agePicker: false,
appntSex_show: false,
}
},
computed: {},
watch: {},
created() {},
mounted() {},
methods: {
appntSexOk(value) {
this.msubform28085.appntSex = value.value
this.appntSex_show = false
},
showAgePicker(index) {
this.agePicker = true
this.index = index
},
showBirthday(index) {
this.birthdayPicker = true
this.index = index
},
openOcc(index) {
this.occPopup = true
this.index = index
},
del_benf(index) {
if (this.benfList.length > 1) {
this.benfList.splice(index, 1)
}
},
add_benf(event) {
this.benfList.push({})
},
submitForm() {
this.$validator.validate().then((ev) => {
if (!ev) {
this.$toast(this.$validator.errors.all()[0]);
return false
}
//通过逻辑部分
})
},
chooseOcc(cascaderData) {
this.benfList[this.index].occLabel = cascaderData['selectedOptions'][cascaderData.tabIndex].label
this.benfList[this.index].occCode = cascaderData['selectedOptions'][cascaderData.tabIndex].value
this.occPopup = false
},
foramterDate(type, val) {
if (type === 'year') {
return `${val}`;
}
else if (type === 'month') {
return `${val}`;
}
return val;
},
saveBir(pickerData) {
this.benfList[this.index].birthday = this.$utils.formatDate(pickerData, "yyyy-MM-dd")
this.birthdayPicker = false
},
ageConfirm(value) {
this.benfList[this.index].age = value.value
this.benfList[this.index].ageLabel = value.label
this.agePicker = false
},
}
}
</script>
<style lang="scss">
</style>
<style lang="scss" scoped>
.filter-popup {
::v-deep .van-picker__toolbar {
height: 80px;
}
}
::v-deep .title-wrapper {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
::v-deep .title-action-wrapper {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px 10px;
padding-bottom: 0px;
box-sizing: border-box;
}
::v-deep .title-search-wrapper {
width: 100%;
display: block;
.van-search__action {
display: inline-flex;
justify-content: center;
align-items: center;
}
}
.generatedForm {
background: #EEEEEE;
padding: 5px
}
</style>

View File

@@ -0,0 +1,11 @@
//使用混淆模式直接在当前js 注册事件与vue 开发一致,
// vue 文件与js 文件之间的周期函数互通都可以使用this直接调用
export default {
methods: {
//当前函数是前端规则校验
validates() {
let rule_state = false
return rule_state
}
}
}

View File

@@ -0,0 +1,122 @@
<!--
Codes Generated By ebiz-lowcode:
http://www.ebiz-interactive.com/
-->
<template>
<div class="container">
<van-form class=" generatedForm" label-align="left" label-width="80px" ref="vForm">
<van-search label="m-search" v-model="formData.msearch42552" label-align="right" background="#B0B0B0">
</van-search>
<m-swiper :options="mswiper51434Options" :showNextBtb="false" :showPagination="false">
<div class="swiper-slide">
<van-image src="http://39.104.123.254:7515/action.jpg" height="300"> </van-image>
</div>
<div class="swiper-slide">
</div>
</m-swiper>
<van-cell title="热门商品" icon-prefix="van-icon" arrow-direction="right">
</van-cell>
<div class="map-form-container" v-for="(item,index) in mmap113313" :key="index">
<van-row>
<van-col :span="11" class="grid-cell">
<van-image src="http://39.104.123.254:7515/action.jpg" height="300"> </van-image>
<van-cell title="文本内容" icon-prefix="van-icon" arrow-direction="right">
</van-cell>
<van-row>
<van-col :span="12" class="grid-cell">
</van-col>
<van-col :span="12" class="grid-cell">
</van-col>
</van-row>
</van-col>
<van-col :span="11" :offset="2" class="grid-cell">
<van-image src="http://39.104.123.254:7515/action.jpg" height="300"> </van-image>
<van-cell title="文本内容" icon-prefix="van-icon" arrow-direction="right">
</van-cell>
<van-row>
<van-col :span="12" class="grid-cell">
</van-col>
<van-col :span="12" class="grid-cell">
</van-col>
</van-row>
</van-col>
</van-row>
</div>
</van-form>
</div>
</template>
<script>
import test_fun from './test.js'
// 按需引入
import {
Field,
Search,
Cell,
Col,
Row
}
from 'vant'
export default {
components: {
// 按需引入的组件部分
[Field.name]: Field,
[Search.name]: Search,
[Cell.name]: Cell,
[Col.name]: Col,
[Row.name]: Row,
},
props: {},
mixins: [test_fun],
data() {
return {
formData: {
msearch42552: "",
mimage16416: null,
mimage62124: null,
mimage51916: null,
},
//
mswiper51434Options: {
"height": 200,
"add": false
},
}
},
computed: {},
watch: {},
created() {},
mounted() {},
methods: {
// H5提交函数
submitForm() {
this.$validator.validate().then((ev) => {
if (!ev) {
this.$toast(this.$validator.errors.all()[0]);
return false
}
//通过逻辑部分
})
},
}
}
</script>
<style lang="scss">
</style>
<style lang="scss" scoped>
.generatedForm {
background: #eeeeee;
padding: 5px
}
</style>

3
src/icons/index.js Normal file
View File

@@ -0,0 +1,3 @@
const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('./svg', false, /\.svg$/)
requireAll(req)

View File

@@ -0,0 +1,5 @@
<svg t="1719199245897" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7147"
width="200" height="200">
<path d="M511.965867 3.413333C290.044587 3.413333 109.550933 185.77408 109.550933 409.985707c0 224.21504 315.132587 567.99232 315.132587 567.99232 47.342933 56.808107 127.225173 56.808107 174.63296 0 0 0 315.132587-343.790933 315.132587-568.005974C914.45248 185.760427 733.893973 3.413333 511.965867 3.413333z m0 581.451094c-102.079147 0-186.4192-83.729067-186.4192-188.34432 0-104.608427 82.855253-188.327253 186.4192-188.327254 103.55712 0 186.368 85.200213 186.368 188.340907 0 103.144107-82.797227 188.34432-186.368 188.34432v-0.013653z"
p-id="7148" fill="#FF976A"></path>
</svg>

After

Width:  |  Height:  |  Size: 750 B

5
src/icons/svg/cell.svg Normal file
View File

@@ -0,0 +1,5 @@
<svg t="1718347578794" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="25874" width="200" height="200">
<path d="M122.368 165.888h778.24c-9.216 0-16.384-7.168-16.384-16.384v713.728c0-9.216 7.168-16.384 16.384-16.384h-778.24c9.216 0 16.384 7.168 16.384 16.384V150.016c0 8.192-6.656 15.872-16.384 15.872zM89.6 850.432a46.98 46.98 0 0 0 47.104 47.104h750.08a46.98 46.98 0 0 0 47.104-47.104V162.304a46.98 46.98 0 0 0-47.104-47.104h-750.08A46.98 46.98 0 0 0 89.6 162.304v688.128z m112.128-440.32V614.4h620.544V410.112H201.728z m572.928 153.6H248.832V459.776h525.824v103.936z"
p-id="25875"></path>
</svg>

After

Width:  |  Height:  |  Size: 662 B

128
src/main.js Normal file
View File

@@ -0,0 +1,128 @@
import Vue from 'vue'
import App from './App.vue'
import Router from './router'
import Store from './store'
import Filters from '@/filters'
import utils from '@/assets/js/common'
import './icons'
import FastClick from 'fastclick'
import '@/assets/js/generatedValidate/index' //表单校验
import validatorItem from '@/assets/js/generatedValidate/generatedValidateItem' //表单校验
import '@utils/compatible' //兼容性代码
import NoMoreClick from '@/directive/no-more-click'
import eruda from 'eruda'
//全局注册vant常用组件
import 'vant/lib/index.css'
import 'viewerjs/dist/viewer.css'
import 'quill/dist/quill.snow.css'
import Bus from '@utils/bus'
import { Toast, Form,Loading,Lazyload,Notify, Image } from 'vant'
import generatedFormat from '@/assets/js/generatedFormat/index'
import generatedApi from '@/api/generatedApi/index'
import generatedComponents from './generatedComponents'
for (let item in generatedComponents) {
Vue.component(item, generatedComponents[item])
}
Vue.use(Image);
Vue.use(Toast)
Vue.use(Form)
Vue.use(Loading)
Vue.use(Lazyload)
Vue.use(Notify)
Vue.use(Lazyload, {
lazyComponent: true,
});
//router or bridge jump
Vue.prototype.$bus = new Bus()
Vue.prototype.$generatedFormat = generatedFormat
Vue.prototype.$generatedApi = generatedApi
Vue.prototype.$generatedDictList = generatedFormat.formatList
Vue.prototype.$validatorItem = { ...validatorItem }
Vue.prototype.$computeNumber = function computeNumber(a, type, b) {
/**
* 获取数字小数点的长度
* @param {number} n 数字
*/
function getDecimalLength(n) {
const decimal = n.toString().split('.')[1]
return decimal ? decimal.length : 0
}
/**
* 修正小数点
* @description 防止出现 `33.33333*100000 = 3333332.9999999995` && `33.33*10 = 333.29999999999995` 这类情况做的处理
* @param {number} n
*/
const amend = (n, precision = 15) => parseFloat(Number(n).toPrecision(precision))
const power = Math.pow(10, Math.max(getDecimalLength(a), getDecimalLength(b)))
let result = 0
a = amend(a * power)
b = amend(b * power)
switch (type) {
case '+':
result = (a + b) / power
break
case '-':
result = (a - b) / power
break
case '*':
result = (a * b) / (power * power)
break
case '/':
result = a / b
break
}
result = amend(result)
return {
/** 计算结果 */
result,
/**
* 继续计算
* @param {"+"|"-"|"*"|"/"} nextType 继续计算方式
* @param {number} nextValue 继续计算的值
*/
next(nextType, nextValue) {
return computeNumber(result, nextType, nextValue)
}
}
}
// 全局 防重复点击
Vue.directive('no-more-click', NoMoreClick)
Vue.prototype.$utils = utils
//混合开发调试工具
// 注册过滤器
Object.keys(Filters).forEach(function(k) {
Vue.filter(k, Filters[k])
})
let envFlag = process.env.VUE_APP_FLAG
if (envFlag != 'prd') {
// eslint-disable-next-line no-undef
eruda.init()
Vue.config.devtools = true
} else {
Vue.config.devtools = false
// eslint-disable-next-line no-undef
// eruda.init() //TODO 生产环境验证,打开调试工具
}
//权限控制
import { permission } from '@/assets/js/utils/permission'
permission()
//ios点击300毫秒时延
FastClick.attach(document.body)
// components下的文件全部转化成组件
const files = require.context('@/components/', true, /\.vue$/)
files.keys().map(item => {
Vue.component(files(item).default.name, files(item).default)
})
Vue.config.productionTip = false
const vm = new Vue({
router: Router,
store: Store,
render: h => h(App)
}).$mount('#app')
window.page = vm

32
src/router/app/index.js Normal file
View File

@@ -0,0 +1,32 @@
/*
* @name:
* @author: Zhang Weiwei
* @created_date: Do not edit
* @description:
*/
// 用途app模块路由配置
//定义相关组件
const notFound = () => import('@/views/app/404')
const home = () => import('@/views/app/Home.vue')
export default [
{
path: '/404',
component: notFound,
meta: {
title: '404'
}
},
{
path: '*',
redirect: '/404'
},
{
path: '/',
redirect: '/home'
},
{
path: '/home',
component: home,
}
]

View File

@@ -0,0 +1,18 @@
export default [
{
path: '/insuranceInfo',
name: 'insuranceInfo',
component: () => import('@/generatedView/insurance/insuranceInfo.vue'),
meta: {
title: '信息录入'
}
},
{
path: '/test',
name: 'test',
component: () => import('@/generatedView/test/test.vue'),
meta: {
title: 'test'
}
},
]

14
src/router/index.js Normal file
View File

@@ -0,0 +1,14 @@
import Vue from 'vue'
import Router from 'vue-router'
import App from './app/index'
import generatedRouter from './generatedRouter/index'
Vue.use(Router)
const constantRouterMap = [...App, ...generatedRouter] //后续可以删减模块
export default new Router({
mode: 'hash', //路由模式
routes: constantRouterMap,
scrollBehavior: () => ({ y: 0 })
})

2
src/store/actions.js Normal file
View File

@@ -0,0 +1,2 @@
const actions = {}
export default actions

4
src/store/getters.js Normal file
View File

@@ -0,0 +1,4 @@
const getters = {
networkState: state => state.app.networkState
}
export default getters

14
src/store/index.js Normal file
View File

@@ -0,0 +1,14 @@
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import mutations from './mutations'
import actions from './actions'
Vue.use(Vuex)
export default new Vuex.Store({
mutations,
actions,
getters,
modules: {}
})

2
src/store/mutations.js Normal file
View File

@@ -0,0 +1,2 @@
const mutations = {}
export default mutations

25
src/store/user.js Normal file
View File

@@ -0,0 +1,25 @@
/**
* @name: 用户信息数据
* @author: Zhang Weiwei
* @created_date: 2023.10.08
* @description: 用户信息和sessionId
*/
const state = {
// 投保信息录入
userInfo: {
customerNo: '00000000134'
},
sessionId: ''
}
const getters = {
userInfo: state => state.userInfo,
sessionId: state => state.sessionId
}
export default {
namespaced: true, // 启用命名空间
state,
getters
}

38
src/views/app/404.vue Normal file
View File

@@ -0,0 +1,38 @@
<!--
Codes Generated By ebiz-lowcode:
http://www.ebiz-interactive.com/
-->
<template>
<div class="container" style='height: 100vh;'>
<van-empty style='height: 100%' description='这里什么都没有' :image='notFoundImg' image-size='100vw' />
</div>
</template>
<script>
import notFoundImg from '@/assets/images/404.jpg'
import {Empty} from 'vant'
export default {
components: {
[Empty.name]:Empty
},
props: {},
data() {
return {
notFoundImg,
}
},
computed: {},
watch: {},
created() {},
mounted() {},
methods: {
// H5提交函数
submitForm() {}
}
}
</script>
<style lang="scss"></style>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,59 @@
<template>
<div class="function-van-cellst-container">
<van-cell-group class="fs14 p20">
<van-cell class="fs18 mb10">基础功能清单</van-cell>
<van-cell>
1apirouterstore等模块划分
</van-cell>
<van-cell>
2mock方案rap2登录我的信息接口mock
</van-cell>
<van-cell>
3权限控制路由拦截器http拦截器
</van-cell>
<van-cell>
4表单验证
</van-cell>
<van-cell>
5常用sass
</van-cell>
<van-cell>
6路由页面切换动画
</van-cell>
<van-cell>
7多环境打包配置
</van-cell>
<van-cell>
8esvan-cellnt + prettier
</van-cell>
<van-cell>9移动端适配方案vw</van-cell>
<van-cell>10主题定制</van-cell>
<van-cell>
11过滤器注册移动端300ms延时调试工具eruda
</van-cell>
</van-cell-group>
<van-tabbar v-model="active">
<van-tabbar-item icon="home-o">首页</van-tabbar-item>
<van-tabbar-item icon="setting-o" @click="$toast('暂未开发……')">我的</van-tabbar-item>
</van-tabbar>
</div>
</template>
<script>
import { Tabbar, TabbarItem,Cell,CellGroup } from 'vant'
export default {
name: 'functionvan-cellst',
components: {
[Tabbar.name]: Tabbar,
[TabbarItem.name]: TabbarItem,
[Cell.name]: Cell,
[CellGroup.name]: CellGroup
},
data() {
return {
active: 0
}
}
}
</script>
<style lang="scss" scoped></style>

40
src/views/app/Home.vue Normal file
View File

@@ -0,0 +1,40 @@
<!--
Codes Generated By ebiz-lowcode:
http://www.ebiz-interactive.com/
-->
<template>
<div class="container">
<functionList></functionList>
</div>
</template>
<script>
import functionList from '@/views/app/FunctionList.vue'
export default {
components: {
functionList
},
props: {},
data() {
return {
formData: {},
mtab37656ActiveTab: 'tab1',
mtab49216ActiveTab: 'tab1'
}
},
computed: {},
watch: {},
created() {},
mounted() {},
methods: {
// H5提交函数
submitForm() {}
}
}
</script>
<style lang="scss"></style>
<style lang="scss" scoped></style>

50
src/views/app/Login.vue Normal file
View File

@@ -0,0 +1,50 @@
<template>
<div class="login-container ph10">
<h3 class="text-center pv30">欢迎登录</h3>
<van-cell-group cl>
<van-field v-model="username" clearable label="用户名" placeholder="请输入用户名" left-icon="contact" />
<van-field v-model="password" type="password" label="密码" placeholder="请输入密码" left-icon="bag-o" />
</van-cell-group>
<van-button type="info" size="large" class="mt30" @click="login" :loading="loading" loading-text="登录中...">登录</van-button>
</div>
</template>
<script>
import { Field, CellGroup } from 'vant'
import { login } from '@/api/app/user'
export default {
name: 'login',
components: {
[Field.name]: Field,
[CellGroup.name]: CellGroup
},
data() {
return {
username: 'admin',
password: '123456',
loading: false,
redirect: this.$route.query.redirect
}
},
methods: {
login() {
if (this.username == '' || this.password == '') {
this.$toast('账号或密码不能为空')
return
}
this.loading = true
//登录
login()
.then(res => {
localStorage.token = res.token
this.$router.push({ path: this.redirect || '/' })
})
.catch(err => {
console.log(err)
this.loading = false
})
}
}
}
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,9 @@
<template>
<div class="layout-container">我是layout</div>
</template>
<script>
export default {
name: 'layout'
}
</script>

34
src/views/ebiz/index.js Normal file
View File

@@ -0,0 +1,34 @@
export default {
name: 'view',
components: {},
props: {
ownerList: {
type: Object,
default: {
list: []
}
}
},
mounted() {},
watch: {
ownerList() {
console.log('数据更新')
}
},
render(h) {
return (
<div class={'app-container'}>
{this.ownerList.list.map((item) => {
return h(item.code, {
props: {
pageList: this.ownerList.list,
propList: item.content ? item.content : null,
id: this.$route.query.saleId,
item: item
}
})
})}
</div>
)
}
}

5
tests/unit/.eslintrc.js Normal file
View File

@@ -0,0 +1,5 @@
module.exports = {
env: {
jest: true
}
}

View File

@@ -0,0 +1,12 @@
import { shallowMount } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'
describe('HelloWorld.vue', () => {
it('renders props.msg when passed', () => {
const msg = 'new message'
const wrapper = shallowMount(HelloWorld, {
propsData: { msg }
})
expect(wrapper.text()).toMatch(msg)
})
})

64
vue.config.js Normal file
View File

@@ -0,0 +1,64 @@
const autoprefixer = require('autoprefixer')
const pxtoviewport = require('postcss-px-to-viewport')
const path = require('path')
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
publicPath: '/saleH5',
lintOnSave: false, //是否开启代码检查
outputDir: 'dist', //打包输出目录
productionSourceMap: false,
devServer: {
https: false
},
css: {
sourceMap: true, // 查看css属于哪个css文件
loaderOptions: {
postcss: {
plugins: [
autoprefixer(),
pxtoviewport({
viewportWidth: 375,
// 该项仅在使用 Circle 组件时需要
// 原因参见 https://github.com/youzan/vant/issues/1948
selectorBlackList: ['van-circle__layer']
})
]
}
}
},
chainWebpack: (config) => {
// 移除 prefetch 插件
config.resolve.alias.set('@utils', resolve('./src/assets/js/utils'))
// config.plugins.delete('prefetch')
/* 配置svg图标自动加载 begin */
config.module.rule('svg').exclude.add(resolve('src/icons')).end()
config.module
.rule('icons')
.test(/\.svg$/)
.include.add(resolve('src/icons'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
//设置路径别名
},
configureWebpack: (config) => {
;(config.devtool = 'source-map'), // 调试js
(config.performance = {
hints: 'error',
//入口起点的最大体积 700kb
maxEntrypointSize: 7168000,
//生成文件的最大体积 700kb
maxAssetSize: 7168000,
//只给出 js 文件的性能提示
assetFilter: function (assetFilename) {
return assetFilename.endsWith('.js')
}
})
}
}

23
vue编码规范.md Normal file
View File

@@ -0,0 +1,23 @@
- Vue 文件命名: 大驼峰式命名法,即每个单词的首字母大写 CamelCase.vue2-3 个单词用具体意义,不要过于简写。
- 定义变量使用 let ,定义常量使用 const使用 exportimport 模块化。
- 基于模块方式开发,每个 Vue 文件等同于一个模块,模块应该专注于解决单一问题,是独立的可服用的。
- 行内表达式尽量简化,太复杂了不宜阅读和维护,可以考虑使用 method 或是 computed 属性来替代其功能;如获取年:(new Date()).getFullYear(),不要写在行内,使用 computed 来实现。
- 组件 props 尽量使用原始类型(字符串、数字、布尔值),这样清晰直观,便于理解。尽量避免使用复杂的对象。使用 prop 验证代码更严谨。具体请参考prop 验证
- 使用 ES6 的箭头函数,这样就不用切换上下文,不用编写类似 let self = this 这样的代码。
- 组件自定义事件命名使用中横岗,对应组件外的一组意义操作。
- 避免使用this.\$parent
- 谨慎使用this.\$refs
- 样式作用域空间:<style scoped></style>
- 代码校验:[ESLint](https://eslint.org/)
- 其他请参考:[官方风格指南](https://cn.vuejs.org/v2/style-guide/)

10599
yarn.lock Normal file

File diff suppressed because it is too large Load Diff

814
开发规范.md Normal file
View File

@@ -0,0 +1,814 @@
# 一、文件命名规范
## 1.1 文件夹以及文件命名
规则:用简短有意义的`英文`(不能出现中文命名)来命名。
1、文件夹名称全部小写。如需连接可使用中横线“-”连字符。
正例:
![](https://tcs-devops.aliyuncs.com/storage/112weadece95e607340c9bcd7466455e3348?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndlYWRlY2U5NWU2MDczNDBjOWJjZDc0NjY0NTVlMzM0OCJ9.t02hk42NnzebreNiIOl0uY-57cQBWhkCzZ3Sd37s_bY&download=image.png "")
![](https://tcs-devops.aliyuncs.com/storage/112w00bfbea32bd6818f00483613ac2f70df?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMncwMGJmYmVhMzJiZDY4MThmMDA0ODM2MTNhYzJmNzBkZiJ9.id7MmD-IC7IMrXV4HoUbzVQtE8UWV9AEfeRreb4C_DQ&download=image.png "")
反例:
![](https://tcs-devops.aliyuncs.com/storage/112wb460aaa44da1f22100e8ee98b57076ce?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndiNDYwYWFhNDRkYTFmMjIxMDBlOGVlOThiNTcwNzZjZSJ9.Edj-a3vz2vHYg97RA9TRgc6ytJeUMwGhCvOyoIrEl4k&download=image.png "")
![](https://tcs-devops.aliyuncs.com/storage/112w08343fabaa3893873d3e13b5c529e621?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMncwODM0M2ZhYmFhMzg5Mzg3M2QzZTEzYjVjNTI5ZTYyMSJ9.agUY61Wn7BjxFgkQonjqTL7FY6bjYgYsBDhZKKoKkCE&download=image.png "")
2、vue文件采用大驼峰形式。即第一个单词首字母大写之后每个单词首字母大写。也可views —> 文件夹名称 —> Index.vue文件夹可多级
正例:
![](https://tcs-devops.aliyuncs.com/storage/112wadfe1f85ec72b13415c2ba081a9784eb?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndhZGZlMWY4NWVjNzJiMTM0MTVjMmJhMDgxYTk3ODRlYiJ9.xLG6Sq1WhIaKzLsnI8Bk0IgtOftJ2h_oDWGqySFalzc&download=image.png "")
反例:
![](https://tcs-devops.aliyuncs.com/storage/112w82f0e65a5e3a49d6c31f2204c8b0c09b?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc4MmYwZTY1YTVlM2E0OWQ2YzMxZjIyMDRjOGIwYzA5YiJ9.sI9ecBXMS_bjJm8aMSNg28Jbaryo_um0PSENmMoiJ34&download=image.png "")
3、html、css、js文件命全部小写。如需连接可使用中横线“-”连字符。
正例:
![](https://tcs-devops.aliyuncs.com/storage/112we5c97e10d2c864ed9ec548b4cf1df54f?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndlNWM5N2UxMGQyYzg2NGVkOWVjNTQ4YjRjZjFkZjU0ZiJ9.5TQww8oRINUAiZjRgcKgoqIsDuyZqjicg3Ge2b_iteo&download=image.png "")
反例:
![](https://tcs-devops.aliyuncs.com/storage/112wcdbf5100cb0490c028db996e4db3573d?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndjZGJmNTEwMGNiMDQ5MGMwMjhkYjk5NmU0ZGIzNTczZCJ9.mGEaJVURmMdNzoTzc38HBdYnwAtJ3jCS_3O-lK0qr-4&download=image.png "")
4、图片命名规则全部小写如需要可用下划线“_”连字符。
正例:
![](https://tcs-devops.aliyuncs.com/storage/112w573093677729d4639517bef4d00c8d8b?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc1NzMwOTM2Nzc3MjlkNDYzOTUxN2JlZjRkMDBjOGQ4YiJ9.fjrzHyZ7rzpet8X6kK2thc4NAkukP1fsTXUsxtN__mQ&download=image.png "")
反例:
![](https://tcs-devops.aliyuncs.com/storage/112we52184aa40987709a547e732d0fbe4ca?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndlNTIxODRhYTQwOTg3NzA5YTU0N2U3MzJkMGZiZTRjYSJ9.a0r4JO2HMGKGiRs3r4-yJeW8HjwzgU_0G7j7FeslKu4&download=image.png "")
## 1.2 vue文件内css的命名规则
规则:用简短有意义的英文来命名。如需连接可使用中横线“-”连字符。
1、规定html/vue的每一个容器都要加入对应的名字 pscontainer一个页面只能有一个如需所有的container有公共样式可如下图如不需要可只保留对应的名字+container类名
![](https://tcs-devops.aliyuncs.com/storage/112wfacae63841b247370ba354d2a63e8770?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndmYWNhZTYzODQxYjI0NzM3MGJhMzU0ZDJhNjNlODc3MCJ9.DpXaXJptVYhMQVhBjcczwic7BfAh5FEp27IqYpKLp7I&download=image.png "")
2、需加入scoped防止污染全局如需覆盖框架样式加入::v-deep 即可。
![](https://tcs-devops.aliyuncs.com/storage/112wa75384c76889dbce9c9f1cf885e3ee84?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndhNzUzODRjNzY4ODlkYmNlOWM5ZjFjZjg4NWUzZWU4NCJ9.8xxLGUwkJl7DQHb87mSMc-7enRBtZvtg5RGZPfuYeaQ&download=image.png "")
## 1.3 vue文件内js的命名规则
1、常量命名有固定指意的全部大写并用下划线分隔单词。无特定指意可采用小驼峰形式。
正例:
![](https://tcs-devops.aliyuncs.com/storage/112weca23c6d0b446b72da40a543ca4a8a22?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndlY2EyM2M2ZDBiNDQ2YjcyZGE0MGE1NDNjYTRhOGEyMiJ9.-hk-Xt9kcQ3JxzgqT7aWAkVbJtUPMMps9xRZTaJDgSk&download=image.png "")
反例:
![](https://tcs-devops.aliyuncs.com/storage/112w9a8d0657a51c2abdb9e7411007ff54aa?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc5YThkMDY1N2E1MWMyYWJkYjllNzQxMTAwN2ZmNTRhYSJ9.T4ldChrzM_jiMqXpWpsIw3EHWFbkkYhQ-82bL3sXehg&download=image.png "")
2、变量命名采用小驼峰且使用let。
正例:
![](https://tcs-devops.aliyuncs.com/storage/112w7ed6a232e8ede6801ee60f121d6d7bf7?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc3ZWQ2YTIzMmU4ZWRlNjgwMWVlNjBmMTIxZDZkN2JmNyJ9.uTl292Xz_MB75UP0ccz6IPtnlURY1KPa1h_7eTs6htw&download=image.png "")
反例:
![](https://tcs-devops.aliyuncs.com/storage/112wfc376c192ab08d88765e381d69398736?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndmYzM3NmMxOTJhYjA4ZDg4NzY1ZTM4MWQ2OTM5ODczNiJ9.3vO4WMhK_sn3OgP4GvOMkgPuMyYTGOQJZzLfb6illp8&download=image.png "")
3、Class、构造函数命名采用大驼峰。
正例:
![](https://tcs-devops.aliyuncs.com/storage/112w2ce3b288c2477e4897a7cf34a4a1a4ee?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMncyY2UzYjI4OGMyNDc3ZTQ4OTdhN2NmMzRhNGExYTRlZSJ9.Kqlj55x52j66RqHVchPbpBVSJ1jrgUH2FkBWdQfcbBg&download=image.png "")
反例:
![](https://tcs-devops.aliyuncs.com/storage/112w28d80245d993abaa36873940921f539e?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMncyOGQ4MDI0NWQ5OTNhYmFhMzY4NzM5NDA5MjFmNTM5ZSJ9.nyrUM_dm3sIUcna4LHLYSYHNTtarb1szJIdcz4F6DdY&download=image.png "")
4、函数命名采用小驼峰。
正例:
![](https://tcs-devops.aliyuncs.com/storage/112w67013196129b4fb8e069e2b7e20632e3?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc2NzAxMzE5NjEyOWI0ZmI4ZTA2OWUyYjdlMjA2MzJlMyJ9.PgFtBY1M4kuPU9vNP57WugVFP3L3pTaPMKrqTlwS7wE&download=image.png "")
反例:
![](https://tcs-devops.aliyuncs.com/storage/112weae201995bed4c78a7d23632327ee1f8?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndlYWUyMDE5OTViZWQ0Yzc4YTdkMjM2MzIzMjdlZTFmOCJ9.lx_QhjCjWClmQaXNYPqxk2YPhk4cZxSFGD3ZM14bALk&download=image.png "")
推荐:
| 动词 | 含义 | 返回值 |
| --- | ----------- | ----------------------- |
| can | 判断是否可执行某个动作 | true---可执行false---不可执行 |
| has | 判断是否含有某个值 | true---含有此值false---无此值 |
| is | 判断是否为某个值 | true---是此值false---不是此值 |
| get | 获取某个或某些值 | ----- |
| set | 设置某个或某些值 | ----- |
5、组件命名采用大驼峰。
正例:
![](https://tcs-devops.aliyuncs.com/storage/112w781c6bce4d581f42ac11947d7d70606f?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc3ODFjNmJjZTRkNTgxZjQyYWMxMTk0N2Q3ZDcwNjA2ZiJ9.j2-uIcGrZjg5eLAq_Tl7eQU_HlD2hKLUn5ngtqRl7aA&download=image.png "")
反例:
![](https://tcs-devops.aliyuncs.com/storage/112wcc3d079e68f084d2736e3f858f799e4e?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndjYzNkMDc5ZTY4ZjA4NGQyNzM2ZTNmODU4Zjc5OWU0ZSJ9.QF4w9yWFaDXQoDet-KVaiCeTQS7784UacpuTGLNX3G4&download=image.png "")
6、import及export进来的变量名采用大驼峰。
正例:
![](https://tcs-devops.aliyuncs.com/storage/112w2a8af43c5ec931ee928d6ae563708751?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMncyYThhZjQzYzVlYzkzMWVlOTI4ZDZhZTU2MzcwODc1MSJ9.m1c4FfP98kFDREff4128tj1qka8h10goRAHdx5V6UiA&download=image.png "")
反例:
![](https://tcs-devops.aliyuncs.com/storage/112w45cdd8c5c5d12b73be360563edf43648?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc0NWNkZDhjNWM1ZDEyYjczYmUzNjA1NjNlZGY0MzY0OCJ9.jnzuSNvDCUs6TX_ayZ4yL1Jt_WEzrJJHZcxftfdEAys&download=image.png "")
# 二、编码规范
## 2.1 sass 规范
### 2.1.1 Sass 目录规范
![](https://tcs-devops.aliyuncs.com/storage/112wd729e162d444d8fdf1ba87e4823631be?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndkNzI5ZTE2MmQ0NDRkOGZkZjFiYTg3ZTQ4MjM2MzFiZSJ9.QSsHv_4gZ4n-ZUainwF9gA9AOBdCcYIagTkRxtlSa6k&download=image.png "")
### 2.1.2 目录说明
1、common.scss
初始化样式、样式出口文件要在入口文件App.vue引入。
![](https://tcs-devops.aliyuncs.com/storage/112w78f9e04efd55a217b02f3f0ba2c33940?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc3OGY5ZTA0ZWZkNTVhMjE3YjAyZjNmMGJhMmMzMzk0MCJ9.lDophNbqxQgM5kzJjAC4bOS9GU3n8HXdxxBheb3Ewl8&download=image.png "")
2、vant-ui.scss
如果vant某些样式不是你需要的在 vant-ui.scss 里可以重写来覆盖vant样式。
如果你只想重写当前组件的样式可在直接在组件里重写如设置了style的scoped属性导致修改样式无效可以使用::v-deep ,方法如下:
![](https://tcs-devops.aliyuncs.com/storage/112wee2ab2223e96d460371ff08a30628935?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndlZTJhYjIyMjNlOTZkNDYwMzcxZmYwOGEzMDYyODkzNSJ9.dr5RkCR865e_OFTAIo3ZCnwtCLG1MbutWbfINI2-M94&download=image.png "")
3、mixin.scss
@mixin 指令允许我们定义一个可以在整个样式表中重复使用的样式。
@include 指令可以将混入(定义的@mixin可理解为sass模块引入到文档中实例如下
![](https://tcs-devops.aliyuncs.com/storage/112w1dd7a46e33833e4d559ed145e7e7709d?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMncxZGQ3YTQ2ZTMzODMzZTRkNTU5ZWQxNDVlN2U3NzA5ZCJ9.WRAjDKTJF4nAiZF9NAUvgAkJok7LnwvoA4OBTaJotWw&download=image.png "")
可向混入传递变量,实例如下:
![](https://tcs-devops.aliyuncs.com/storage/112w85f5366db81b27d88e39d9c9312dee7b?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc4NWY1MzY2ZGI4MWIyN2Q4OGUzOWQ5YzkzMTJkZWU3YiJ9.XOIbnJnVR_YP6OsNdX0P6GGV0uVAsFbVUfM-4VSdFvo&download=image.png "")
常用内外边距及类名缩写列表
![](https://tcs-devops.aliyuncs.com/storage/112w05b034272215e2eb4f2b2d501e7522bb?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMncwNWIwMzQyNzIyMTVlMmViNGYyYjJkNTAxZTc1MjJiYiJ9.nOuoLW7pCthJ_7WG5nnL_jRzPaecC3JmvWXZ-jYhoxQ&download=image.png "")
常用边距模块
![](https://tcs-devops.aliyuncs.com/storage/112wd4673d1331c8d1a89181296c938d8cd9?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndkNDY3M2QxMzMxYzhkMWE4OTE4MTI5NmM5MzhkOGNkOSJ9.iG93vQbG4uEQQO6RxtbaYHyOmzFRFhpCcZ9rc7WFC_E&download=image.png "")
配合循环语句和判断语句来匹配并引入。
![](https://tcs-devops.aliyuncs.com/storage/112we6c843fd61a39402ee4b8fcb32fbbd33?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndlNmM4NDNmZDYxYTM5NDAyZWU0YjhmY2IzMmZiYmQzMyJ9.fl4sKLLkyXkGQBHyVaMyiW3dXJvMQO6V7YwlSQPZIVM&download=image.png "")
CSS输出
![](https://tcs-devops.aliyuncs.com/storage/112wfef214dad732d28987e4e901e254a11f?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndmZWYyMTRkYWQ3MzJkMjg5ODdlNGU5MDFlMjU0YTExZiJ9.8QWyFDLPJjpifd51351GVjsbVYXUP9Jfv9cpMNPDY2o&download=image.png "")
4、transition.scss
如果你需要在多处使用同一个固定CSS3动画统一写在 transition.scss
![](https://tcs-devops.aliyuncs.com/storage/112w544ad2d9c8072c4f088bfc64f52f9db0?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc1NDRhZDJkOWM4MDcyYzRmMDg4YmZjNjRmNTJmOWRiMCJ9.qmsDnTqwUz9u0ZAKyyKtF9WpODGGzS5dVnCpFuW-PkI&download=image.png "")
5、utils.scss
工具样式文件,如果你需要在多处使用同一个固定样式时可以写在此文件中,如:
![](https://tcs-devops.aliyuncs.com/storage/112w84883b6066d05a727da320a526453a62?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc4NDg4M2I2MDY2ZDA1YTcyN2RhMzIwYTUyNjQ1M2E2MiJ9.TKET959zLcmca8Zg_D0mxzqbITSq0wJ8_pTXn4baVMk&download=image.png "")
6、variables.scss
如需声明变量,统一写在 variables.scss用 $ 加变量名 声明,如:
![](https://tcs-devops.aliyuncs.com/storage/112w9049d1c93efc6b2b0c3e12ad6a28e37c?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc5MDQ5ZDFjOTNlZmM2YjJiMGMzZTEyYWQ2YTI4ZTM3YyJ9.NUJgEv0uLOhXMg_2qY8qCmChhAOvuKuic3tm-U-QbcE&download=image.png "")
### 2.1.3 全局CSS样式
1、浮动、清除浮动
- .fl 左浮动
- .fr 右浮动
- .chearfix 清除浮动
2、字体样式
- .fs12 字体尺寸 12px
- .fs14 字体尺寸 14px
- .fs16 字体尺寸 16px
- .fs18 字体尺寸 18px
- .fw600 字体粗细 600
- .fwb 字体粗细 bold
3、布局定位
- .relative 相对于其正常位置进行定位
- .absolute 相对于 static 定位以外的第一个父元素进行定位
- .fixed 相对于浏览器窗口定位
- .mh-auto 块级元素水平居中
- .hide 元素隐藏,但仍占用空间
- .hidden 元素隐藏,不占用空间
- .flex 弹性盒模型布局,块级元素
- .inline-flex 弹性盒模型布局,内联块元素
- .inline-b 内联块元素,表现为同行显示并可修改宽高内外边距等属性
- .justify-content-c 弹性项目居中填充
- .align-items-c 元素位于容器的中心。弹性盒子元素在该行的侧轴(纵轴)上居中放置
4、常用文字颜色
- .c-gray-base 文字颜色 #999
- .c-gray-dark 文字颜色 #666
- .c-gray-darker 文字颜色 #333
- .green 文字颜色 green
- .red 文字颜色 red
- .yellow 文字颜色 yellow
- .gray 文字颜色 gray
- .white 文字颜色 白色
4、背景颜色
- .bg-black 背景颜色 黑色 black
- .bg-white 背景颜色 白色 white
- .bg-none 背景颜色 透明 transparent
5、文字位置设置
- .text-left 左对齐
- .text-right 右对齐
- .text-center 居中对其
- .text-underline 文字下划线
6、垂直方向对齐方式
- .v-top 把元素的顶端与行中最高元素的顶端对齐 vertical-align: top
- .v-middle 把此元素放置在父元素的中部 vertical-align: middle
- .v-bottom 把元素的顶端与行中最低的元素的顶端对齐 vertical-align: bottom
- .v-baseline 默认,元素放置在父元素的基线上 vertical-align: baseline
![](https://tcs-devops.aliyuncs.com/storage/112w5dcea9cee753c50fb86417a4172ca9aa?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc1ZGNlYTljZWU3NTNjNTBmYjg2NDE3YTQxNzJjYTlhYSJ9.OJmUglIADBzVXYcJ3Fk0jibu-_Gz_epFFJ8xlnOWRAg&download=image.png "")
7、单行省略
.ellipsis 单行省略
![](https://tcs-devops.aliyuncs.com/storage/112w0b9ef8c7799df68f158bbda98c07056c?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMncwYjllZjhjNzc5OWRmNjhmMTU4YmJkYTk4YzA3MDU2YyJ9.cCK7TDGp7Fm9z3dUGlq7n89UgAFxKZxU6T-ewk5YRNo&download=image.png "")
![](https://tcs-devops.aliyuncs.com/storage/112w202b24b71523a36ed2133167767cd4bb?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMncyMDJiMjRiNzE1MjNhMzZlZDIxMzMxNjc3NjdjZDRiYiJ9.swOzyMXnYH3_KdsSAuOh4R02czVFT95YvKyhsod4HWk&download=image.png "")
可根据宽度自适应显示文字长度
![](https://tcs-devops.aliyuncs.com/storage/112w44c4c615a470f2f51706a0cb2e56b314?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc0NGM0YzYxNWE0NzBmMmY1MTcwNmEwY2IyZTU2YjMxNCJ9.dg1RRZsW2D6LogzzsfSVBLNQ20ulUuI01Wo4fYtkGf0&download=image.png "")
8、宽度、高度、内外边距、圆角弧度、透明度
- 我们在 variables.scss 文件里声明了** 宽度、高度、内外边距、圆角弧度、透明度** 常用的一些数值,以及一些类名缩写
![](https://tcs-devops.aliyuncs.com/storage/112w47efd6cbfc35d1504e1b4a04d62b3b35?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc0N2VmZDZjYmZjMzVkMTUwNGUxYjRhMDRkNjJiM2IzNSJ9.wwI3GqALc4BOxShAQO_Swxv3n9JQni7wKiXFEq-Skds&download=image.png "")
- 在 mixin.scss 文件定义了混入函数,通过传参的方式,根据类名缩写及数值来匹配相应的样式。
![](https://tcs-devops.aliyuncs.com/storage/112w428cc279cc9d4c3ad1f4bb489cb7d4cc?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc0MjhjYzI3OWNjOWQ0YzNhZDFmNGJiNDg5Y2I3ZDRjYyJ9.IwHuwFiDKkbqO5ibFtAkXazZ2_T5IXKfP-CnTT_eKCg&download=image.png "")
- 并在样式出口文件 common.scss中引入这样全局都可使用这些类名缩写来使用这些样式。
![](https://tcs-devops.aliyuncs.com/storage/112waf5ce40fdfc5140d931b874f242954e8?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndhZjVjZTQwZmRmYzUxNDBkOTMxYjg3NGYyNDI5NTRlOCJ9.D8j-xXv37AcRGqXKTJV75x3YDATOsUGkPCXHiGeWmcg&download=image.png "")
文档如下:
**宽度 、高度**
类名缩写wh
常用数值40 50 60 70 80 86 100 110 120 140 150 155 160 180 192 200 220 260 280 315 325 350 400 440 445 450 550 700 1340
使用方法:类名 + 数值
例如:
宽度为100<div class="w100"></div>
高度为100<div class="h100"></div>
**圆角弧度**
类名缩写radius
常用数值1 2 3 4 5 6 7 8 9 10 12 15 18 20 50 100
使用方法:类名 + 数值
例如:
圆角弧度为10<div class="radius10"></div>
**透明度**
类名缩写opacity
常用数值0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9
使用方法:类名 + 数值
例如:
透明度为0.9<div class="opacity0.9"></div>
**内外边距**
类名缩写m, mv, mh, mt, ml, mr, mb, p, pv, ph, pt, pl, pr, pb, top, left, right, bottom
- m margin 外边距
- mv margin-top margin-bottom 上下外边距
- mh margin-left margin-right 左右外边距
- mt margin-top 上外边距
- ml margin-left 左外边距
- mr margin-right 右外边距
- mb margin-bottom 下外边距
- p padding 内边距
- pv padding-top padding-bottom 上下内边距
- ph padding-left padding-right 左右内边距
- pt padding-top 上内边距
- pl padding-left 左内边距
- pr padding-right 右内边距
- pb padding-bottom 下内边距
- top 定位属性 top
- left 定位属性 left
- right 定位属性 right
- bottom 定位属性 bottom
常用数值0 1 2 5 6 8 9 10 12 15 20 25 30 35 40 45 50 60 80 86 90 100
使用方法:类名 + 数值
例如:
左右外边距为30<div class="mh30"></div>
上下内边距为30<div class="pv30"></div>
定位属性top为30<div class="top30"></div>
### 2.1.4 使用实例
代码为:
![](https://tcs-devops.aliyuncs.com/storage/112wed5a2dd2b0fa9ac9ddd1f461806c9f2d?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndlZDVhMmRkMmIwZmE5YWM5ZGRkMWY0NjE4MDZjOWYyZCJ9.Hdw-VxfVERb6ViCBxN5QxxEJxTckqdYGNTt7fqCI6JQ&download=image.png "")
输出为:
![](https://tcs-devops.aliyuncs.com/storage/112w445d15a5f4070e368d95dbc642c98f48?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc0NDVkMTVhNWY0MDcwZTM2OGQ5NWRiYzY0MmM5OGY0OCJ9.99oFH8U6STmk8n3mTd-ZfjIapmp-7Nhmqx5lq3_rYzo&download=image.png "")
代码为:
![](https://tcs-devops.aliyuncs.com/storage/112w48537c6054f22596bde7ef25aaa7507f?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc0ODUzN2M2MDU0ZjIyNTk2YmRlN2VmMjVhYWE3NTA3ZiJ9.najVWYdylSampCBfLyEOW6hOiFgis45Zz3eNZkR4ztc&download=image.png "")
输出为:
![](https://tcs-devops.aliyuncs.com/storage/112we8cb555fceb69a2fc9be050d04b01a49?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndlOGNiNTU1ZmNlYjY5YTJmYzliZTA1MGQwNGIwMWE0OSJ9.d3-IzKu_LjvK5ZqXATkUsLSLFW1Fcp5n9R2VITOM6LA&download=image.png "")
## 2.2 vue 编码规范
### 2.2.1 vue 文件基本结构
组件顶级元素顺序按 `<template>``<script>``<style> `的顺序放置。
![](https://tcs-devops.aliyuncs.com/storage/112wc320efeec9083942d69ac63cd5d7e2f5?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndjMzIwZWZlZWM5MDgzOTQyZDY5YWM2M2NkNWQ3ZTJmNSJ9.T6vRvIknhs89wjsyW1eK0b53du3drRyr-wCiAWSrNeg&download=image.png "")
### 2.2.2 template
在template里的最外层放置容器类名为 **组件名+container**,例如:
![](https://tcs-devops.aliyuncs.com/storage/112w84f24f4c43074a16175f725f6740cb7d?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc4NGYyNGY0YzQzMDc0YTE2MTc1ZjcyNWY2NzQwY2I3ZCJ9.gLqtgh47B3YgtlH7W0r5Qm-C04WR3T9RtDA6Ag_RxKM&download=image.png "")
### 2.2.3 script
各个属性、周期需按照如下顺序放置name、components、props、data、周期函数、methods、computed、watch、filter其他规范如下
- **name**:组件命名必填,和组件文件名保持一致,始终是 PascalCase在DOM模板中应该是kebab-case
![](https://tcs-devops.aliyuncs.com/storage/112w7074c3e139c801998d9750d9e2a19e89?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc3MDc0YzNlMTM5YzgwMTk5OGQ5NzUwZDllMmExOWU4OSJ9.yeFK0x3ZJgdCzWcehmkrStn_eHq4vPeZVMN0fsMNI5A&download=image.png "")
![](https://tcs-devops.aliyuncs.com/storage/112wfbb16e846e4ebac6fea7dadb13ef18bf?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndmYmIxNmU4NDZlNGViYWM2ZmVhN2RhZGIxM2VmMThiZiJ9.ChjqOdn24FXVnuLnbbFStL3o5pIWtrDWpIH_kNwvFqY&download=image.png "")
- **props**:定义需指定其类型,命名应该始终使用 camelCase而在模板和 JSX 中应该始终使用 kebab-case
![](https://tcs-devops.aliyuncs.com/storage/112w73164c36f30b9ec72ce3de64d667771b?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc3MzE2NGMzNmYzMGI5ZWM3MmNlM2RlNjRkNjY3NzcxYiJ9.O8e_gD2DbCv54BfTAYCptwxuAk9_wBY0z37E5GzxCjY&download=image.png "")
- **data**变量注释规范 在变量后单行注释说明
![](https://tcs-devops.aliyuncs.com/storage/112wb6b1fcfacdc1b68612388da7d0a072e1?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndiNmIxZmNmYWNkYzFiNjg2MTIzODhkYTdkMGEwNzJlMSJ9.IdC-yb1cASSdlP6yrEZXpTO7nAiq37Kv-SH5QRB6BvY&download=image.png "")
- **methods**
建议使用扩展运算符拷贝对象
![](https://tcs-devops.aliyuncs.com/storage/112w60ac5fe966ef1072355fcebb8e38ec4b?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc2MGFjNWZlOTY2ZWYxMDcyMzU1ZmNlYmI4ZTM4ZWM0YiJ9.c7WO_ANbVTTrEk2HLiioT1ouINDBLZvRXKTz8fglXs8&download=image.png "")
提交数据时不可直接使用页面渲染对象,推荐使用扩展运算符
![](https://tcs-devops.aliyuncs.com/storage/112w60d942a6d2ca13e22be3b9a9f2e73302?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc2MGQ5NDJhNmQyY2ExM2UyMmJlM2I5YTlmMmU3MzMwMiJ9.EPOpkav-fwydBv9hGvYQPmBTt0SkR2Yc5gz5zEMZPCs&download=image.png "")
- **computed**复杂计算应使用计算属性 **computed**
理论上computed 所有实现可以使用 methods 完全替换。computed 只有在与它相关或者需要的数据发生改变时才会重新求值。
![](https://tcs-devops.aliyuncs.com/storage/112wed87b289192a2fe9062ed7ede98b05e9?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndlZDg3YjI4OTE5MmEyZmU5MDYyZWQ3ZWRlOThiMDVlOSJ9.Zm6jmNWH1wZBgUErCJoDrZJJT1KtvPqsW-pfoUibDPs&download=image.png "")
调用computed的方法时不需要加****。
![](https://tcs-devops.aliyuncs.com/storage/112wc7e3daf5a73dc2b654d47fc5479c6790?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndjN2UzZGFmNWE3M2RjMmI2NTRkNDdmYzU0NzljNjc5MCJ9.X66W2ZomrKMf5iS49-aG1odWymyxTORhRqX0jb8gn48&download=image.png "")
- **watch**:当需要在数据变化时执行异步或开销较大的操作时应使用侦听器 **watch**
![](https://tcs-devops.aliyuncs.com/storage/112w04fcd0084a08f79a0715203bf4b82935?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMncwNGZjZDAwODRhMDhmNzlhMDcxNTIwM2JmNGI4MjkzNSJ9.HrEjCprpizYIYRoMBHlOvAs0pJd-Ky5u5Dd-TaDsJuo&download=image.png "")
上图中初始 fullName是没有值的watch默认不会执行只有当侦听的数据发生改变时才会执行通过声明 **immediate **选项为** true**,可以立即执行一次 handler。
![](https://tcs-devops.aliyuncs.com/storage/112w51efcabff7498d201deff502467f38c0?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc1MWVmY2FiZmY3NDk4ZDIwMWRlZmY1MDI0NjdmMzhjMCJ9.n_2U0qO4AhsBMbUj1SH_DpgHfL7-XMshGUY8wi7RYrg&download=image.png "")
不使用 deep 时,当我们改变 obj.a 的值时watch不能监听到数据变化**默认情况下handler 只监听属性引用的变化,也就是只监听了一层,但修改对象内部的属性是监听不到的**。
通过使用 **deep: true** 进行深入观察,这时,我们监听 obj会把 obj 下面的属性层层遍历,都加上监听事件,这样做,**性能开销也会变大**,只要修改 obj 中任意属性值,都会触发 handler。
![](https://tcs-devops.aliyuncs.com/storage/112w3ee3abeaa9f998f71c36bde0ed09f489?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnczZWUzYWJlYWE5Zjk5OGY3MWMzNmJkZTBlZDA5ZjQ4OSJ9.xpzdyL3LKv-Xz1r0CFLuOs_v9laAOnyPisoe7uirdFs&download=image.png "")
### 2.2.4 style
声明语言 **lang="scss"** ,为了避免样式冲突,添加 **scoped **属性,并避免出现元素选择器。
以嵌套的方式在父容器类里写你需要的样式因为我们声明了很多公用的全局CSS样式所以组件里的样式尽量不超过20行。
如果你想重写当前组件vant的样式可使用** ::v-deep ** 重写,示例如下
![](https://tcs-devops.aliyuncs.com/storage/112wfc9c9b405d4b3fe5062152b598425d6f?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndmYzljOWI0MDVkNGIzZmU1MDYyMTUyYjU5ODQyNWQ2ZiJ9.R5l13dt_9lWQq-B8iL0C4ldEESObD44dvxmggHcppg8&download=image.png "")
### 2.2.5 指令规范
指令有缩写一律采用缩写形式如v-bind、v-on简写成 **: **、**@**。
![](https://tcs-devops.aliyuncs.com/storage/112wd6cf59a6a6cd6ce92681119d6b4dd3d0?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndkNmNmNTlhNmE2Y2Q2Y2U5MjY4MTExOWQ2YjRkZDNkMCJ9.jGxbA-fzY2pIZrgm387Z4_2Srh-M0b8pPZUG2iV-PQ8&download=image.png "")
v-for 循环必须加上 **key** 属性,在整个 for 循环中 key 需要 **唯一** 避免 v-if 和 v-for 同时用在一个元素上(性能问题),可把 v-if 放在父容器上。
![](https://tcs-devops.aliyuncs.com/storage/112wf2a56dd62a6586ae625fcb2d6cce5f16?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndmMmE1NmRkNjJhNjU4NmFlNjI1ZmNiMmQ2Y2NlNWYxNiJ9.Zcac6rnDnuyQ2tb9czts6OZmTD1Hkqx4CLrH_i_g8t4&download=image.png "")
### 2.2.6 注释规范
代码注释在一个项目的后期维护中显的尤为重要,使用注释是良好的编程实践,它可以帮助他人理解代码的意图和功能,也方便自己在以后阅读代码时理解思路。
注释的内容主要包含这样三个方面:**做什么、为什么、怎么做**。对于一些复杂的组件和接口,我们可能还需要写明“如何用”。
文件和函数一定要写注释,而且要写得尽可能全面详细。函数内部的注释要相对少一些,一般都是靠好的命名、提炼函数、解释性变量、总结性注释来提高代码可读性。
**单行注释:**可以在语句之前和之后使用
```javascript
alert('Hello, JavaScript'); // 输出Hello, JavaScript
```
**多行注释:**用于跨多行注释代码片段
```javascript
/*
This is a multi-line comment.
It can span across multiple lines.
*/
```
.**html/.js/.vue/.css文件注释**
文件顶部必须包含文件注释,用 @name 标识文件说明。标识符冒号与内容之间必须保留一个空格。新增的情况
当该业务项目主要由固定的一个或多个人负责时,需要添加**@author**标识,一方面是尊重劳动成果,另一方面方便在需要时快速定位责任人。
```javascript
/*
* @name 文件名或模块名
* @author 作者姓名
* @created_date 创建时间 2018.07.05
* @description 文件或模块描述
*/
```
- 修该的情况(追加)
```javascript
/*
* @modified by 修改者姓名
* @modified_date 修该时间2018.07.05
* @description 修该点
*/
```
**常量**:每个常量都需要添加说明注释
**data**: data 数据必须添加单行注释
```javascript
data () {
return {
name: 'zhangsan', // 姓名
age: 18, // 年龄
sex: '男', // 性别
address: '北京市' // 地址
}
}
```
**公共配置文件中的部分函数/方法/过滤器**等css 或者样式选填)
```javascript
/*
* @name 函数名
* @author 作者姓名
* @created_date 创建时间 2018.07.05
* @description 函数功能和使用描述
* @param {参数类型} 参数名称,如: date 字符串日期 “20200101”
* @param {参数类型} 参数名称
* @return 没有返回信息写 void / 有返回信息 {返回类型} 描述信息
*/
```
修该的情况(追加)
```javascript
/*
* @modified by 修改者姓名
* @modified_date 修该时间2018.07.05
* @description 修该点
*/
```
**函数:**每个 js 函数添加注释js函数的关键逻辑流程、判断、变量处理方式等)添加注释说明
```javascript
/*
* 函数名
* @description 函数功能和使用描述
* @param {参数类型} 参数名称,如: date 字符串日期 “20200101”
* @param {参数类型} 参数名称
* @return 没有返回信息写 void / 有返回信息 {返回类型} 描述信息
*/
```
```text
// 判断 xxxx 如果xxxx则xxxx
ifxxxx) {
} else {
}
```
**TODO 标记**
如果某段代码有功能未实现,或者有待完善,必须添加 **TODO **标记,**TODO **后应留一个**空格**。例如:
```javascript
submit () {
// TODO 今天偷懒了,明天补上
}
```
开发中不允许写死数据,如需测试数据,要添加 **TODO **标记备注,如:
```text
userName: '小明' // TODO 测试数据,待修改
```
## 2.3 样式规范
### 2.3.1 数值与单位
- 当属性值或颜色参数为 0 - 1 之间的数时,省略小数点前的 0
`~~color: rgba(255, 255, 255, 0.5)~~`
`color: rgba(255, 255, 255, .5);`
- 当长度值为 0 时省略单位。
`~~margin: 0px auto left: 0px;~~`~~ ~~
`margin: 0 auto; left: 0;`
- 十六进制的颜色属性值使用小写和尽量简写。
`~~color: #ffcc00~~`
`color: #fc0;`
### 2.3.2 样式属性顺序
单个样式规则下的属性在书写时,应按功能进行分组,并以 **Positioning Model > Box Model > Typographic > Visual** 的顺序书写,提高代码的可读性。
- 如果包含 **content **属性,应放在最前面;
- **Positioning Model **布局方式、位置,相关属性包括:**position / top / right / bottom / left / z-index / display / float / ...**
- **Box Model** 盒模型,相关属性包括:**width / height / padding / margin / border / overflow / ...**
- **Typographic **文本排版,相关属性包括:**font / line-height / text-align / word-wrap / ...**
- **Visual** 视觉外观,相关属性包括:**color / background / list-style / transform / animation / transition / ...**
**Positioning** 处在第一位,因为他可以使一个元素脱离正常文本流,并且覆盖盒模型相关的样式。盒模型紧跟其后,因为他决定了一个组件的大小和位置。其他属性只在组件内部起作用或者不会对前面两种情况的结果产生影响,所以他们排在后面。
### 2.3.3 合理使用使用引号
在某些样式中,会出现一些含有空格的关键字或者中文关键字。
- **font-family** 内使用引号
当字体名字中间有空格,中文名字体及 Unicode 字符编码表示的中文字体,为了保证兼容性,都建议在字体两端添加单引号:
![](https://tcs-devops.aliyuncs.com/storage/112w75cdfcd5908c865e3b0742ea09b595b8?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc3NWNkZmNkNTkwOGM4NjVlM2IwNzQyZWEwOWI1OTViOCJ9.Az4VaavZjA-f4CDCF8N4skSjZnUVud9H-Aokjg5tyaE&download=image.png "")
- **background-image** 的 url内使用引号
如果路径里面有空格,旧版 IE 是无法识别的,会导致路径失效,所以不管是否有空格,都加上单引号:
![](https://tcs-devops.aliyuncs.com/storage/112w53e833aad445d15648eefab3fc990065?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMnc1M2U4MzNhYWQ0NDVkMTU2NDhlZWZhYjNmYzk5MDA2NSJ9.Lj-EsJKoh55ChrEIY0mxzn--ifR5zZNs0lePfhsisgk&download=image.png "")
### 2.3.4 避免使用!important
`!important` 的存在会给后期维护以及多人协作带来噩梦般的影响。当存在样式覆盖层叠时,如果你发现新定义的一个样式无法覆盖一个旧的样式,只有加上 `!important` 才能生效时,是因为你新定义的选择器的优先级不够旧样式选择器的优先级高。所以,合理的书写新样式选择器,是完全可以规避一些看似需要使用 `!important` 的情况的。
### 2.3.5 避免使用行内样式
行内样式指的是将CSS代码直接写在标签的style属性中这种写法虽然简单但是可能会造成代码混乱难以维护。
![](https://tcs-devops.aliyuncs.com/storage/112wf5167a002a49660d07352e054cfaef2a?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY5MDk0MDU3OSwiaWF0IjoxNjkwMzM1Nzc5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMndmNTE2N2EwMDJhNDk2NjBkMDczNTJlMDU0Y2ZhZWYyYSJ9._D7p41D3rMf7YQeFu6tpn7lIeANDsDrpMSriwgi30jM&download=image.png "")
### 2.3.6 避免不同样式应用方法混杂
在一个页面中保证只使用一种方法进行样式引入,以保证代码的整洁和一致,提高代码的可读性和可维护性
### 2.3.7 避免使用 Id 选择器进行样式绑定
在 Vue.js 和其他现代前端框架中,通常推荐以组件为单位进行样式的定义和管理,而组件的特性是可重用和可复制的,但是 ID 在一个 HTML 文档中必须是唯一的,所以如果你在组件的样式中使用 ID 选择器,当这个组件被重复使用时,就会造成 ID 冲突。
因此,应该尽量避免在 Vue.js 组件的样式中使用 ID 选择器。取而代之的是,你可以使用类选择器或属性选择器来定义样式,这样既可以保证样式的优先级不会过高,也可以避免 ID 冲突的问题。
## 2.4 JavaScrpit 规范
- 变量声明、表达式、return、throw、break、continue、do-while结束要加分号。
- 用'===', '!=='代替'==', '!='
- 不要在同个作用域下声明同名变量;不要使用未声明的变量;不要声明了变量却不使用。
# 三、注意事项
## 3.1 通用事项
1. 开发时添加注释,新增或修改.html/.js/.vue/.css 文件等添加注释注意格式参照2.2.6
1. 调用对象方法/CSS3/HTML5 考虑兼容性,防止页面布局错乱(`document.body.clientWidth `||` document.documentElement.clientWidth`
1. 调用接口时,注意上送参数格式(如金额、日期)
1. 开发过程中,页面中 `data` 里的变量必须添加注释
1. 前端获取重要数据在页面展示时,防止后端数据未返回,前端需考虑对此字段做缺省值处理,非判空处理
1. `new Date(date).getTime()`方法获取时间戳,在苹果手机上不兼容,返回 NAN原因ios 下只能解析反斜杠/而无法解析-导致的,解决办法:`new Date(date.replace(/-/g,'/')).getTime() `
1. 神策埋点 事件名(可不一致),属性名一致情况下,该属性值类型必须保持一致,否则导致后者埋点失败,若提供的神策埋点存在此问题,及时与模块负责人同步
1. 开发、测试、回归环境合并代码若存在冲突处理,再冲突处理完成后进行代码比对
1. 判空处理需与提供方(后端-接口、客户端-插件)确认为空返回的数据格式,切勿自行认定
1. 多考虑不同场景,做好影响性分析,切勿影响存量逻辑,或修改通用规则,全量排查后进行修改,切勿遗漏
1. 未登录场景调用接口,需与后端确认接口是否支持未登录调用
1. 接口涉及上送金额,统一使用公共方法(`$Fw.util.Format.formatAmt`)做金额格式转换接口金额字段要求:字符串、保留 2 位小数、反格式化
## 3.2 手机银行事项
### 3.2.1 公共 js
1. 涉及金额计算,请使用公共方法(`$Fw.add``$Fw.Numsub``$Fw.mul``$Fw.division`)进行加减乘除-**避免精度问题**
1. 通过公共方法(`$Fw.util.Format.getToday`)进行获取前几日、几月、几年-**页面中若使用 getToday 获取前几日/天/年方法,存在问题,对于特殊月份 2 月取值计算有误**
1. 接口涉及上送金额,统一使用公共方法(`$Fw.util.Format.formatAmt`)做金额格式转换 接口金额字段要求:字符串、保留 2 位小数、反格式化-**所有接口涉及上送金额字段,需要保留两位小数上送,如客户输入 100接口上送时需要上送 100.00,否则导致接口报错**
### 3.2.2 页面渲染
1. 账号、金额等涉及接口上送字段,在页面使用过滤器进行格式化处理,不改变原有值-**js 中进行格式化处理,在上送时需反格式化处理,易遗漏**
1. 若需展示人民币符号,请复制粘贴"¥"此符号进行替换-**手动输入为错误符号¥,安卓机型可复现问题**
1. 调用接口,若字段为空,返回数据中无此字段,需做判空处理-**若返回无此字段页面展示undefined**
### 3.2.3 代码规范
1. 删除页面多余的代码(模拟数据、方法)
1. 代码中判断条件语句不要用中文作为判断依据
1. 严格按照 eslint 规范,类型判断是 string 还是 number 类型要区分清楚
1. css、js、文件命名统一按照规范文档命名
### 3.2.4 功能逻辑
1. **交易完成后跳转结果页面,结果页需返回至首页,不可返回上页**(根据功能区分),不可出现死循环跳转
1. 添加埋点时,调用接口 fail 回调中加埋点变量时,需加报错弹窗 -**fail 自定义设置后,会默认不提示错误信息,需手动弹窗提示**
1. 调用接口若有 loading 加载框fail 回调中需主动关闭 loading
1. 功能需求修改,需分析游客,非游客,登录,非登录,强弱认证以及当前页面接口数据是否返回为空对页面加载是否有影响-**不同条件会影响页面加载**
1. 新增功能需考虑是否支持未登录、游客身份客户,是否支持村行,功能优化需考虑是否涉及温情版改造
1. 功能界面若需登录/或游客认证,应考虑是否存在营销广告位、在线客服等不可控登录/游客入口进入
### 3.2.5 交互设计
1. 首次查询时不应展示上拉加载组件,应加判断条件,接口查询出数据后展示
1. 点击范围区域扩大
1. 功能首页涉及内容较多建议分组件开发、维护,各组件的生命周期中写对应方法—局部加载
1. tab 页面,仅首次点击时需做查询,无需每次点击时反复请求,非首次切换后,**客户可手动下拉刷新**,上拉加载;点击同一个 tab 页签,不做刷新处理
1. 页面涉及多接口调用,可自定义控制 loading 展示以及关闭,避免加载断层
1. 涉及**下一步展示密码弹窗场景,需自动弹起键盘,无需客户手动再次点击**,此项纳入概要设计、代码检查规范中