This commit is contained in:
邓晓坤
2019-09-12 16:22:38 +08:00
parent 90ea054ae0
commit ff8a261f79
195 changed files with 65268 additions and 0 deletions

2
.browserslistrc Normal file
View File

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

7
.env.development Normal file
View File

@@ -0,0 +1,7 @@
# env
NODE_ENV = 'development'
# flag
VUE_APP_FLAG='development'

7
.env.production Normal file
View File

@@ -0,0 +1,7 @@
# env
NODE_ENV = 'production'
# flag
VUE_APP_FLAG='production'

5
.env.staging Normal file
View File

@@ -0,0 +1,5 @@
# env
NODE_ENV = 'production'
# flag
VUE_APP_FLAG='staging'

3
.eslintignore Normal file
View File

@@ -0,0 +1,3 @@
public
dist
node_modules

15
.eslintrc.js Normal file
View File

@@ -0,0 +1,15 @@
module.exports = {
root: true,
env: {
node: true
},
extends: ['plugin:vue/essential', '@vue/prettier'],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'prettier/prettier': 'error'
},
parserOptions: {
parser: 'babel-eslint'
}
}

6
.prettierrc Normal file
View File

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

144
README.md Normal file
View File

@@ -0,0 +1,144 @@
# ebiz-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 + ...
## 目录结构
```
.
├── node_modules // npm/yarn安装的项目依赖模块
├── public // 静态资源目录
├── src // 源码目录
│   ├── api // 网络请求文件
│   │   ├── app // 基础工程网络请求文件
│   │   │   ├── user.js // 用户模块api请求
│   │   ├── example
│   │   │   └── *** // 示例模块api请求
│   ├── assets // 资源目录
│   │   ├── fonts // 字体文件
│   │   ├── images // 图片文件
│   │   | ├── app // 基础工程图片
│   │   | ├── 404_img // 404图片
│   │   ├── js
│   │   | ├── utils //工具类js
│   │   | | ├── get-url.js //根据设置获取请求url
│   │   | | ├── jump.js //跳转文件 bridge or router
│   │   | | ├── 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.development // 开发环境配置
├── .env.production // 生产环境配置
├── .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/dcrs/ebiz-h5.git
cd ebiz-h5
yarn install推荐使用yarn
yarn serve开发环境
```
## 项目打包
```bash
# 测试环境打包
yarn run build:stage测试环境打包
# 线上环境打包
yarn run build:prod线上环境打包
```
## 预发环境打包预览、文件检查等
```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 目录下创建所需状态管理文件
## 主要功能点介绍
- 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.VUE_APP_FLAG 对环境进行配置
- 跨域问题可通过后台解决,也可设置前端代理 proxy
- router
- 模块划分
- 路由拦截
- 路由懒加载
- 权限控制
- 可在 permission.js 里设置黑白名单

14
babel.config.js Normal file
View File

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

30
jest.config.js Normal file
View File

@@ -0,0 +1,30 @@
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'
]
}

15750
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

52
package.json Normal file
View File

@@ -0,0 +1,52 @@
{
"name": "ebiz-h5",
"version": "1.0.0",
"description": "鼎诚人寿",
"author": "wangfangbo <wang.fangbo@ebiz-fooge.com>",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging",
"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": {
"axios": "^0.19.0",
"core-js": "^2.6.5",
"echarts": "^4.2.1",
"fastclick": "^1.0.6",
"js-base64": "^2.5.1",
"nprogress": "^0.2.0",
"pdfh5": "^1.2.13",
"vant": "2.2.0",
"vee-validate": "^2.2.14",
"vue": "^2.6.10",
"vue-pdf": "^4.0.7",
"vue-router": "^3.0.3",
"vuex": "^3.0.1",
"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",
"eruda": "^1.5.7",
"eslint": "^5.16.0",
"eslint-plugin-prettier": "^3.1.0",
"eslint-plugin-vue": "^5.0.0",
"node-sass": "^4.9.0",
"postcss-px-to-viewport": "^1.1.1",
"sass-loader": "^7.1.0",
"vue-template-compiler": "^2.6.10"
}
}

5
postcss.config.js Normal file
View File

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

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

21
public/index.html Normal file
View File

@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<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" />
<title></title>
<script src="<%= BASE_URL %>js/EWebBridge.js"></script>
</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 -->
<!-- <script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script> -->
<script src="https://cdn.bootcss.com/echarts/4.2.1-rc1/echarts.min.js"></script>
</body>
</html>

250
public/js/EWebBridge.js Normal file
View File

@@ -0,0 +1,250 @@
'use strict'
// Promise ES6 polyfill https://github.com/taylorhakes/promise-polyfill, 如果此polyfill依然无法满足需求那么可以引入https://github.com/stefanpenner/es6-promise
!(function(e) {
function n() {}
function t(e, n) {
return function() {
e.apply(n, arguments)
}
}
function o(e) {
if ('object' != typeof this) throw new TypeError('Promises must be constructed via new')
if ('function' != typeof e) throw new TypeError('not a function')
;(this._state = 0), (this._handled = !1), (this._value = void 0), (this._deferreds = []), s(e, this)
}
function i(e, n) {
for (; 3 === e._state; ) e = e._value
return 0 === e._state
? void e._deferreds.push(n)
: ((e._handled = !0),
void o._immediateFn(function() {
var t = 1 === e._state ? n.onFulfilled : n.onRejected
if (null === t) return void (1 === e._state ? r : u)(n.promise, e._value)
var o
try {
o = t(e._value)
} catch (i) {
return void u(n.promise, i)
}
r(n.promise, o)
}))
}
function r(e, n) {
try {
if (n === e) throw new TypeError('A promise cannot be resolved with itself.')
if (n && ('object' == typeof n || 'function' == typeof n)) {
var i = n.then
if (n instanceof o) return (e._state = 3), (e._value = n), void f(e)
if ('function' == typeof i) return void s(t(i, n), e)
}
;(e._state = 1), (e._value = n), f(e)
} catch (r) {
u(e, r)
}
}
function u(e, n) {
;(e._state = 2), (e._value = n), f(e)
}
function f(e) {
2 === e._state &&
0 === e._deferreds.length &&
o._immediateFn(function() {
e._handled || o._unhandledRejectionFn(e._value)
})
for (var n = 0, t = e._deferreds.length; n < t; n++) i(e, e._deferreds[n])
e._deferreds = null
}
function c(e, n, t) {
;(this.onFulfilled = 'function' == typeof e ? e : null), (this.onRejected = 'function' == typeof n ? n : null), (this.promise = t)
}
function s(e, n) {
var t = !1
try {
e(
function(e) {
t || ((t = !0), r(n, e))
},
function(e) {
t || ((t = !0), u(n, e))
}
)
} catch (o) {
if (t) return
;(t = !0), u(n, o)
}
}
var a = setTimeout
;(o.prototype['catch'] = function(e) {
return this.then(null, e)
}),
(o.prototype.then = function(e, t) {
var o = new this.constructor(n)
return i(this, new c(e, t, o)), o
}),
(o.all = function(e) {
var n = Array.prototype.slice.call(e)
return new o(function(e, t) {
function o(r, u) {
try {
if (u && ('object' == typeof u || 'function' == typeof u)) {
var f = u.then
if ('function' == typeof f)
return void f.call(
u,
function(e) {
o(r, e)
},
t
)
}
;(n[r] = u), 0 === --i && e(n)
} catch (c) {
t(c)
}
}
if (0 === n.length) return e([])
for (var i = n.length, r = 0; r < n.length; r++) o(r, n[r])
})
}),
(o.resolve = function(e) {
return e && 'object' == typeof e && e.constructor === o
? e
: new o(function(n) {
n(e)
})
}),
(o.reject = function(e) {
return new o(function(n, t) {
t(e)
})
}),
(o.race = function(e) {
return new o(function(n, t) {
for (var o = 0, i = e.length; o < i; o++) e[o].then(n, t)
})
}),
(o._immediateFn =
('function' == typeof setImmediate &&
function(e) {
setImmediate(e)
}) ||
function(e) {
a(e, 0)
}),
(o._unhandledRejectionFn = function(e) {
'undefined' != typeof console && console && console.warn('Possible Unhandled Promise Rejection:', e)
}),
(o._setImmediateFn = function(e) {
o._immediateFn = e
}),
(o._setUnhandledRejectionFn = function(e) {
o._unhandledRejectionFn = e
}),
'undefined' != typeof module && module.exports ? (module.exports = o) : e.Promise || (e.Promise = o)
})(this)
function appCallBack() {}
;(function(window) {
if (window.EWebBridge) {
return
}
// 初始化App桥接环境
function setupWebViewJavascriptBridge(callback) {
// Android 调用
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady',
function() {
callback(WebViewJavascriptBridge)
},
false
)
}
// iOS使用
if (navigator.userAgent.indexOf('iPhone') != -1) {
/*
// WebViewJavascriptBridge v5
if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
window.WVJBCallbacks = [callback];
var WVJBIframe = document.createElement('iframe');
WVJBIframe.style.display = 'none';
WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
*/
// WebViewJavascriptBridge v6
if (window.WebViewJavascriptBridge) {
return callback(WebViewJavascriptBridge)
}
if (window.WVJBCallbacks) {
return window.WVJBCallbacks.push(callback)
}
window.WVJBCallbacks = [callback]
var WVJBIframe = document.createElement('iframe')
WVJBIframe.style.display = 'none'
WVJBIframe.src = 'https://__bridge_loaded__'
document.documentElement.appendChild(WVJBIframe)
setTimeout(function() {
document.documentElement.removeChild(WVJBIframe)
}, 0)
}
}
// App桥接调用初始化
setupWebViewJavascriptBridge(function(bridge) {
//桥接默认
/*
// Iphone/iOS WebViewJavascriptBridge v6 桥接上面没有注册init函数
bridge.init(function(message, responseCallback) {
console.log('JS got a message', message)
var data = {
'Javascript Responds': 'hello!'
}
console.log('JS responding with', data)
responseCallback(data)
})
*/
bridge.registerHandler('appCallWebInJs', function(data, responseCallback) {
try {
data = JSON.parse(data)
//业务逻辑放在这里;
appCallBack(data, true)
responseCallback('{"code": "0","message": "success"}')
} catch (e) {
appCallBack({}, false)
responseCallback('{"code": "1","message": "App调用JS异常:"' + e + '"}')
}
})
})
// H5 & webapp 调用APP并返回一个Promise对象
function triggerCallHandler(method, params) {
return new Promise(function(resolve) {
WebViewJavascriptBridge.callHandler(method, params, function(response) {
resolve(response)
})
})
}
// 初始化SDK
var EWebBridge = (window.EWebBridge = {
webCallAppInJs: function(method, params) {
// params --> Mixed (json对象 {"a":"123","b":"200"} 或 null 或其他形式的参数具体根据和app端的约定来)
method = method || 'getUserToken'
params = params || null
return triggerCallHandler(method, params)
}
})
})(window)
//notation: js file can only use this kind of comments
//since comments will cause error when use in webview.loadurl,
//comments will be remove by java use regexp

390
public/js/EWebBridge1.js Normal file
View File

@@ -0,0 +1,390 @@
'use strict'
// Promise ES6 polyfill https://github.com/taylorhakes/promise-polyfill, 如果此polyfill依然无法满足需求那么可以引入https://github.com/stefanpenner/es6-promise
!(function(e) {
function n() {}
function t(e, n) {
return function() {
e.apply(n, arguments)
}
}
function o(e) {
if ('object' != typeof this) throw new TypeError('Promises must be constructed via new')
if ('function' != typeof e) throw new TypeError('not a function')
;(this._state = 0), (this._handled = !1), (this._value = void 0), (this._deferreds = []), s(e, this)
}
function i(e, n) {
for (; 3 === e._state; ) e = e._value
return 0 === e._state
? void e._deferreds.push(n)
: ((e._handled = !0),
void o._immediateFn(function() {
var t = 1 === e._state ? n.onFulfilled : n.onRejected
if (null === t) return void (1 === e._state ? r : u)(n.promise, e._value)
var o
try {
o = t(e._value)
} catch (i) {
return void u(n.promise, i)
}
r(n.promise, o)
}))
}
function r(e, n) {
try {
if (n === e) throw new TypeError('A promise cannot be resolved with itself.')
if (n && ('object' == typeof n || 'function' == typeof n)) {
var i = n.then
if (n instanceof o) return (e._state = 3), (e._value = n), void f(e)
if ('function' == typeof i) return void s(t(i, n), e)
}
;(e._state = 1), (e._value = n), f(e)
} catch (r) {
u(e, r)
}
}
function u(e, n) {
;(e._state = 2), (e._value = n), f(e)
}
function f(e) {
2 === e._state &&
0 === e._deferreds.length &&
o._immediateFn(function() {
e._handled || o._unhandledRejectionFn(e._value)
})
for (var n = 0, t = e._deferreds.length; n < t; n++) i(e, e._deferreds[n])
e._deferreds = null
}
function c(e, n, t) {
;(this.onFulfilled = 'function' == typeof e ? e : null), (this.onRejected = 'function' == typeof n ? n : null), (this.promise = t)
}
function s(e, n) {
var t = !1
try {
e(
function(e) {
t || ((t = !0), r(n, e))
},
function(e) {
t || ((t = !0), u(n, e))
}
)
} catch (o) {
if (t) return
;(t = !0), u(n, o)
}
}
var a = setTimeout
;(o.prototype['catch'] = function(e) {
return this.then(null, e)
}),
(o.prototype.then = function(e, t) {
var o = new this.constructor(n)
return i(this, new c(e, t, o)), o
}),
(o.all = function(e) {
var n = Array.prototype.slice.call(e)
return new o(function(e, t) {
function o(r, u) {
try {
if (u && ('object' == typeof u || 'function' == typeof u)) {
var f = u.then
if ('function' == typeof f)
return void f.call(
u,
function(e) {
o(r, e)
},
t
)
}
;(n[r] = u), 0 === --i && e(n)
} catch (c) {
t(c)
}
}
if (0 === n.length) return e([])
for (var i = n.length, r = 0; r < n.length; r++) o(r, n[r])
})
}),
(o.resolve = function(e) {
return e && 'object' == typeof e && e.constructor === o
? e
: new o(function(n) {
n(e)
})
}),
(o.reject = function(e) {
return new o(function(n, t) {
t(e)
})
}),
(o.race = function(e) {
return new o(function(n, t) {
for (var o = 0, i = e.length; o < i; o++) e[o].then(n, t)
})
}),
(o._immediateFn =
('function' == typeof setImmediate &&
function(e) {
setImmediate(e)
}) ||
function(e) {
a(e, 0)
}),
(o._unhandledRejectionFn = function(e) {
'undefined' != typeof console && console && console.warn('Possible Unhandled Promise Rejection:', e)
}),
(o._setImmediateFn = function(e) {
o._immediateFn = e
}),
(o._setUnhandledRejectionFn = function(e) {
o._unhandledRejectionFn = e
}),
'undefined' != typeof module && module.exports ? (module.exports = o) : e.Promise || (e.Promise = o)
})(this)
function appCallBack() {}
;(function(window) {
if (window.EWebBridge) {
return
}
// 初始化App桥接环境
function setupWebViewJavascriptBridge(callback) {
// Android 调用
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady',
function() {
callback(WebViewJavascriptBridge)
},
false
)
}
// iOS使用
if (navigator.userAgent.indexOf('iPhone') != -1) {
// WebViewJavascriptBridge v6
if (window.WebViewJavascriptBridge) {
return callback(WebViewJavascriptBridge)
}
if (window.WVJBCallbacks) {
return window.WVJBCallbacks.push(callback)
}
window.WVJBCallbacks = [callback]
var WVJBIframe = document.createElement('iframe')
WVJBIframe.style.display = 'none'
WVJBIframe.src = 'https://__bridge_loaded__'
document.documentElement.appendChild(WVJBIframe)
setTimeout(function() {
document.documentElement.removeChild(WVJBIframe)
}, 0)
}
}
// App桥接调用初始化
setupWebViewJavascriptBridge(function(bridge) {
bridge.registerHandler('appCallWebInJs', function(data, responseCallback) {
try {
data = JSON.parse(data)
//业务逻辑放在这里;
appCallBack(data, true)
responseCallback('{"code": "0","message": "success"}')
} catch (e) {
appCallBack({}, false)
responseCallback('{"code": "1","message": "App调用JS异常:"' + e + '"}')
}
})
})
// H5 & webapp 调用APP并返回一个Promise对象
function triggerCallHandler(method, params) {
return new Promise(function(resolve) {
WebViewJavascriptBridge.callHandler(method, params, function(response) {
resolve(response)
})
})
}
//解析url参数
function getQuery() {
var query = window.location.href.split('?')
query = query.length > 1 ? query[1].split('&') : []
var json = {}
for (var i = 0, len = query.length; i < len; i++) {
var key = query[i].split('=')[0],
index = query[i].indexOf('='),
value = query[i].substr(index + 1)
json[key] = value
}
return json
}
// 初始化SDK
var EWebBridge = (window.EWebBridge = {
webCallAppInJs: function(method, params, debugCallback) {
// params --> Mixed (json对象 {"a":"123","b":"200"} 或 null 或其他形式的参数具体根据和app端的约定来)
method = method || 'getUserToken'
params = params || null
var queryParam = getQuery()
if (queryParam.workinapp == 1) {
return triggerCallHandler(method, params)
} else {
debugCallback && typeof debugCallback === 'function' && debugCallback()
}
}
})
})(window)
//notation: js file can only use this kind of comments
//since comments will cause error when use in webview.loadurl,
//comments will be remove by java use regexp
;(function() {
//If iPhone Call it, then return
if (window.WebViewJavascriptBridge || navigator.userAgent.indexOf('iPhone') != -1) {
return
}
var messagingIframe
var sendMessageQueue = []
var receiveMessageQueue = []
var messageHandlers = {}
var CUSTOM_PROTOCOL_SCHEME = 'yy'
var QUEUE_HAS_MESSAGE = '__QUEUE_MESSAGE__/'
var responseCallbacks = {}
var uniqueId = 1
function _createQueueReadyIframe(doc) {
messagingIframe = doc.createElement('iframe')
messagingIframe.style.display = 'none'
doc.documentElement.appendChild(messagingIframe)
}
//set default messageHandler
function init(messageHandler) {
if (WebViewJavascriptBridge._messageHandler) {
throw new Error('WebViewJavascriptBridge.init called twice')
}
WebViewJavascriptBridge._messageHandler = messageHandler
var receivedMessages = receiveMessageQueue
receiveMessageQueue = null
for (var i = 0; i < receivedMessages.length; i++) {
_dispatchMessageFromNative(receivedMessages[i])
}
}
function send(data, responseCallback) {
_doSend(
{
data: data
},
responseCallback
)
}
function registerHandler(handlerName, handler) {
messageHandlers[handlerName] = handler
}
function callHandler(handlerName, data, responseCallback) {
_doSend(
{
handlerName: handlerName,
data: data
},
responseCallback
)
}
//sendMessage add message, 触发native处理 sendMessage
function _doSend(message, responseCallback) {
if (responseCallback) {
var callbackId = 'cb_' + uniqueId++ + '_' + new Date().getTime()
responseCallbacks[callbackId] = responseCallback
message.callbackId = callbackId
}
sendMessageQueue.push(message)
messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE
}
// 提供给native调用,该函数作用:获取sendMessageQueue返回给native,由于android不能直接获取返回的内容,所以使用url shouldOverrideUrlLoading 的方式返回内容
function _fetchQueue() {
var messageQueueString = JSON.stringify(sendMessageQueue)
sendMessageQueue = []
//android can't read directly the return data, so we can reload iframe src to communicate with java
messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://return/_fetchQueue/' + encodeURIComponent(messageQueueString)
}
//提供给native使用,
function _dispatchMessageFromNative(messageJSON) {
setTimeout(function() {
var message = JSON.parse(messageJSON)
var responseCallback
//java call finished, now need to call js callback function
if (message.responseId) {
responseCallback = responseCallbacks[message.responseId]
if (!responseCallback) {
return
}
responseCallback(message.responseData)
delete responseCallbacks[message.responseId]
} else {
//直接发送
if (message.callbackId) {
var callbackResponseId = message.callbackId
responseCallback = function(responseData) {
_doSend({
responseId: callbackResponseId,
responseData: responseData
})
}
}
var handler = WebViewJavascriptBridge._messageHandler
if (message.handlerName) {
handler = messageHandlers[message.handlerName]
}
//查找指定handler
try {
handler(message.data, responseCallback)
} catch (exception) {
if (typeof console != 'undefined') {
console.log('WebViewJavascriptBridge: WARNING: javascript handler threw.', message, exception)
}
}
}
})
}
//提供给native调用,receiveMessageQueue 在会在页面加载完后赋值为null,所以
function _handleMessageFromNative(messageJSON) {
console.log(messageJSON)
if (receiveMessageQueue && receiveMessageQueue.length > 0) {
receiveMessageQueue.push(messageJSON)
} else {
_dispatchMessageFromNative(messageJSON)
}
}
var WebViewJavascriptBridge = (window.WebViewJavascriptBridge = {
init: init,
send: send,
registerHandler: registerHandler,
callHandler: callHandler,
_fetchQueue: _fetchQueue,
_handleMessageFromNative: _handleMessageFromNative
})
var doc = document
_createQueueReadyIframe(doc)
var readyEvent = doc.createEvent('Events')
readyEvent.initEvent('WebViewJavascriptBridgeReady')
readyEvent.bridge = WebViewJavascriptBridge
doc.dispatchEvent(readyEvent)
})()

72
src/App.vue Normal file
View File

@@ -0,0 +1,72 @@
<template>
<div id="app">
<!--实现路由切换动画-->
<transition :name="transitionName">
<RouterView />
<!-- <keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view> -->
</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;
height: 100%;
}
.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>

28
src/api/app/user.js Normal file
View File

@@ -0,0 +1,28 @@
import request from '@/assets/js/utils/request'
import getUrl from '@/assets/js/utils/get-url'
// 登录
export function login(data) {
return request({
url: getUrl('/user/login', 0),
method: 'post',
data
})
}
// 获取个人信息
export function getInfo(token) {
return request({
url: getUrl('/user/info', 0),
method: 'get',
params: { token }
})
}
// 登出
export function logout() {
return request({
url: getUrl('/user/logout', 0),
method: 'post'
})
}

View File

@@ -0,0 +1,54 @@
import request from '@/assets/js/utils/request'
import getUrl from '@/assets/js/utils/get-url'
// 初始化试算因子
export function calculatePremium(data) {
return request({
url: getUrl(`/${localStorage.isFrom}/product/getDetail`, 1), //根据来源 判断 调用建议书接口/电投接口
method: 'post',
data
})
}
// 主险列表
export function mainRiskList(data) {
return request({
url: getUrl(`/${localStorage.isFrom}/product/getMainRiskLst`, 1),
method: 'post',
data
})
}
//试算
export function trial(data) {
return request({
url: getUrl(`/${localStorage.isFrom}/insure/trial`, 1),
method: 'post',
data
})
}
//订单详情
export function orderDetail(data) {
return request({
url: getUrl('/sale/order/orderDetail', 1),
method: 'post',
data
})
}
//删除已选产品
export function deleteOrderInfo(data) {
return request({
url: getUrl('/sale/order/deleteOrderInfo', 1),
method: 'post',
data
})
}
//获取微信分享
export function wxShare(data) {
return request({
url: getUrl('/ppf/wx/config', 1),
method: 'post',
data
})
}

View File

@@ -0,0 +1,38 @@
import request from '@/assets/js/utils/request'
import getUrl from '@/assets/js/utils/get-url'
// 代理人客户列表
export function getCustomersList(data) {
return request({
url: getUrl('/getCustomersList', 0),
method: 'post',
data
})
}
//代理人客户新增与编辑
export function updateCustomerInfo(data) {
return request({
url: getUrl('/updateCustomerInfo', 0),
method: 'post',
data
})
}
//查询代理人客户信息
export function getAgentCustomerInfo(data) {
return request({
url: getUrl('/getAgentCustomerInfo', 0),
method: 'post',
data
})
}
//删除代理人客户信息
export function deleteCustomerInfo(data) {
return request({
url: getUrl('/deleteCustomerInfo', 0),
method: 'post',
data
})
}

48
src/api/ebiz/my/my.js Normal file
View File

@@ -0,0 +1,48 @@
import request from '@/assets/js/utils/request'
import getUrl from '@/assets/js/utils/get-url'
// 登录
export function login(data) {
return request({
url: getUrl('/user/login', 0),
method: 'post',
data
})
}
// 获取个人信息
export function getInfo(token) {
return request({
url: getUrl('/user/info', 0),
method: 'get',
params: { token }
})
}
// 登出
export function logout() {
return request({
url: getUrl('/user/logout', 0),
method: 'post'
})
}
// 获取代理人信息
export function getAgentInfo(data) {
return request({
// url: getUrl('/agent/agent/info', 0),
url: getUrl('/customer/agent/info', 1),
method: 'post',
data
})
}
// 获取代理人收入信息
export function getAgentIncome(data) {
return request({
// url: getUrl('/agent/income/info', 0),
url: getUrl('/agent/agent/income/info', 1),
method: 'post',
data
})
}

View File

@@ -0,0 +1,29 @@
import request from '@/assets/js/utils/request'
import getUrl from '@/assets/js/utils/get-url'
// 获取产品类别
export function getCategory(data) {
return request({
url: getUrl('/sale/product/getCategory', 1),
method: 'post',
data
})
}
// 获取产品列表
export function getList(data) {
return request({
url: getUrl('/sale/product/getProList', 1),
method: 'post',
data
})
}
// 获取产品详情
export function getProductInfo(data) {
return request({
url: getUrl('/sale/product/getItemDetail', 1),
method: 'post',
data
})
}

View File

@@ -0,0 +1,76 @@
import request from '@/assets/js/utils/request'
import getUrl from '@/assets/js/utils/get-url'
// 获取建议书列表
export function getList(data) {
return request({
url: getUrl('/proposal/proposal/list', 1), //0=》mock数据 1=》正式数据
method: 'post',
data
})
}
// 转投保
export function toInsurance(data) {
return request({
url: getUrl('/proposal/proposal/toInsurance', 1), //0=》mock数据 1=》正式数据
method: 'post',
data
})
}
// 获取建议书详情
export function getDetail(data) {
return request({
url: getUrl('/proposal/proposal/info', 1),
method: 'post',
data
})
}
// 获取建议书演示
export function getDemo(data) {
return request({
url: getUrl('/proposal/proposal/demo', 1),
method: 'post',
data
})
}
// 获取建议书演示(分享到微信)
export function getDemoByProposalNo(data) {
return request({
url: getUrl('/proposal/proposal/getDemoByProposalNo', 1),
method: 'post',
data
})
}
// 保存建议书
export function saveProposal(data) {
return request({
url: getUrl('/proposal/proposal/saveOrUpdateProposal', 1),
method: 'post',
data
})
}
// 更新建议书
export function updateInsured(data) {
return request({
url: getUrl('/proposal/proposal/updateInsured', 1),
method: 'post',
data
})
}
// 生成建议书pdf
export function makePdf(data) {
return request({
url: getUrl('/proposal/file/getFile', 1),
method: 'post',
data
})
}
// 删除建议书
export function deleteProposal(data) {
return request({
url: getUrl('/proposal/proposal/deleteProposal', 1),
method: 'post',
data
})
}

135
src/api/ebiz/sale/sale.js Normal file
View File

@@ -0,0 +1,135 @@
import request from '@/assets/js/utils/request'
import getUrl from '@/assets/js/utils/get-url'
// 保费计算
export function saveOrUpdateOrderInfo(data) {
return request({
url: getUrl('/sale/order/saveOrUpdateOrderInfo', 1),
method: 'post',
data
})
}
// 订单列表
export function orderList(data) {
return request({
url: getUrl('/sale/order/orderList', 1),
method: 'post',
data
})
}
// 订单删除
export function deleteOrderInfo(data) {
return request({
url: getUrl('/sale/order/deleteOrderInfo', 1),
method: 'post',
data
})
}
// 获取告知信息
export function information(data) {
return request({
url: getUrl('/sale/product/getDetail', 1),
method: 'post',
data
})
}
// 告知信息保存
export function saveInformation(data) {
return request({
url: getUrl('/sale/order/saveOrUpdateOrderInfo', 1),
method: 'post',
data
})
}
// 获取订单详情
export function getOrderDetail(data) {
return request({
url: getUrl('/sale/order/orderDetail', 1),
method: 'post',
data
})
}
// 获取验证码
export function getAuthCode(data) {
return request({
url: getUrl('/customer/authcode/loginedSend', 1),
method: 'post',
data
})
}
// 上传图片
export function uploadImg(data) {
return request({
url: getUrl('/app/uploadImage', 1, 2),
method: 'post',
data
})
}
// 核保接口
export function underWrite(data) {
return request({
url: getUrl('/sale/insure/underWrite', 1),
method: 'post',
data
})
}
// 支付接口
export function acceptInsurance(data) {
return request({
url: getUrl('/sale/insure/acceptInsurance', 1),
method: 'post',
data
})
}
// 获取银行卡接口
export function getBankList(data) {
return request({
url: getUrl('/app/code/getCodeValue', 1, 2),
method: 'post',
data
})
}
// 获取微信人脸token
export function getToken(data) {
return request({
url: getUrl('/customer/token', 1),
method: 'post',
data
})
}
// 测试
export function test(data) {
return request({
url: getUrl('/media/ebizSignInfo/sign', 1),
method: 'post',
data
})
}
// 提交回执签收
export function submit(data) {
return request({
url: getUrl('/sale/receiptSign/submit', 1),
method: 'post',
data
})
}
// 获取投保单详情接口
export function getDetail(data) {
return request({
url: getUrl('/sale/order/orderDetail', 1),
method: 'post',
data
})
}

View File

@@ -0,0 +1,29 @@
import request from '@/assets/js/utils/request'
import getUrl from '@/assets/js/utils/get-url'
// 获取保单列表
export function getPolicyList(data) {
return request({
url: getUrl('/sale/policy/policyList', 1),
method: 'post',
data
})
}
// 获取保单详情
export function getPolicyDetail(data) {
return request({
url: getUrl('/sale/policy/policyDetail', 1),
method: 'post',
data
})
}
// 获取pdf阅读
export function getReceiptSign(data) {
return request({
url: getUrl('/sale/receiptSign/sign', 1),
method: 'post',
data
})
}

BIN
src/assets/images/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
src/assets/images/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
src/assets/images/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
src/assets/images/4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
src/assets/images/5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
src/assets/images/add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 939 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

BIN
src/assets/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

BIN
src/assets/images/u114.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
src/assets/images/u1192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
src/assets/images/u1194.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 901 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 755 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 719 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 896 B

BIN
src/assets/images/u2198.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

BIN
src/assets/images/u4516.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 B

BIN
src/assets/images/u6071.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
src/assets/images/u6490.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

BIN
src/assets/images/u99.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

View File

@@ -0,0 +1,594 @@
import utilsAge from '@/assets/js/utils/age'
/**
* @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
}
/**
* @desc 时间格式转化
* @param {String} format 转化格式
* @return {String} 已转化的时间
*/
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
},
/**
* @description 去除前后空格
* @param {String} 值
* @return {String}
*/
trim(val) {
return val.replace(/(^\s*)|(\s*$)/g, '')
},
// 获取query特定参数
getQueryParameter() {
let activityFromApp = this.getQuery().activityFromApp
let appUserToken = this.getQuery().appUserToken
let env = this.getQuery().env
let query = {}
if (activityFromApp) {
query.activityFromApp = activityFromApp
}
if (appUserToken) {
query.appUserToken = decodeURIComponent(appUserToken.replace(/%20/g, '+'))
}
if (env) {
query.env = env
}
return query
},
/**
* 替换字符串具体位置字符
* @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('')
},
addSpace(value) {
if (value) {
return value.replace(/\s/g, '').replace(/(.{4})/g, '$1 ')
}
return value
},
// 字符省略
ellipsis(value = '', num = -1) {
if (value) {
let str = ''
if (num > 0 && value.length > num) {
str = '...'
}
return value.slice(0, num) + str
}
return value
},
/**
* @desc 获取 cookie
* @param {String}
* @return {*}
*/
getCookie(name1) {
let rs = ''
var name = name1 + '='
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(name) != -1) {
rs = this._string2json(c.substring(name.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)
},
/**
* 获取设备类型
*/
device() {
let ua = navigator.userAgent
return {
isChrome: ua.match(/Chrome\/([\d.]+)/) || ua.match(/CriOS\/([\d.]+)/),
// eslint-disable-next-line no-useless-escape
isAndroid: ua.match(/(Android);?[\s\/]+([\d.]+)?/),
isIphone: ua.indexOf('iPhone') != -1,
isWeixin: ua.match(/MicroMessenger/i)
}
},
/**
* 设置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
}
},
/**
* @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
},
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
},
/**
* 除法
* @param {Number} dividend 被除数
* @param {Number} divisor 除数
* @return {Number} 值
*/
divide(dividend, divisor = 100) {
if (dividend && divisor) {
dividend = Number(dividend)
return this.toFloatFixed(dividend / divisor)
}
return dividend
},
// 保留小数位替代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
},
/**
* 获取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 {[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
},
// 获取周
getWeek(str) {
let rs = ''
switch (str + '') {
case '1':
rs = '一'
break
case '2':
rs = '二'
break
case '3':
rs = '三'
break
case '4':
rs = '四'
break
case '5':
rs = '五'
break
case '6':
rs = '六'
break
case '7':
case '0':
rs = '日'
break
default:
break
}
return rs
},
// 获取补全的时间
getTime(str) {
if (str < 10) {
return '0' + str
}
return str
},
// 数组去重
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
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
}
},
/**
@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
},
//解析url参数
getQuery() {
var query = []
// 当url是通过传参过来的话我们把第一个参数作为url并进行解析
if (arguments[0]) {
let lnk = document.createElement('a')
lnk.href = arguments[0]
query = this.extractQuery(lnk)
} else {
/*
var query = window.location.search.split('?');
if(query.length <= 1) query = window.location.hash.split('#');
query = query.length > 1 ? query[1].split('&') : []
*/
query = this.extractQuery(window.location)
}
var json = {}
for (var i = 0, len = query.length; i < len; i++) {
var key = query[i].split('=')[0],
index = query[i].indexOf('='),
value = query[i].substr(index + 1)
json[key] = value
}
return json
},
extractQuery(lnk) {
var query = lnk.search.split('?')
//url/#/repairBooking?activityFromApp=1
if (query.length <= 1) query = lnk.hash.split('?')
query = query.length > 1 ? query[1].split('&') : []
return query
},
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
},
//初始化localstorg信息
intLocalStorage(res, isProposal) {
let appntDTO = ''
let insuredDTO = ''
if (isProposal) {
appntDTO = res.appntDTO
insuredDTO = res.insuredDTOs && res.insuredDTOs[0]
} else {
appntDTO = res.orderDTO.appntDTO
insuredDTO = res.orderDTO.insuredDTOs[0]
}
let age = utilsAge.getAge(appntDTO.birthday, new Date())
localStorage.saleInsuredInfo = JSON.stringify({
birthday: appntDTO.birthday,
name: appntDTO.name,
sex: appntDTO.sex,
idType: appntDTO.idType,
age,
idNo: appntDTO.idNo,
appntId: appntDTO.appntId
})
if (insuredDTO) {
let insuredPersonAge = utilsAge.getAge(insuredDTO.birthday, new Date())
localStorage.saleInsuredPersonInfo = JSON.stringify({
birthday: insuredDTO.birthday,
name: insuredDTO.name,
sex: insuredDTO.sex,
idType: insuredDTO.idType,
age: insuredPersonAge,
relationToAppnt: insuredDTO.relationToAppnt,
medical: insuredDTO.medical,
occupationName: insuredDTO.occupationName,
occupationCode: insuredDTO.occupationCode,
insuredId: insuredDTO.insuredId,
idNo: insuredDTO.idNo
})
let [chooseProductCodes, mainRiskCodes, addRiskCodes] = [[], [], []]
if (insuredDTO.riskDTOLst && insuredDTO.riskDTOLst.length > 0) {
insuredDTO.riskDTOLst.forEach(item => {
chooseProductCodes.push(item.riskCode)
if (item.isMainRisk == 0) {
mainRiskCodes.push(item.riskCode)
} else {
addRiskCodes.push(item.riskCode)
}
})
}
localStorage.mainRiskCodes = JSON.stringify(mainRiskCodes)
localStorage.oldAddRiskCodes = JSON.stringify(addRiskCodes)
localStorage.chooseProductCodes = JSON.stringify(chooseProductCodes)
} else {
localStorage.mainRiskCodes = ''
localStorage.oldAddRiskCodes = ''
localStorage.chooseProductCodes = ''
if (!isProposal) {
localStorage.saleInsuredPersonInfo = ''
}
}
},
/*根据出生日期算出年龄*/
jsGetAge(strBirthday) {
var returnAge
var strBirthdayArr = strBirthday.split('-')
var birthYear = strBirthdayArr[0]
var birthMonth = strBirthdayArr[1]
var birthDay = strBirthdayArr[2]
let d = new Date()
var nowYear = d.getFullYear()
var nowMonth = d.getMonth() + 1
var nowDay = d.getDate()
if (nowYear == birthYear) {
returnAge = 0 //同年 则为0岁
} else {
var ageDiff = nowYear - birthYear //年之差
if (ageDiff > 0) {
if (nowMonth == birthMonth) {
var dayDiff = nowDay - birthDay //日之差
if (dayDiff < 0) {
returnAge = ageDiff - 1
} else {
returnAge = ageDiff
}
} else {
var monthDiff = nowMonth - birthMonth //月之差
if (monthDiff < 0) {
returnAge = ageDiff - 1
} else {
returnAge = ageDiff
}
}
} else {
returnAge = -1 //返回-1 表示出生日期输入错误 晚于今天
}
}
return returnAge //返回周岁年龄
}
}

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

@@ -0,0 +1,210 @@
/**
* @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
}
/**
* @desc 时间格式转化
* @param {String} format 转化格式
* @return {String} 已转化的时间
*/
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
},
/**
* @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)
}
}
}

View File

@@ -0,0 +1,53 @@
var chnNumChar = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']
var chnUnitSection = ['', '万', '亿', '万亿', '亿亿']
var chnUnitChar = ['', '十', '百', '千']
function SectionToChinese(section) {
var strIns = '',
chnStr = ''
var unitPos = 0
var zero = true
while (section > 0) {
var v = section % 10
if (v === 0) {
if (!zero) {
zero = true
chnStr = chnNumChar[v] + chnStr
}
} else {
zero = false
strIns = chnNumChar[v]
strIns += chnUnitChar[unitPos]
chnStr = strIns + chnStr
}
unitPos++
section = Math.floor(section / 10)
}
return chnStr
}
export function NumberToChinese(num) {
var unitPos = 0
var strIns = '',
chnStr = ''
var needZero = false
if (num === 0) {
return chnNumChar[0]
}
while (num > 0) {
var section = num % 10000
if (needZero) {
chnStr = chnNumChar[0] + chnStr
}
strIns = SectionToChinese(section)
strIns += section !== 0 ? chnUnitSection[unitPos] : chnUnitSection[0]
chnStr = strIns + chnStr
needZero = section < 1000 && section > 0
num = Math.floor(num / 10000)
unitPos++
}
return chnStr
}

View File

@@ -0,0 +1,57 @@
export default {
getAge: function(name, today) {
return this.getAgeByValue(name, today)
},
getAgeByBirth: function(value, today) {
return this.getAgeByValue(value, today)
},
getAgeByValue: function(value, today) {
var b = value.match(/^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/)
if (b == null) {
return null
} else {
var month = b[3] * 1
var day = b[4] * 1
var nowY = today.getFullYear()
var age = nowY - b[1]
if (today.getMonth() + 1 < month) {
age--
} else if (today.getMonth() + 1 == month && today.getDate() < day) {
age--
}
if (age < 1) {
var dayNum = this.getDateDiff(value, nowY + '-' + (today.getMonth() + 1) + '-' + today.getDate())
if (dayNum <= 28) {
age--
}
}
return age
}
},
/**
* 取得两个日期的时间差
*/
getDateDiff: function(date1, date2) {
var dt1, dt2
if (date1 instanceof Date) {
dt1 = date1
} else {
dt1 = this.stringToDate(date1)
}
if (date2 instanceof Date) {
dt2 = date2
} else {
dt2 = this.stringToDate(date2)
}
return (dt2.getTime() - dt1.getTime()) / (1000 * 3600 * 24) + 1
},
/**
* 字符串转日期
*/
stringToDate: function(string) {
return new Date(Date.parse(string.replace(/-/g, '/')))
}
}

4042
src/assets/js/utils/area.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,443 @@
// 数据字典
export default {
//国家地区
nativeplace: [
{ id: 1, text: '中国大陆' },
{ id: 2, text: '中国香港' },
{ id: 3, text: '中国澳门' },
{ id: 4, text: '中国台湾' },
{ id: 5, text: '英国' },
{ id: 6, text: '印度' },
{ id: 7, text: '意大利' },
{ id: 8, text: '以色列' },
{ id: 9, text: '新西兰' },
{ id: 10, text: '希腊' },
{ id: 11, text: '西班牙' },
{ id: 12, text: '威尔士' },
{ id: 13, text: '泰国' },
{ id: 14, text: '苏格兰' },
{ id: 15, text: '瑞士' },
{ id: 16, text: '瑞典' },
{ id: 17, text: '日本' },
{ id: 18, text: '葡萄牙' },
{ id: 19, text: '挪威' },
{ id: 20, text: '尼日利亚' },
{ id: 21, text: '美国' },
{ id: 22, text: '加拿大' },
{ id: 23, text: '荷兰' },
{ id: 24, text: '韩国' },
{ id: 25, text: '芬兰' },
{ id: 26, text: '法国' },
{ id: 27, text: '俄国' },
{ id: 28, text: '德国' },
{ id: 29, text: '波兰' },
{ id: 30, text: '巴西' },
{ id: 31, text: '澳大利亚' },
{ id: 32, text: '奥地利' },
{ id: 33, text: '爱尔兰' },
{ id: 34, text: '埃及' }
],
//证件类型
idType: [
{ id: 1, text: '身份证' },
{ id: 2, text: '户口本' },
{ id: 3, text: '出生证明' },
{ id: 4, text: '护照' },
{ id: 5, text: '港澳居民通行证' },
{ id: 6, text: '台湾居民通行证' },
{ id: 7, text: '其他' }
],
//投保人证件类型
insuredIdType: [
{ id: 1, text: '身份证' },
{ id: 2, text: '户口本', disabled: true },
{ id: 3, text: '出生证明', disabled: true },
{ id: 4, text: '护照' },
{ id: 5, text: '港澳居民通行证' },
{ id: 6, text: '台湾居民通行证' },
{ id: 7, text: '其他' }
],
//出生证明
birthType: [
{ id: 1, text: '身份证' },
{ id: 2, text: '户口本' },
{ id: 3, text: '出生证明', disabled: true },
{ id: 4, text: '护照' },
{ id: 5, text: '港澳居民通行证' },
{ id: 6, text: '台湾居民通行证' },
{ id: 7, text: '其他' }
],
//投保人/被保人关系
relationToAppnt: [{ id: 1, text: '本人' }, { id: 2, text: '配偶' }, { id: 3, text: '父母' }, { id: 4, text: '子女' }, { id: 5, text: '其他' }],
//婚姻状况
marriage: [{ id: 1, text: '已婚' }, { id: 2, text: '未婚' }, { id: 3, text: '离婚' }, { id: 4, text: '丧偶' }],
//文化程度
degree: [
{ id: 1, text: '博士及以上' },
{ id: 2, text: '硕士' },
{ id: 3, text: '本科' },
{ id: 4, text: '大专' },
{ id: 5, text: '高中' },
{ id: 6, text: '初中' },
{ id: 7, text: '中专' },
{ id: 8, text: '小学' },
{ id: 9, text: '小学以下' }
],
//居民身份 仅支持中国
taxIdentity: [{ id: 1, text: '仅为中国' }, { id: 2, text: '仅为外国', disabled: true }, { id: 3, text: '都是', disabled: true }],
//交费期限
payEndYear: [
{
id: 1,
text: '1年交'
},
{
id: 2,
text: '4年交'
},
{
id: 3,
text: '5年交'
},
{
id: 4,
text: '9年交'
},
{
id: 5,
text: '10年交'
},
{
id: 6,
text: '14年交'
},
{
id: 7,
text: '15年交'
},
{
id: 8,
text: '19年交'
},
{
id: 9,
text: '20年交'
},
{
id: 10,
text: '29年交'
},
{
id: 11,
text: '30年交'
},
{
id: 12,
text: '至75周岁'
}
],
//交费方式
payIntv: [
{
id: 1,
text: '月交',
disabled: true
},
{
id: 2,
text: '季交',
disabled: true
},
{
id: 3,
text: '半年交',
disabled: true
},
{
id: 4,
text: '年交'
},
{
id: 5,
text: '一次交清'
}
],
// 保险期间 data-dictionary
insureYear: [
{
id: 1,
text: '1年'
},
{
id: 2,
text: '4年'
},
{
id: 3,
text: '9年'
},
{
id: 4,
text: '10年'
},
{
id: 5,
text: '14年'
},
{
id: 6,
text: '15年'
},
{
id: 7,
text: '19年'
},
{
id: 8,
text: '20年'
},
{
id: 9,
text: '29年'
},
{
id: 10,
text: '30年'
},
{
id: 11,
text: '至70周岁'
},
{
id: 12,
text: '至75周岁'
},
{
id: 13,
text: '至80周岁'
},
{
id: 14,
text: '终身'
}
],
//客户类型
customerType: [
{
id: 0,
text: '准客户'
},
{
id: 1,
text: '老客户'
}
],
//客户来源
customerSource: [
{
id: 0,
text: '转介绍'
},
{
id: 1,
text: '缘故'
},
{
id: 2,
text: '陌生'
}
],
//在职情况
workCondition: [
{
id: 1,
text: '在职'
},
{
id: 2,
text: '退休'
},
{
id: 3,
text: '其他'
}
],
policyState: [
{
id: '01',
text: '待客户确认'
},
{
id: '02',
text: '待客户付款'
},
{
id: '03',
text: '待公司确认'
},
{
id: '04',
text: '待客户上载影像'
},
{
id: '05',
text: '逾期关闭'
},
{
id: '06',
text: '客户撤销'
},
{
id: '07',
text: '公司谢绝'
},
{
id: '08',
text: '订单成交'
},
{
id: '09',
text: '订单退保'
},
{
id: '10',
text: '订单待签单'
},
{
id: '11',
text: '待生成电子保单'
},
{
id: '12',
text: '退保/领取审核中'
},
{
id: '13',
text: '等待出单'
},
{
id: '14',
text: '支付中'
},
{
id: '15',
text: '支付受理中'
},
{
id: '16',
text: '待手动承保'
},
{
id: '17',
text: '手动承保完成'
},
{
id: '18',
text: '阿里云端数据同步中间状态'
},
{
id: '19',
text: '支付失败'
},
{
id: '20',
text: '待答问卷'
},
{
id: '21',
text: 'ABS保单预约挂起中'
},
{
id: '22',
text: 'ABS保单取消预约挂起中'
},
{
id: '23',
text: '理赔挂起中'
},
{
id: '24',
text: '保单终止'
},
{
id: '25',
text: 'ABS保单受益权转让挂起中'
},
{
id: '26',
text: '保单冻结挂起中'
},
{
id: '27',
text: '冻结受益权转让挂起中'
},
{
id: '28',
text: '受益权还原挂起中'
},
{
id: '29',
text: '受益权转让挂起中'
},
{
id: '30',
text: '受益权还原挂起中'
},
{
id: '31',
text: '续保等待人核'
},
{
id: '32',
text: '续保第一次健康告知异常'
},
{
id: '33',
text: '待人核导核心'
},
{
id: '34',
text: '人核导核心成功'
},
{
id: '35',
text: '投保人保存成功'
},
{
id: '36',
text: '被保人保存成功'
},
{
id: '37',
text: '受益人人保存成功'
},
{
id: '38',
text: '账户信息保存成功'
},
{
id: '39',
text: '险种信息保存成功'
},
{
id: '40',
text: '告知信息保存成功'
},
{
id: '41',
text: '待转批扣'
},
{
id: '42',
text: '转批扣成功'
},
{
id: '43',
text: '待签名'
},
{
id: '44',
text: '计划书转投保'
}
]
}

View File

@@ -0,0 +1,53 @@
export function formatRiskList(list, insureList, riskList) {
list.forEach(list => {
list.firstPrem = 0 //首期总保费
//格式化数据(页面展示)
list[insureList].forEach(insured => {
insured.mainRisk = []
if (insured[riskList] == undefined || insured[riskList] == null || insured[riskList] == '') {
insured[riskList] = []
}
insured[riskList].forEach(main => {
list.firstPrem = ((list.firstPrem * 100 + main.prem * 100) / 100).toFixed(2) //保留两位小数
if (main.isMainRisk == '0') {
//此时为主险
insured.mainRisk.push(main)
}
})
insured.mainRisk.forEach(main => {
main.addtion = []
insured[riskList].forEach(addtion => {
if (addtion.isMainRisk == '1') {
if (main.mainRiskCode == addtion.mainRiskCode) {
main.addtion.push(addtion)
}
}
})
})
})
})
return list
}
export function formatAllRisk(list) {
let riskList = []
list.forEach(risk => {
if (risk.isMainRisk == '0') {
riskList.push(risk)
}
})
riskList.forEach(main => {
main.addtion = []
list.forEach(risk => {
if (risk.isMainRisk == '1') {
if (main.mainRiskCode == risk.mainRiskCode) {
main.addtion.push(risk)
main.prem += risk.prem
}
}
})
})
return riskList
}

View File

@@ -0,0 +1,22 @@
// 获取省市区名称
import area from '@/assets/js/utils/area'
/**
* 获取省市区名称
* @param {String} provinceCode 省级编码
* @param {String} cityCode 市级编码
* @param {String} areaCode 区级编码
* @return {String} 省市区名称
*/
// export default function getAreaName(provinceCode, cityCode, areaCode) {
// return area.province_list[provinceCode] + '-' + area.city_list[cityCode] + '-' + area.county_list[areaCode]
// }
export default function getAreaName(data) {
if (data.length == 3) {
return area.province_list[data[0].code] + '-' + area.city_list[data[1].code] + '-' + area.county_list[data[2].code]
} else {
return area.province_list[data[0].code] + '-' + area.city_list[data[1].code]
}
}

View File

@@ -0,0 +1,15 @@
import config from '@/config'
import urlMap from '@/config/urlMap'
export default function getUrl(url, api = 1, domainType = 1) {
//api默认为1请求接口服务 0 mock服务 1接口服务
//domainType 默认为1取apiDomain可自定义其他域名
let domain = ''
if (domainType == 1) {
domain = config.apiDomain
} else if (domainType == 2) {
domain = config.imgDomain
}
return api === 0 ? urlMap[url] : domain + url
}

View File

@@ -0,0 +1,170 @@
const idNoCheck = {
//是否以9开头
startWithNine: function(card) {
if (card.substr(0, 1) === '9') {
return true
}
return false
},
isCardNo: function(card) {
//身份证号码为15位或者18位15位时全为数字18位前17位为数字最后一位是校验位可能为数字或字符X
var reg = /(^\d{17}(\d|X)$)/
var reg2 = /(^\d{15}$)/
if (!reg.test(card) && !reg2.test(card)) {
return false
}
return true
},
//取身份证前两位,校验省份
checkProvince: function(card) {
var province = card.substr(0, 2)
if (vcity[province] == undefined) {
return false
}
return true
},
//检查生日是否正确
checkBirthday: function(card) {
var len = card.length
//身份证15位时次序为省3位3位2位2位2位校验位3位皆为数字
if (len == '15') {
var re_fifteen = /^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/
var arr_data = card.match(re_fifteen)
var year = arr_data[2]
var month = arr_data[3]
var day = arr_data[4]
var birthday = new Date('19' + year + '/' + month + '/' + day)
return this.verifyBirthday('19' + year, month, day, birthday)
}
//身份证18位时次序为省3位3位4位2位2位校验位4位校验位末尾可能为X
if (len == '18') {
let re_eighteen = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/
let arr_data = card.match(re_eighteen)
let year = arr_data[2]
let month = arr_data[3]
let day = arr_data[4]
let birthday = new Date(year + '/' + month + '/' + day)
return this.verifyBirthday(year, month, day, birthday)
}
return false
},
//校验日期
verifyBirthday: function(year, month, day, birthday) {
var now = new Date()
// var now_year = now.getFullYear()
//年月日是否合理
if (birthday.getFullYear() == year && birthday.getMonth() + 1 == month && birthday.getDate() == day) {
//判断年份的范围0岁到100岁之间)
//var time = now_year - year;
if (year < 1900) {
return false
}
if (now.getTime() - birthday.getTime() < 0) {
return false
}
// if (time >= 0 && time <= 100) {
// return true;
// }
return true
}
return false
},
//校验位的检测
checkParity: function(card) {
//15位转18位
//card = changeFivteenToEighteen(card);
var len = card.length
if (len == '18') {
var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2)
var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2')
var cardTemp = 0,
i,
valnum
for (i = 0; i < 17; i++) {
cardTemp += card.substr(i, 1) * arrInt[i]
}
valnum = arrCh[cardTemp % 11]
if (valnum == card.substr(17, 1)) {
return true
}
return false
}
return false
},
/**
* 身份证校验
*
*/
isIdno: function(idNo) {
//是否为空
if (idNo === '') {
return false
}
//校验长度,类型
if (this.isCardNo(idNo) === false) {
return false
}
if (this.startWithNine(idNo) === true) {
return false
}
//检查省份 --
// if (this.checkProvince(idNo) === false) {
// return false;
// }
//校验生日
if (this.checkBirthday(idNo) === false) {
return false
}
//检验位的检测
if (this.checkParity(idNo) === false) {
return false
}
return true
}
}
const vcity = {
11: '北京',
12: '天津',
13: '河北',
14: '山西',
15: '内蒙古',
21: '辽宁',
22: '吉林',
23: '黑龙江',
31: '上海',
32: '江苏',
33: '浙江',
34: '安徽',
35: '福建',
36: '江西',
37: '山东',
41: '河南',
42: '湖北',
43: '湖南',
44: '广东',
45: '广西',
46: '海南',
50: '重庆',
51: '四川',
52: '贵州',
53: '云南',
54: '西藏',
61: '陕西',
62: '甘肃',
63: '青海',
64: '宁夏',
65: '新疆',
71: '台湾',
81: '香港',
82: '澳门',
91: '国外'
}
export default idNoCheck

View File

@@ -0,0 +1,28 @@
/* eslint-disable no-undef */
export default function jump(options) {
// eslint-disable
if (window.WebViewJavascriptBridge && options.flag) {
if (options.flag == 'h5') {
EWebBridge.webCallAppInJs('bridge', {
flag: options.flag,
extra: options.extra
})
} else {
//extra 参数说明 refresh: '1', //是否返回后刷新01是 index: '-2' //回退两级
if (options.extra) {
EWebBridge.webCallAppInJs(options.flag, options.extra)
} else {
EWebBridge.webCallAppInJs(options.flag)
}
}
} else {
// 1:replace 2:go 默认为push
if (options.routerInfo && options.routerInfo.type == '1') {
this.$router.replace(options.routerInfo)
} else if (options.routerInfo && options.routerInfo.type == '2') {
this.$router.go(options.routerInfo.index || -1)
} else if (options.routerInfo) {
this.$router.push(options.routerInfo)
}
}
}

View File

@@ -0,0 +1,40 @@
//权限控制
import router from '@/router'
// import NProgress from 'nprogress' // Progress 进度条
// import 'nprogress/nprogress.css' // Progress 进度条样式
export function permission() {
router.beforeEach((to, from, next) => {
// NProgress.start()
//修改title
const title = to.meta && to.meta.title
if (title) {
document.title = title
}
//判断是否登录
let token = localStorage.token
if (!token) {
localStorage.token = ''
//无token判断是否需要登录
if (to.meta.auth) {
if (window.WebViewJavascriptBridge) {
//eslint-disable-next-line
EWebBridge.webCallAppInJs('bridge', { flag: 'login' })
} else {
next(`/login?redirect=${to.path}`)
}
} else {
next()
}
} else {
if (to.path == '/login') {
next({ path: '/' })
} else {
next()
}
}
})
// 结束Progress
router.afterEach(() => {
// NProgress.done()
})
}

View File

@@ -0,0 +1,65 @@
import axios from 'axios'
import { Dialog, Toast } from 'vant'
let whiteList = ['/sale/order/orderList', '/proposal/proposal/list']
// 创建axios实例
const service = axios.create({
timeout: 66666666 // 请求超时时间
})
// request拦截器
service.interceptors.request.use(
config => {
let relativePath = config.url && config.url.split('v1')[1]
if (whiteList.includes(relativePath)) {
Toast.loading({
duration: 0, // 持续展示 toast
forbidClick: true, // 禁用背景点击
loadingType: 'spinner',
message: '加载中……'
})
}
// config.headers['token'] = window.localStorage.getItem('token')
config.headers['token'] = '3692d9e914f34383a0a57cbf5c2de929'
// 873c5f2248b44789a9ebbe4262cac8e5
return config
},
error => {
// Do something with request error
Promise.reject(error)
}
)
// respone拦截器
service.interceptors.response.use(
response => {
const res = response.data
Toast.clear()
if (res.code != 0) {
if (res.code == 10001 || res.code == 10002) {
Dialog.confirm({
confirmButtonText: '重新登录',
message: '你已被登出,可以取消继续留在该页面,或者重新登录'
}).then(() => {
//eslint-disable-next-line
EWebBridge.webCallAppInJs('bridge', {
flag: 'login'
})
})
} else {
//Toast.fail(res.msg)
}
return Promise.reject(res)
} else {
return response.data.content
}
},
error => {
console.log('err' + error) // for debug
//Toast.fail(error.message)
return Promise.reject(error)
}
)
export default service

View File

@@ -0,0 +1,137 @@
import Vue from 'vue'
import VeeValidate, { Validator } from 'vee-validate'
import zh_CN from 'vee-validate/dist/locale/zh_CN'
import idNoCheck from './idNoCheck'
Vue.use(VeeValidate)
Validator.locale = 'zh_CN'
Validator.localize('zh_CN', {
messages: zh_CN.messages
})
/*自定义校验规则*/
//手机号
Validator.extend('mobile', {
getMessage: () => '手机格式不正确',
// validate: value => value.length === 11 && /^((13|14|15|17|18)[0-9]{1}\d{8})$/.test(value)
validate: value => value.length === 11 && /^1\d{10}$/.test(value)
})
//非空
Validator.extend('required', {
getMessage(field) {
return field + '不能为空'
},
validate(value) {
if (value) {
return true
}
return false
}
})
//邮箱
Validator.extend('email', {
getMessage: () => '邮箱格式错误',
validate(value) {
return /^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/.test(value)
}
})
//名字
Validator.extend('name', {
getMessage: () => '名字长度不超过2-120个字符',
validate: value => {
// return /^[\u4e00-\u9fa5·]{1,15}$/.test(value)
return /^[a-zA-Z\.\s\u4e00-\u9fa5]{2,120}$/.test(value)
}
})
//年龄
Validator.extend('age', {
getMessage: () => '年龄不得小于18岁',
validate: value => {
return value > 17 && /^\d{1,3}$/.test(value)
}
})
//身份证号校验规则
Validator.extend('idNo', {
getMessage() {
return '您填写的证件号码有误只能为18位以内数字或字母组合'
},
validate(value) {
if (idNoCheck.isIdno(value)) {
return true
}
return false
}
})
Validator.extend('idNoTemp', {
getMessage() {
return '证件号输入错误'
},
validate: value => {
return /^[0-9a-zA-Z]*$/g.test(value)
}
})
// 银行卡校验规则则
Validator.extend('bankCard', {
getMessage(field) {
return field + '格式不正确,请您填写正确的格式'
},
validate: value => {
return /^(\d{16}|\d{19})$/.test(value)
}
})
// 邮编
Validator.extend('zipCode', {
getMessage() {
return '您输入的邮编有误,请重新输入'
},
validate: value => {
return /^[0-9]{6}$/.test(value)
}
})
// 只能是数字
Validator.extend('onlyNumber', {
getMessage: field => field + '只能输入数字',
validate: value => {
if (!/^\d+$|^\d+[.]?\d+$/.test(value)) {
return false
}
return true
}
})
// 只能是正整数
Validator.extend('onlyInteger', {
getMessage: field => field + '输入错误',
validate: value => {
if (!/^[0-9]\d*$/.test(value)) {
return false
}
return true
}
})
// 身高
Validator.extend('stature', {
getMessage: () => '身高输入有误',
validate: value => {
return /^[0-9]{3}$/.test(value)
// if (value > 250) {
// return false
// }
// return true
}
})
// 体重
Validator.extend('avoirdupois', {
getMessage: () => '体重输入有误',
validate: value => {
return /^(\d){1,3}(\.\d{2}){1}$/.test(value) && value < 250
}
})

View File

@@ -0,0 +1,49 @@
import { wxShare } from '@/api/ebiz/common/common.js'
var wx = require('weixin-js-sdk')
//鼎诚人寿 微信分享
export function weixinShare(options) {
let defaults = {
title: '',
imgUrl: '',
desc: '',
link: window.location.href
}
let params = Object.assign(defaults, options)
wxShare({ url: location.href }).then(response => {
if (response.result == '0') {
let data = response.content
if (typeof data == 'string') {
data = JSON.parse(data)
}
wx.config({
//debug: true,
appId: data.appId,
timestamp: data.timestamp,
nonceStr: data.nonceStr,
signature: data.signature,
jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareWeibo']
})
wx.ready(function() {
wx.onMenuShareTimeline({
title: params.title,
link: params.link,
imgUrl: params.imgUrl,
success: function() {},
cancel: function() {}
})
wx.onMenuShareAppMessage({
title: params.title,
desc: params.desc,
link: params.link,
imgUrl: params.imgUrl,
type: 'link',
dataUrl: '',
success: function() {},
cancel: function() {}
})
})
}
})
}

BIN
src/assets/lib/text.pdf Normal file

Binary file not shown.

View File

@@ -0,0 +1,43 @@
@import './variables.scss';
@import './mixin.scss';
@import './utils.scss';
@import './transition.scss';
@import './vant-ui.scss';
* {
margin: 0;
padding: 0;
}
body {
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: #f5f5f5;
}
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);

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

@@ -0,0 +1,210 @@
@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-height($width-list) {
@each $size in $width-list {
.h#{$size} {
height: #{$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 text-overflow() {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

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;
}

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

@@ -0,0 +1,296 @@
//浮动、清除浮动
.clearfix {
@include clearfix;
}
.fl {
float: left;
}
.fr {
float: right;
}
//字体相关
.fs12 {
font-size: $font-size-small !important;
}
.fs13 {
font-size: 13px !important;
}
.fs14 {
font-size: $font-size-base !important;
}
.fs15 {
font-size: 15px !important;
}
.fs16 {
font-size: $font-size-large !important;
}
.fs17 {
font-size: 17px !important;
}
.fs18 {
font-size: $font-size-xl !important;
}
.fs26 {
font-size: $font-size-xll;
}
.fw500 {
font-weight: 500 !important;
}
.fw600 {
font-weight: 600 !important;
}
.fwb {
font-weight: bold !important;
}
//布局定位
.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;
display: flex;
}
.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-s {
justify-content: space-between;
}
.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;
}
.align-items-c {
align-items: center;
}
.align-items-b {
align-items: baseline;
}
.flex-direction-colunm {
flex-direction: column
}
// 字体颜色
.green {
color: $green !important;
}
.red {
color: $red !important;
}
.yellow {
color: $yellow !important;
}
.orange {
color: $orange !important;
}
.gray {
color: $gray !important;
}
.white {
color: $white !important;
}
.blue {
color: $blue !important;
}
.black {
color: $black !important;
}
// 常用文字颜色
.c-gray-base {
color: $gray-base !important; //999
}
.c-gray-dark {
color: $gray-dark !important; //666
}
.c-gray-darker {
color: $gray-darker !important; //333
}
.c-link {
color: #4a90e2 !important; //
}
// 文字位置设置
.text-left {
text-align: left !important;
}
.text-right {
text-align: right !important;
}
.text-justify {
text-align: justify !important;
}
.text-center {
text-align: center !important;
}
.text-underline {
text-decoration: underline;
}
// 垂直方向对齐方式
.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;
}
//背景色
.bg-black {
background: $black !important;
}
.bg-gray {
background: $gray !important;
}
.bg-white {
background: $white !important;
}
.bg-red {
background: $red !important;
}
.bg-green-base {
background: #ddf2ef !important;
}
.bg-green-dark {
background: #E9332E !important;
}
.bg-blue-dark {
background: #3fa9ff !important;
}
.bg-none {
background-color: transparent !important;
}
.border-b {
border-bottom: 1px solid $black;
}
.border-bt:not(:last-child)::after {
position: absolute;
z-index: 99;
box-sizing: border-box;
content: ' ';
pointer-events: none;
right: 0;
bottom: 0;
left: 4.26667vw;
border-bottom: 1px solid #dadada;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
.bg-none {
background-color: transparent !important;
}
.bottom-btn {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
}
.radius50 {
border-radius: 50%;
}

View File

@@ -0,0 +1,81 @@
#app {
.van-dialog__confirm,
.van-dialog__confirm:active,
.van-picker__cancel,
.van-picker__confirm,
.van-tag--danger.van-tag--plain {
color: #E9332E;
}
.van-button--plain.van-button--danger,
.van-tag--plain.van-tag--danger {
color: #E9332E;
background: transparent;
}
.van-checkbox__icon--checked .van-icon {
color: #fff;
background-color: #E9332E;
border-color: #E9332E;
}
.van-button--danger {
background: #E9332E;
border: 1px solid #E9332E;
}
.van-tabs__line,
.van-tag--danger {
background-color: #E9332E;
}
.van-radio__icon--checked .van-icon {
border-color: #E9332E !important;
background-color: #E9332E !important;
}
.van-cell:not(:last-child)::after {
border-bottom: 1px solid #dadada;
}
}
.dialog-delete {
width: 255px;
padding-bottom: 20px;
.van-dialog__header {
padding-top: 20px;
margin-bottom: 8px;
color: #E9332E;
}
.van-dialog__footer {
justify-content: space-between;
}
.van-dialog__message {
font-size: 14px;
color: #333;
padding-bottom: 30px;
}
.van-button {
max-width: 94px;
border-radius: 4px;
}
.van-dialog__cancel {
background: #e1f4f1;
margin-left: 20px;
}
.van-dialog__confirm {
background: #E9332E;
margin-right: 20px;
}
.van-hairline--top::after {
border: none;
}
}

View File

@@ -0,0 +1,33 @@
//颜色
$white: #fff !default;
$green: #E9332E !default;
$red: #f56123 !default;
$yellow: #f56123 !default;
$orange: #dd9c56 !default;
$gray: #b1b1b1 !default;
$black: #000 !default;
$blue: #5ca7de !default;
$gray-base: #999 !default;
$gray-dark: #666 !default;
$gray-darker: #333 !default;
$font-size-base: 14px !default;
$font-size-large: 16px !default;
$font-size-small: 12px !default;
$font-size-xl: 18px !default;
$font-size-xll: 26px !default;
// 宽度列表
$width-list: 8 10 12 15 18 20 35 40 45 50 60 70 80 86 90 100 110 120 130 140 150 155 160 165 180 192 200 220 240 250 260 280 315 325 345 350 365 400 440 445 450
550 700 1340;
// 内外边距列表
$distance-list: 0 1 2 5 6 7 8 9 10 12 15 20 25 30 35 40 45 50 60 70 80 86 90 100 150 165 185 210;
$distance-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;

View File

@@ -0,0 +1,32 @@
<template>
<div class="jump-container" @click="jump">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'jump',
props: {
flag: {
type: String,
default: 'h5'
},
routerInfo: Object,
extra: Object
},
methods: {
jump() {
// eslint-disable-next-line
if (window.WebViewJavascriptBridge) {
// eslint-disable-next-line
EWebBridge.webCallAppInJs('bridge', {
flag: this.flag,
extra: this.extra
})
} else {
this.$router.push(this.routerInfo)
}
}
}
}
</script>

View File

@@ -0,0 +1,185 @@
<template>
<div class="date-picter mb1" id="date-picter">
<van-field
readonly
clickable
:label="label"
:value="date"
:placeholder="placeholder"
@click="DatePickerShow(flag)"
:required="required"
:name="label"
right-icon="arrow"
/>
<van-popup v-model="showDataPicker" position="bottom">
<van-datetime-picker :type="type" v-model="data" @confirm="onConfirmDate" @cancel="cancel" :max-date="maxDate" :min-date="minDate" />
</van-popup>
</div>
</template>
<script>
import { Field, Popup, DatetimePicker } from 'vant'
import utils from '../../assets/js/business-common'
export default {
name: 'FieldDatePicter',
props: {
maxDate: {
type: Date,
default: () => {
return new Date('2039-12-31')
}
},
label: {
type: String,
default: '11'
},
value: {
type: String,
default: ''
},
placeholder: {
type: String,
default: '请选择'
},
type: {
type: String,
default: 'date'
},
defaultDate: {
type: Date,
default: () => {
return new Date()
}
},
defaulTime: {
type: String,
default: ''
},
required: {
type: Boolean,
default: false
},
flag: {
type: Boolean,
default: false
}
},
data() {
return {
currentDate: new Date(),
showDataPicker: false,
data: '', //时间插件绑定的值
date: '', //field显示的值
minDate: new Date('1900-01-01') //因为VANT组件默认是十年前
}
},
components: {
[DatetimePicker.name]: DatetimePicker,
[Field.name]: Field,
[Popup.name]: Popup
},
created() {
// this.DatePickerShow(this.flag)
this.init()
// setTimeout(() => {
// this.showDataPicker = false
// }, 0)
},
mounted() {},
watch: {
value() {
this.init()
}
},
methods: {
/**
* 初始化
*/
init() {
if (this.type == 'time') {
this.data = this.value
} else if (this.value) {
this.data = new Date(this.value)
} else {
this.data = this.currentDate
}
if (this.required) {
this.rules = 'required'
}
this.date = this.value
},
onConfirmDate(value) {
let result = ''
if (this.type == 'time') {
result = value
} else {
let dateType = {
date: 'yyyy-MM-dd',
datetime: 'yyyy-MM-dd HH:mm:ss',
'year-month': 'yyyy-MM',
time: 'mm:ss'
}
result = utils.formatDate(value, dateType[this.type])
}
this.$emit('update:value', result)
this.date = result
this.$emit('confirm', result)
this.showDataPicker = false
},
cancel() {
this.showDataPicker = false
this.$emit('cancel', '')
},
DatePickerShow(flag) {
this.showDataPicker = flag
this.$emit('showUp', flag)
}
}
}
</script>
<style lang="scss" scoped>
.date-picter:not(:last-child)::after {
position: absolute;
z-index: 99;
box-sizing: border-box;
content: ' ';
pointer-events: none;
right: 0;
// bottom: 0;
// top: 0;
left: 4.26667vw;
border-bottom: 1px solid #dadada;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
#date-picter {
/deep/.van-cell:not(:last-child)::after {
position: absolute;
box-sizing: border-box;
content: ' ';
pointer-events: none;
right: 0;
bottom: 0;
left: 4.26667vw;
border-bottom: 1px solid transparent;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
}
.nav-bar {
.van-nav-bar {
&__text {
color: white;
}
&__title {
color: white;
}
}
.van-icon {
color: white;
}
}
</style>

View File

@@ -0,0 +1,121 @@
<template>
<div class="date-picter">
<van-field readonly clickable :label="label" :value="fieldData" :placeholder="placeholder" @click="showPicker = true" :required="required">
<div slot="button" :class="{ tea_arrowDown: !showPicker, tea_arrowUp: showPicker }">
<van-icon name="arrow-down" slot="button" />
</div>
</van-field>
<van-popup v-model="showPicker" position="bottom">
<van-picker :columns="columns" :default-index="defaultIndex" :valueKey="valueKey" @change="change" />
</van-popup>
</div>
</template>
<script>
import { Field, Popup, Picker, Icon } from 'vant'
export default {
name: 'FieldPicker',
props: {
label: {
type: String,
default: '11'
},
value: {
type: String,
default: ''
},
placeholder: {
type: String,
default: '请选择'
},
required: {
type: Boolean,
default: false
},
data: {
type: Array,
default: () => {}
},
//选项对象中,文字对应的 key
valueKey: {
type: String,
default: 'text'
},
keyId: {}
},
data() {
return {
currentDate: new Date(),
showPicker: false,
defaultIndex: 0,
columns: [],
keyData: [],
type: 0, //0:普通数组 1对象数组,
fieldData: ''
}
},
components: {
[Field.name]: Field,
[Popup.name]: Popup,
[Picker.name]: Picker,
[Icon.name]: Icon
},
created() {
this.init()
},
mounted() {},
methods: {
/**
* 初始化
*/
init() {
this.columns = this.data
if (this.columns.length > 0) {
let arrayType = typeof this.columns[0]
//传入的是对象数组
if (arrayType == 'object') {
this.type = 1
} else {
this.type = 0
}
//获得默认选中的index
if (this.value) {
for (let i in this.columns) {
if (this.type == 0 && this.columns[i] == this.value) {
this.defaultIndex = i - 0
this.fieldData = this.columns[i]
break
} else if (this.type == 1 && this.columns[i][this.keyId] == this.value) {
this.defaultIndex = i - 0
this.fieldData = this.columns[i][this.valueKey]
break
}
}
}
}
},
change(picker, value, index) {
this.fieldData = value
if (this.type == 0) {
this.$emit('update:value', value)
} else {
this.$emit('update:value', this.columns[index][keyId])
}
this.$emit('on-change', value, index)
this.showPicker = false
},
cancel() {
this.showPicker = false
this.$emit('cancel', '')
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,93 @@
<template>
<div class="sex-radio">
<div class="van-cell-group ">
<div class="van-cell van-field pv7" :class="{ 'van-cell--required': required }">
<div class="van-cell__title van-field__label">
<span>{{ label }}</span>
</div>
<van-radio-group class="radio-area" v-model="radio">
<van-radio @click="handleChoose(itemRadio.value)" :name="itemRadio.value" v-for="(itemRadio, index) in radios" :key="index">
<div slot="icon"></div>
<van-button class="ph30" type="danger" :plain="radio == itemRadio.value ? false : true" round size="small">{{ itemRadio.label }}</van-button>
</van-radio>
</van-radio-group>
</div>
</div>
</div>
</template>
<script>
import { RadioGroup, Radio } from 'vant'
export default {
name: 'select-radio',
props: {
value: {
type: String,
default: '0'
},
label: {
type: String,
default: ''
},
radios: {
type: Array,
default: []
},
required: {
type: Boolean,
default: true
}
},
data() {
return {}
},
mounted() {},
methods: {
handleChoose(value) {
this.$emit('update:value', value)
}
},
computed: {
radio: {
get() {
return this.value
},
set() {}
}
},
components: {
[RadioGroup.name]: RadioGroup,
[Radio.name]: Radio
}
}
</script>
<style lang="scss"></style>
<style lang="scss" scoped>
.sex-radio {
.radio-area {
display: -webkit-flex;
display: flex;
justify-content: flex-start;
margin-left: -8px;
}
.van-cell {
align-items: center;
}
.van-button--plain {
background: #fff;
}
}
.sex-radio:not(:last-child)::after {
position: absolute;
z-index: 99;
box-sizing: border-box;
content: ' ';
pointer-events: none;
right: 0;
// bottom: 0;
// top: 0;
left: 4.26667vw;
border-bottom: 1px solid #dadada;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
</style>

View File

@@ -0,0 +1,112 @@
<template>
<div class="customer">
<van-index-bar>
<div v-if="data.length > 0">
<div class=" bg-white mt10 " v-for="customerInfo in data" :key="customerInfo.letter">
<van-index-anchor :index="customerInfo.letter" />
<div v-for="customer in customerInfo.data" :key="customer.name" class="flex ml15 mt10 pb10 content border-b align-items-c" @click="choose(customer)">
<img class="w40 mr15 " src="../../../assets/images/bnf_avatar.png" />
<div class="c-gray-darker fs14">
<div>{{ customer.customerName }}</div>
<div class="mt5">{{ customer.customerPhone }}</div>
</div>
<div class="text-right" style="flex:1">
<van-tag :color="customer.customerType == 0 ? '#7ED321' : customer.customerType == 1 ? '#5CA7DE' : '#333'" class="mr40" plain>{{
customer.typeName
}}</van-tag>
</div>
</div>
</div>
</div>
<div v-else class="text-center">
<img class="mt40" src="../../../assets/images/pic_page-non.png" />
<p class="mt15">暂无客户</p>
</div>
</van-index-bar>
</div>
</template>
<script>
import { getCustomersList, getAgentCustomerInfo } from '@/api/ebiz/customer/customer'
import dataDictionary from '@/assets/js/utils/data-dictionary' //根据数据字典找到用户等级
import utils from '@/assets/js/business-common'
import { IndexBar, IndexAnchor, Tag, Icon } from 'vant'
export default {
name: 'Customer',
data() {
return {
data: [],
isSuccess: false,
type: ['success', 'primary', 'danger', '']
}
},
created() {
this.getList()
},
components: {
[IndexBar.name]: IndexBar,
[IndexAnchor.name]: IndexAnchor,
[Tag.name]: Tag,
[Icon.name]: Icon
},
mounted() {},
methods: {
choose(data) {
let params = {
customerNumber: data.customerNumber
}
getAgentCustomerInfo(params).then(res => {
console.log(res, '详情')
if (res.result == '0') {
this.isSuccess = true
let content = res.content
if (content.birthday) {
content.age = utils.jsGetAge(content.birthday)
}
this.$emit('on-choose', content)
}
})
},
getList() {
getCustomersList({}).then(res => {
console.log(res)
if (res.result == '0') {
let customerList = []
//根据数据字典中的客户等级 展示
for (var key in res.agentCustomerList) {
res.agentCustomerList[key].forEach(current => {
dataDictionary.customerType.forEach(type => {
if (current.customerType == type.id) {
current.typeName = type.text
}
})
})
let current = {
data: res.agentCustomerList[key],
letter: key
}
customerList.push(current)
}
this.data = customerList
}
})
}
}
}
</script>
<style lang="scss">
.customer {
.van-index-anchor {
padding-top: 2px;
padding-bottom: 2px;
border-bottom: 1px solid #d6d6d6;
}
.border-b {
border-bottom: 1px solid #d6d6d6;
}
.content:last-child {
border: none;
}
}
</style>

View File

@@ -0,0 +1,155 @@
<template>
<div id="customer-picker">
<van-field
:label="label"
:value="name"
@input="onChange"
:placeholder="placeholder"
:required="required"
:right-icon="$assetsUrl + 'images/avatar.png'"
@click-right-icon="chooseCustomer"
/>
<van-popup v-model="parentShowPicker" position="bottom">
<customer @on-choose="choose" :code="code" :name="name" :life="life" :health="health"></customer>
</van-popup>
</div>
</template>
<script>
import { Field, Popup, Icon, Sticky } from 'vant'
import Customer from './Customer'
export default {
name: 'CustomerPicker',
props: {
label: {
type: String,
default: '11'
},
value: {
type: String,
default: ''
},
chooseName: {
type: String,
default: ''
},
placeholder: {
type: String,
default: '请选择'
},
required: {
type: Boolean,
default: false
},
data: {
type: Array,
default: () => {}
},
//选项对象中,文字对应的 key
valueKey: {
type: String,
default: 'text'
},
keyId: {},
lifeGrade: {
type: String,
default: ''
},
healthGrade: {
type: String,
default: ''
},
parentShowPicker: {
type: Boolean,
default: false
}
},
data() {
return {
name: '',
code: '',
life: '',
health: '',
showPicker: false
}
},
components: {
[Field.name]: Field,
[Popup.name]: Popup,
[Customer.name]: Customer,
[Icon.name]: Icon,
[Sticky.name]: Sticky
},
created() {
this.init()
},
mounted() {
this.showPicker = this.parentShowPicker
},
watch: {
value() {
this.name = this.value
}
},
methods: {
/**
* 初始化
*/
init() {
this.name = this.value
},
onChange(value) {
this.$emit('nameChange', value)
},
choose(data) {
this.name = data.customerName
this.$emit('on-choose', data)
},
chooseCustomer() {
this.showPicker = true
this.$emit('on-click')
},
cancel() {
this.showPicker = false
this.$emit('cancel', '')
}
}
}
</script>
<style lang="scss" scoped>
#customer-picker {
.van-popup--bottom {
height: 100%;
}
.van-popup {
background: #f5f5f5;
}
/deep/.van-cell:not(:last-child)::after {
position: absolute;
box-sizing: border-box;
content: ' ';
pointer-events: none;
right: 0;
bottom: 0;
left: 4.26667vw;
border-bottom: 1px solid transparent;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
}
#customer-picker:not(:last-child)::after {
position: absolute;
z-index: 99;
box-sizing: border-box;
content: ' ';
pointer-events: none;
right: 0;
// bottom: 0;
// top: 0;
left: 4.26667vw;
border-bottom: 1px solid #dadada;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
</style>

View File

@@ -0,0 +1,333 @@
const customer = [
{
data: [
{
birthDay: '1989-09-09',
name: '安然',
phone: '15369303118',
sex: 1,
type: 0,
typeName: '准客户'
},
{
birthDay: '1980-07-09',
name: '安新',
phone: '15369303108',
sex: 1,
type: 0,
typeName: '准客户'
}
],
letter: 'A'
},
{
data: [
{
birthDay: '1989-08-09',
name: '白杨万',
phone: '15369303118',
sex: 0,
type: 0,
typeName: '准客户'
},
{
birthDay: '1983-03-17',
name: '柏静然',
phone: '18645436488',
sex: 0,
type: 0,
typeName: '准客户'
},
{
birthDay: '1982-07-09',
name: '本杰',
phone: '15369303108',
type: 0,
typeName: '准客户'
}
],
letter: 'B'
},
{
data: [
{
birthDay: '1979-09-19',
name: '陈希媛',
phone: '15369303118',
sex: 1,
type: 0,
typeName: '准客户'
},
{
birthDay: '1980-08-09',
name: '陈新元',
phone: '18636884987',
sex: 0,
type: 1,
typeName: '潜在客户'
}
],
letter: 'C'
},
{
data: [
{
birthDay: '1987-09-04',
name: '丹妮',
phone: '13821261512',
sex: 1,
type: 0,
typeName: '准客户'
},
{
birthDay: '1987-09-04',
name: '丁逸',
phone: '18646584562',
sex: 0,
type: 0,
typeName: '准客户'
},
{
birthDay: '1989-06-12',
name: '邓丽',
phone: '13939116097',
sex: 1,
type: 2,
typeName: '老客户'
},
{
birthDay: '1980-11-02',
name: '邓水恒',
phone: '15670972211',
sex: 0,
type: 1,
typeName: '潜在客户'
},
{
birthDay: '1982-12-22',
name: '刁小柱',
phone: '18646336627',
sex: 0,
type: 1,
typeName: '准客户'
}
],
letter: 'D'
},
{
data: [
{
birthDay: '1963-09-25',
name: '峰磊',
phone: '15922146016',
sex: 0,
type: 0,
typeName: '准客户'
},
{
birthDay: '1978-02-21',
name: '冯雷',
phone: '15039106572',
sex: 1,
type: 0,
typeName: '准客户'
},
{
birthDay: '1963-11-25',
name: '方小喜',
phone: '13946180058',
sex: 1,
type: 1,
typeName: '潜在客户'
},
{
birthDay: '1980-10-25',
name: '付文文',
phone: '15538925803',
sex: 0,
type: 0,
typeName: '潜在客户'
},
{
birthDay: '1976-02-15',
name: '傅博海',
phone: '15134616380',
sex: 2,
type: 0,
typeName: '老客户'
}
],
letter: 'F'
},
{
data: [
{
birthDay: '1976-02-14',
name: '耿钱',
phone: '13839120897',
sex: 0,
type: 0,
typeName: '准客户'
},
{
birthDay: '1977-04-07',
name: '官小林',
phone: '13703915284',
sex: 1,
type: 0,
typeName: '准客户'
},
{
birthDay: '1963-11-25',
name: '郭凯',
phone: '15204631833',
sex: 1,
type: 1,
typeName: '潜在客户'
}
],
letter: 'G'
},
{
data: [
{
birthDay: '1970-01-04',
name: '何文静',
phone: '18745783028',
sex: 0,
type: 1,
typeName: '老客户'
},
{
birthDay: '1980-11-02',
name: '何龙',
phone: '13836010529',
sex: 1,
type: 0,
typeName: '准客户'
},
{
birthDay: '1981-08-22',
name: '何幸聪',
phone: '18636182152',
sex: 0,
type: 1,
typeName: '潜在客户'
}
],
letter: 'H'
},
{
data: [
{
birthDay: '1990-01-12',
name: '刘晓非',
phone: '18345103903',
sex: 0,
type: 0,
typeName: '准客户'
},
{
birthDay: '1981-10-16',
name: '刘得海',
phone: '18003606847',
sex: 1,
type: 1,
typeName: '潜在客户'
},
{
birthDay: '1981-08-22',
name: '李文',
phone: '18037029992',
sex: 0,
type: 0,
typeName: '准客户'
},
{
birthDay: '1979-08-18',
name: '李仁伟',
phone: '18535003368',
sex: 1,
type: 0,
typeName: '准客户'
}
],
letter: 'L'
},
{
data: [
{
birthDay: '1990-01-12',
name: '刘晓非',
phone: '18345103903',
sex: 0,
type: 0,
typeName: '准客户'
},
{
birthDay: '1992-03-34',
name: '王浩斯',
phone: '15145715979',
sex: 1,
type: 2,
typeName: '老客户'
},
{
birthDay: '1975-12-08',
name: '王舒伟',
phone: '18545545277',
sex: 1,
type: 1,
typeName: '潜在客户'
},
{
birthDay: '1992-02-06',
name: '吴土金',
phone: '18945851424',
sex: 1,
type: 2,
typeName: '老客户'
},
{
birthDay: '15838961658',
name: '吴小清',
phone: '15838961658',
sex: 1,
type: 0,
typeName: '准客户'
}
],
letter: 'W'
},
{
data: [
{
birthDay: '1976-08-17',
name: '谢树鹏',
phone: '13503628699',
sex: 1,
type: 0,
typeName: '准客户'
},
{
birthDay: '1992-03-14',
name: '薛冰琪',
phone: '18545545277',
sex: 0,
type: 1,
typeName: '潜在客户'
},
{
birthDay: '1991-02-18',
name: '谢玉轩',
phone: '13251612226',
sex: 1,
type: 2,
typeName: '老客户'
}
],
letter: 'X'
}
]
export default customer

View File

@@ -0,0 +1,623 @@
<template>
<div>
<van-cell-group>
<!-- 基本信息 -->
<select-radio
:radios="sexRadio"
label="性别"
:value.sync="userInfo.customerSex"
:required="false"
></select-radio>
<van-field
:value="userInfo.nativeplace | idToText('nativeplace')"
readonly
label="国家/地区"
name="国家/地区"
right-icon="arrow"
placeholder="请选择"
@click="toSelect('1')"
/>
<van-field
:value="census"
readonly
label="户籍"
name="户籍"
right-icon="arrow"
placeholder="请选择"
@click="censusShow = true"
/>
<FieldDatePicter
label="出生日期"
:value.sync="userInfo.birthday"
type="date"
:flag="true"
@confirm="onDateConfirm($event, '0')"
ref="birthday"
></FieldDatePicter>
<van-field
:value="userInfo.idType | idToText('idType')"
readonly
label="证件类型"
name="证件类型"
right-icon="arrow"
placeholder="请选择"
@click="toSelect('2')"
/>
<van-field
v-model="userInfo.customerIdNumber"
v-validate="'idNoTemp'"
label="证件号码"
name="证件号码"
placeholder="请输入"
></van-field>
<FieldDatePicter
label="证件起始日期"
name="证件起始日期"
:value.sync="userInfo.certificateValidate"
type="date"
:flag="true"
ref="certificateValidate"
@confirm="onDateConfirm($event, '1')"
></FieldDatePicter>
<FieldDatePicter
label="证件截止日期"
name="证件截止日期"
:value.sync="userInfo.certiexpiredate"
type="date"
:flag="true"
ref="certiexpiredate"
@confirm="onDateConfirm($event, '2')"
></FieldDatePicter>
<div class="van-hairline--bottom fs14 p10 clearfix">
<van-checkbox
v-model="userInfo.effectiveDateType"
class="fr"
:disabled="effectiveDateTypeAble"
@change="isEnd"
>长期</van-checkbox>
</div>
<van-field
v-model="userInfo.email"
label="电子邮箱"
name="电子邮箱"
v-validate="'email'"
placeholder="请输入"
clearable
maxlength="50"
/>
<van-field
v-model="userInfo.stature"
label="身高cm"
placeholder="请输入"
clearable
v-validate="'onlyInteger'"
maxlength="3"
type="number"
/>
<van-field
v-model="userInfo.weight"
label=" 体重kg"
placeholder="请输入"
clearable
v-validate="'onlyInteger'"
maxlength="3"
type="number"
/>
<van-field
:value="userInfo.customerType | idToText('customerType')"
readonly
label="客户类型"
name="客户类型"
right-icon="arrow"
placeholder="请选择"
@click="toSelect('7')"
/>
<van-field
:value="userInfo.customerSource | idToText('customerSource')"
readonly
label="客户来源"
name="客户来源"
right-icon="arrow"
placeholder="请选择"
@click="toSelect('8')"
/>
</van-cell-group>
<!-- 工作信息 -->
<van-cell-group class="mt5">
<p class="title pl10 pv5">工作信息</p>
<van-field
:value="userInfo.degree | idToText('degree')"
readonly
label="文化程度"
name="文化程度"
right-icon="arrow"
placeholder="请选择"
@click="toSelect('3')"
/>
<select-radio
:radios="medicalRadio"
label="有无社保"
:value.sync="userInfo.socialSecurity"
:required="false"
></select-radio>
<van-field
:value="userInfo.taxIdentity | idToText('taxIdentity')"
readonly
label="税收居民身份"
name="税收居民身份"
right-icon="arrow"
placeholder="请选择"
@click="toSelect('5')"
/>
<occupation-picker
:value.sync="userInfo.occupationCode"
:chooseName.sync="userInfo.occupationName"
:lifeGrade.sync="userInfo.lifeGrade"
:healthGrade.sync="userInfo.healthGrade"
clearable
label="职业类别"
name="职业类别"
placeholder="请选择"
:parentShowPicker.sync="occupationShowPicker"
@on-click="selectClick"
@on-choose="chooseOccupation"
/>
<van-field
v-model="userInfo.averageYearlyIncome"
type="number"
label="平均年收入(万元)"
name="平均年收入"
v-validate="'onlyInteger'"
placeholder="请输入"
clearable
maxlength="5"
/>
<van-field
v-model="userInfo.liabilitiesMoney"
type="number"
label="负债金额(万元)"
name="负债金额"
v-validate="'onlyInteger'"
placeholder="请输入"
clearable
maxlength="5"
/>
<van-field
v-model="userInfo.workUnits"
label="工作单位"
placeholder="请输入工作单位"
clearable
maxlength="50"
/>
<van-field
:value="userInfo.workCondition | idToText('workCondition')"
readonly
label="在职情况"
name="在职情况"
right-icon="arrow"
placeholder="请选择"
@click="toSelect('9')"
/>
<van-field
v-model="areaName"
readonly
label="单位地址"
name="单位地址"
right-icon="arrow"
placeholder="请选择"
@click="areaShow = true"
/>
<van-field
v-model="userInfo.companyAddress"
label
name="详细地址"
placeholder="请输入详细地址"
maxlength="30"
/>
<van-field
v-model="userInfo.companyZip"
type="number"
label="邮编"
placeholder="请输入"
clearable
maxlength="6"
v-validate="'zipCode'"
/>
<van-field
v-model="userInfo.companyPhone"
label="单位电话"
name="单位电话"
placeholder="请输入"
clearable
maxlength="13"
/>
</van-cell-group>
<!-- 家庭信息 -->
<van-cell-group class="mt5">
<p class="title pl10 pv5">家庭信息</p>
<van-field
:value="userInfo.marriage | idToText('marriage')"
readonly
label="婚姻状况"
name="婚姻状况"
right-icon="arrow"
placeholder="请选择"
@click="toSelect('6')"
/>
<van-field
v-model="userInfo.familyAnnualIncome"
type="number"
label="家庭年收入(万元)"
name="家庭年收入"
v-validate="'onlyInteger'"
placeholder="请输入"
clearable
/>
<van-field
v-model="homeName"
readonly
label="家庭地址"
name="家庭地址"
right-icon="arrow"
placeholder="请选择"
@click="homeShow = true"
/>
<van-field v-model="userInfo.homeAddress" label name="详细地址" placeholder="请输入详细地址" />
<van-field
v-model="userInfo.homeZip"
type="number"
label="邮编"
placeholder="请输入"
clearable
maxlength="6"
v-validate="'zipCode'"
/>
<van-field
v-model="userInfo.homePhone"
label="家庭电话"
name="家庭电话"
placeholder="请输入"
clearable
maxlength="13"
/>
</van-cell-group>
<!-- 字段选择 -->
<van-popup v-model="popupShow" position="bottom">
<van-picker show-toolbar :columns="columns" @confirm="onConfirm" @cancel="popupShow = false" />
</van-popup>
<!-- 地区选择 -->
<van-popup v-model="areaShow" position="bottom">
<van-area
:area-list="areaList"
value="110101"
@confirm="sureArea($event, '1')"
@cancel="areaShow = false"
/>
</van-popup>
<!-- 家庭地址选择 -->
<van-popup v-model="homeShow" position="bottom">
<van-area
:area-list="areaList"
value="110101"
@confirm="sureArea($event, '2')"
@cancel="homeShow = false"
/>
</van-popup>
<!-- 户籍选择 -->
<van-popup v-model="censusShow" position="bottom">
<van-area
:area-list="areaList"
value="110101"
:columns-num="2"
@confirm="sureArea($event, '3')"
@cancel="areaShow = false"
/>
</van-popup>
</div>
</template>
<script>
import { Field, CellGroup, Cell, Popup, Picker, Checkbox, Area } from 'vant'
import SelectRadio from '@/components/ebiz/SelectRadio'
import FieldDatePicter from '@/components/ebiz/FieldDatePicter'
import DataDictionary from '@/assets/js/utils/data-dictionary'
import OccupationPicker from '@/components/ebiz/occipation/OccupationPicker'
import areaList from '@/assets/js/utils/area'
import utilsAge from '@/assets/js/utils/age'
import getAreaName from '@/assets/js/utils/get-area-name'
import filter from '@/filters/index'
import { constants } from 'crypto'
import { userInfo } from 'os'
export default {
name: 'formBlock',
components: {
[Field.name]: Field,
[CellGroup.name]: CellGroup,
[Cell.name]: Cell,
[Popup.name]: Popup,
[Picker.name]: Picker,
[Checkbox.name]: Checkbox,
[FieldDatePicter.name]: FieldDatePicter,
[OccupationPicker.name]: OccupationPicker,
[SelectRadio.name]: SelectRadio,
[Area.name]: Area
},
props: ['userInfo'],
data() {
return {
popupShow: false,
areaShow: false, //省级联动
homeShow: false,
censusShow: false, //户籍联动
census: '',
pickerType: undefined,
columns: [],
valueKey: 'text',
nativeplace: '',
idType: '',
degree: '',
socialSecurity: '',
taxIdentity: '',
areaName: '', //单位地址
homeName: '', //家庭地址
marriage: '',
areaList: areaList,
customerType: '',
customerSource: '',
age: '',
effectiveDateTypeAble: false, //长期按钮是否禁用
occupationShowPicker: false,
sexRadio: [
{
label: '男',
value: '0'
},
{
label: '女',
value: '1'
}
],
medicalRadio: [
{
label: '有',
value: '0'
},
{
label: '无',
value: '1'
}
]
}
},
watch: {
userInfo: {
handler(newVal, oldVal) {
// console.log("老数据",oldVal);
// console.log("新数据",newVal);
// if(newVal.toString() != oldVal.toString()){
this.userInfo = newVal
if (this.userInfo.province) {
this.censusInfo()
}
if (this.userInfo.companyProvince) {
this.areaNameInfo()
}
if (this.userInfo.homeProvince) {
this.homeNameInfo()
}
if (this.userInfo.certiexpiredate == '9999-01-01') {
this.userInfo.effectiveDateType = true
}
},
deep: true
}
},
filters: {
idToText: filter.idToText
},
mounted() {},
methods: {
selectClick() {
let title = ''
;[this.occupationShowPicker, title] = [true, '职业类别']
},
chooseOccupation() {
this.occupationShowPicker = false
},
// 表单校验
validateForm() {
return this.$validator.validateAll()
},
censusInfo() {
let area = [{ code: this.userInfo.province }, { code: this.userInfo.city }]
this.census = getAreaName(area)
},
areaNameInfo() {
let area = [{ code: this.userInfo.companyProvince }, { code: this.userInfo.companyCity }, { code: this.userInfo.companyArea }]
this.areaName = getAreaName(area)
},
homeNameInfo() {
let area = [{ code: this.userInfo.homeProvince }, { code: this.userInfo.homeCity }, { code: this.userInfo.homeArea }]
this.homeName = getAreaName(area)
},
//弹框选择
toSelect(pickerType, valueKey) {
//pickerType 1、国家地区 2、证件类型 3、文化程度 4、有无社保 5、税收居民身份 6、婚姻状况
;[this.popupShow, this.pickerType] = [true, pickerType]
if (valueKey) this.valueKey = valueKey
if (pickerType == '1') {
this.columns = DataDictionary.nativeplace
} else if (pickerType == '2') {
if(this.userInfo.birthday){
let age = utilsAge.getAge(this.userInfo.birthday, new Date())
console.log("年纪",age)
if (age >= 3 && age < 16) {
this.columns = DataDictionary.birthType
} else if (age >= 3 && age >= 16) {
this.columns = DataDictionary.insuredIdType
} else {
this.columns = DataDictionary.idType
}
}else{
this.columns = DataDictionary.idType
}
} else if (pickerType == '3') {
this.columns = DataDictionary.degree
// } else if (pickerType == '4') {
// this.columns = DataDictionary.socialSecurity
} else if (pickerType == '5') {
this.columns = DataDictionary.taxIdentity
} else if (pickerType == '6') {
this.columns = DataDictionary.marriage
} else if (pickerType == '7') {
this.columns = DataDictionary.customerType
} else if (pickerType == '8') {
this.columns = DataDictionary.customerSource
} else if (pickerType == '9') {
this.columns = DataDictionary.workCondition
}
},
//确认选择字段
onConfirm(value) {
this.popupShow = false
if (this.pickerType == '1') {
;[this.userInfo.nativeplace, this.nativeplace] = [value.id, value.text]
this.valueKey = value.text
} else if (this.pickerType == '2') {
//身份证以外的证件类型可以使用长期
if (value.id != '1') {
this.effectiveDateTypeAble = false
} else {
let age = utilsAge.getAge(this.userInfo.birthday, new Date())
this.effectiveDateTypeAble = !(age >= 45)
}
;[this.userInfo.idType, this.idType] = [value.id, value.text]
} else if (this.pickerType == '3') {
;[this.userInfo.degree, this.degree] = [value.id, value.text]
// } else if (this.pickerType == '4') {
// ;[this.userInfo.socialSecurity, this.socialSecurity] = [value.id, value.text]
} else if (this.pickerType == '5') {
;[this.userInfo.taxIdentity, this.taxIdentity] = [value.id, value.text]
} else if (this.pickerType == '6') {
;[this.userInfo.marriage, this.marriage] = [value.id, value.text]
} else if (this.pickerType == '7') {
;[this.userInfo.customerType, this.customerType] = [value.id, value.text]
} else if (this.pickerType == '8') {
;[this.userInfo.customerSource, this.customerSource] = [value.id, value.text]
} else if (this.pickerType == '9') {
;[this.userInfo.workCondition, this.workCondition] = [value.id, value.text]
}
},
//区域选择
sureArea(area, type) {
switch (type) {
case '1': //单位地址
this.areaName = getAreaName(area)
;[this.userInfo.companyProvince, this.userInfo.companyCity, this.userInfo.companyArea] = [area[0].code, area[1].code, area[2].code]
this.areaShow = false
break
case '2': //家庭地址
this.homeName = getAreaName(area)
;[this.userInfo.homeProvince, this.userInfo.homeCity, this.userInfo.homeArea] = [area[0].code, area[1].code, area[2].code]
this.homeShow = false
break
case '3': //户籍
this.census = getAreaName(area)
;[this.userInfo.province, this.userInfo.city] = [area[0].code, area[1].code]
this.censusShow = false
break
}
},
//证件起始截止日期
onDateConfirm(val, type) {
if (type == '0') {
//出生日期
if (Date.parse(val) > Date.parse(new Date())) {
this.userInfo.birthday = ''
this.$refs.birthday.date = ''
return this.$toast('出生日期不晚于当日')
}
//长期判断
let age = utilsAge.getAge(this.userInfo.birthday, new Date())
if (this.userInfo.idType == '1') {
this.effectiveDateTypeAble = !(age >= 45)
if (age < 45) {
this.userInfo.effectiveDateType = false
}
}
//年龄大于等于3岁不能使用出生证明
if (age >= 3) {
if (this.userInfo.idType == '3') {
this.userInfo.idType = ''
this.$toast('请选择正确的证件类型')
}
}
//年龄大于等于16岁不能使用户口本
if (age >= 16) {
if (this.userInfo.idType == '2') {
this.userInfo.idType = ''
this.$toast('请选择正确的证件类型')
}
}
} else if (type == '1') {
//证件起始日期
//如果录入日期早于出生日期或晚于当前日期
if (Date.parse(val) > Date.parse(new Date()) || Date.parse(val) < Date.parse(this.userInfo.birthday)) {
this.userInfo.certificateValidate = ''
this.$refs.certificateValidate.date = ''
return this.$toast('证件起始日期填写错误')
}
// 计算年龄
let certificateAge = utilsAge.getAge(val, new Date())
let birthAge = utilsAge.getAge(this.userInfo.birthday, new Date())
let age = birthAge - certificateAge
// 长期按钮是否禁用
this.effectiveDateTypeAble = age >= 16 && age <= 45
// if(age < 45){
// this.userInfo.effectiveDateType = false
// }
} else {
//证件截止日期
//如果已经勾选了长期
if (this.userInfo.effectiveDateType) {
//清空数据并返回
this.userInfo.certiexpiredate = ''
this.$refs.certiexpiredate.date = ''
return
}
//如果录入日期早于当前日期
if (Date.parse(val) < Date.parse(new Date())) {
this.userInfo.certiexpiredate = ''
this.$refs.certiexpiredate.date = ''
return this.$toast('您的证件已过期')
}
}
},
//长期状态改变时
isEnd(val) {
//勾选长期状态时,证件截止日期置空
if (val) {
this.userInfo.certiexpiredate = ''
this.certiexpiredateRequired = false
sessionStorage.setItem('isEnd', '9999-01-01')
} else {
this.certiexpiredateRequired = true
sessionStorage.setItem('isEnd', '')
}
}
}
}
</script>
<style lang="scss" scoped>
.title {
font-weight: 600;
border-bottom: 1px solid #ebedf0;
}
[class*='van-hairline']::after {
border: none !important;
}
</style>

View File

@@ -0,0 +1,153 @@
<template>
<div class="occupation pb70">
<van-search v-model="searchParams" placeholder="请输入搜索关键词" show-action shape="round" @clear="clearSearch" @search="onSearch">
<div slot="action" @click="onSearch">搜索</div>
</van-search>
<div class="main-area fs12">
<div class="item p10">
<p class="p5" v-for="(item, index) in occupationList" :key="index" @click="handleFirst(item)" :class="{ active: first.code == item.code }">
{{ item.name }}
</p>
</div>
<div class="item p10">
<p class="p5" v-for="(item, index) in sec" :key="index" @click="handleSec(item)" :class="{ active: second.code == item.code }">
{{ item.name }}
</p>
</div>
<div class="item p10">
<p class="p5" v-for="(item, index) in thi" :key="index" @click="handleThi(item)" :class="{ active: third.code == item.code }">
{{ item.name }}
</p>
</div>
<div v-if="third.code" class="choose-result">
<p>职业代码{{ third.code }}</p>
<p>职业{{ chooseName }}</p>
</div>
</div>
<van-button type="danger" class="bottom-btn" @click="ensureChoose">确认选择</van-button>
</div>
</template>
<script>
import occupationData from './data/occupation'
import { Search, Sticky } from 'vant'
export default {
name: 'Occupation',
props: {
name: {
type: String,
default: ''
},
code: {
type: String,
default: ''
},
life: {
type: String,
default: ''
},
health: {
type: String,
default: ''
}
},
data() {
return {
occupationList: [],
sec: [], //二级数据
thi: [], //三级数据
choose: [],
searchParams: '',
first: {},
second: {},
third: {},
chooseName: '',
lifeGrade: '',
healthGrade: ''
}
},
components: {
[Search.name]: Search,
[Sticky.name]: Sticky
},
created() {
this.init(occupationData)
},
mounted() {},
methods: {
init(data) {
this.occupationList = data
this.chooseName = this.name
this.third.code = this.code
this.lifeGrade = this.life
this.healthGrade = this.health
this.third = {}
},
handleFirst(item) {
this.sec = item.subs
this.first = item
this.second = {}
this.thi = []
this.third = {}
},
handleSec(item) {
this.thi = item.subs
this.second = item
this.third = {}
},
handleThi(item) {
this.third = item
this.chooseName = this.third.name
},
ensureChoose() {
if (this.third.code) {
this.$emit('chooseOccupation', this.third)
console.log(this.third)
} else {
this.$toast('请选择职业')
}
},
onSearch() {
let data = []
for (let item of occupationData) {
if (JSON.stringify(item).indexOf(this.searchParams) != -1) {
data.push(item)
}
}
this.init(data)
},
clearSearch() {
this.init(occupationData)
}
}
}
</script>
<style lang="scss" scoped>
.occupation {
.main-area {
padding: 10px;
display: flex;
justify-content: space-between;
.item {
width: 0;
flex-grow: 1;
display: flex;
flex-direction: column;
}
.active {
color: red;
background-color: #f2f2f2;
}
.choose-result {
position: fixed;
width: 100%;
left: 20px;
bottom: 44px;
z-index: 100;
background: #ffffff;
line-height: 20px;
color: red;
}
}
}
</style>

View File

@@ -0,0 +1,180 @@
<template>
<div class="date-picter" id="occupation-picker">
<van-field
readonly
clickable
:label="label"
:value="chooseName"
:placeholder="placeholder"
@click="openOccupation"
:required="required"
right-icon="arrow"
/>
<van-popup v-model="parentShowPicker" position="bottom">
<!-- <div class="close" v-if="showPicker">
<div class="close-wrap">
<p>职业选择</p>
<van-icon name="cross" @click="cancel" />
</div>
</div> -->
<occupation @chooseOccupation="chooseOccupation" :code="code" :name="name"></occupation>
</van-popup>
</div>
</template>
<script>
import { Field, Popup, Icon } from 'vant'
import Occupation from './Occupation'
export default {
name: 'OccupationPicker',
props: {
label: {
type: String,
default: '11'
},
value: {
type: String,
default: ''
},
chooseName: {
type: String,
default: ''
},
placeholder: {
type: String,
default: '请选择'
},
required: {
type: Boolean,
default: false
},
data: {
type: Array,
default: () => {}
},
//选项对象中,文字对应的 key
valueKey: {
type: String,
default: 'text'
},
keyId: {},
lifeGrade: {
type: String,
default: ''
},
healthGrade: {
type: String,
default: ''
},
parentShowPicker: {
type: Boolean,
default: false
}
},
data() {
return {
name: '',
code: '',
life: '',
health: '',
showPicker: false
}
},
components: {
[Field.name]: Field,
[Popup.name]: Popup,
[Icon.name]: Icon,
[Occupation.name]: Occupation
},
created() {
this.init()
},
mounted() {},
methods: {
/**
* 初始化
*/
init() {
this.code = this.value
this.name = this.chooseName
this.life = this.lifeGrade
this.health = this.healthGrade
},
chooseOccupation(data) {
let { code, name, healthGrade, lifeGrade } = data
this.$emit('update:value', code)
this.$emit('update:chooseName', name)
this.$emit('update:lifeGrade', lifeGrade)
this.$emit('update:healthGrade', healthGrade)
this.$emit('on-choose', data)
this.name = name
this.showPicker = false
},
openOccupation() {
this.$emit('on-click')
this.showPicker = true
},
cancel() {
this.showPicker = false
this.$emit('cancel', '')
}
}
}
</script>
<style lang="scss" scoped>
.date-picter:not(:last-child)::after {
position: absolute;
z-index: 99;
box-sizing: border-box;
content: ' ';
pointer-events: none;
right: 0;
// bottom: 0;
// top: 0;
left: 4.26667vw;
border-bottom: 1px solid #dadada;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
#occupation-picker {
/deep/.van-cell:not(:last-child)::after {
position: absolute;
box-sizing: border-box;
content: ' ';
pointer-events: none;
right: 0;
bottom: 0;
left: 4.26667vw;
border-bottom: 1px solid transparent;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
}
.van-popup--bottom {
height: 100%;
}
.close {
// display: flex;
width: 100%;
position: fixed;
top: 0;
left: 0;
text-align: center;
align-items: center;
// right: 20px;
// left: 20px;
.close-wrap {
display: flex;
padding: 5px 10px;
background-color: #fff;
.van-icon {
font-size: 20px;
}
p {
font-size: 16px;
flex-grow: 1;
}
}
}
</style>

Some files were not shown because too many files have changed in this diff Show More