33235b33 by zhen

init project

0 parents
Showing 107 changed files with 3852 additions and 0 deletions
1 # just a flag
2 ENV = 'development'
3
4 # base api
5 # VUE_APP_BASE_API = 'http://192.168.11.94:8081'
6 # VUE_APP_BASE_API = 'http://192.168.252.25:8081'
7 VUE_APP_BASE_API = 'https://pre-web-chery.situdata.com'
8
9 VUE_APP_WEBRTC_URL = 'pre-jitsi-chery.situdata.com'
10 # VUE_APP_WEBRTC_URL = 'srtc.situdata.com'
...\ No newline at end of file ...\ No newline at end of file
1 # just a flag
2
3 VUE_APP_BASE_API = 'https://ft.cheryfs.cn:8100'
4
5 VUE_APP_WEBRTC_URL = 'vc.cheryfs.cn:8443'
...\ No newline at end of file ...\ No newline at end of file
1 node_modules
2 dist
3 .DS_Store
4 .idea
...\ No newline at end of file ...\ No newline at end of file
1 # 云霄后台管理
1 module.exports = {
2 presets: [
3 '@vue/app'
4 ]
5 }
This diff could not be displayed because it is too large.
1 {
2 "name": "yunxiao-admin-fe",
3 "version": "0.1.0",
4 "private": true,
5 "scripts": {
6 "serve": "vue-cli-service serve --mode development",
7 "build": "vue-cli-service build",
8 "lint": "vue-cli-service lint",
9 "test:unit": "vue-cli-service test:unit",
10 "commit": "cz"
11 },
12 "dependencies": {
13 "animate.css": "^4.1.0",
14 "axios": "^0.18.1",
15 "captcha-mini": "^1.1.0",
16 "core-js": "^2.6.11",
17 "echarts": "^4.8.0",
18 "element-ui": "^2.13.2",
19 "js-cookie": "^2.2.1",
20 "nprogress": "^0.2.0",
21 "pug": "^2.0.4",
22 "pug-plain-loader": "^1.0.0",
23 "uuid": "^8.3.0",
24 "v-charts": "^1.19.0",
25 "video.js": "^7.8.4",
26 "vue": "^2.6.10",
27 "vue-router": "^3.1.3",
28 "vue-simple-uploader": "^0.7.4",
29 "vuex": "^3.1.2"
30 },
31 "devDependencies": {
32 "@vue/cli-plugin-babel": "^3.12.1",
33 "@vue/cli-plugin-eslint": "^3.12.1",
34 "@vue/cli-plugin-unit-mocha": "^3.12.1",
35 "@vue/cli-service": "^3.12.1",
36 "@vue/eslint-config-standard": "^4.0.0",
37 "@vue/test-utils": "1.0.0-beta.29",
38 "babel-eslint": "^10.0.3",
39 "chai": "^4.1.2",
40 "commitizen": "^4.2.0",
41 "cz-conventional-changelog": "^3.2.1",
42 "cz-emoji": "^1.2.2",
43 "eslint": "^5.16.0",
44 "eslint-plugin-vue": "^5.2.3",
45 "filemanager-webpack-plugin": "^2.0.5",
46 "node-sass": "^4.13.0",
47 "qr-image": "^3.2.0",
48 "sass-loader": "^7.3.1",
49 "svg-sprite-loader": "^4.3.0",
50 "vue-particles": "^1.0.9",
51 "vue-template-compiler": "^2.5.21"
52 },
53 "eslintConfig": {
54 "root": true,
55 "env": {
56 "node": true
57 },
58 "extends": [
59 "plugin:vue/essential",
60 "@vue/standard"
61 ],
62 "parserOptions": {
63 "parser": "babel-eslint"
64 },
65 "rules": {
66 "no-tabs": "off",
67 "space-before-function-paren": "off"
68 }
69 },
70 "postcss": {
71 "plugins": {
72 "autoprefixer": {}
73 }
74 },
75 "browserslist": [
76 "> 1%",
77 "last 2 versions"
78 ],
79 "config": {
80 "cz-emoji": {
81 "types": [
82 {
83 "emoji": "🌟",
84 "code": "🌟feat:",
85 "description": "A new feature",
86 "name": "feature"
87 },
88 {
89 "emoji": "🐞",
90 "code": "🐞fix:",
91 "description": "A bug fix",
92 "name": "fix"
93 },
94 {
95 "emoji": "📝",
96 "code": "📝docs:",
97 "description": "update docs",
98 "name": "docs"
99 },
100 {
101 "emoji": "💰",
102 "code": "💰perf:",
103 "description": "Improves performance with this change",
104 "name": "perf"
105 },
106 {
107 "emoji": "🎨",
108 "code": "🎨style:",
109 "description": "Doesn't affect the meaning of the code (white-space, semi-colons, etc)",
110 "name": "style"
111 },
112 {
113 "emoji": "🚓",
114 "code": "🚓test:",
115 "description": "Testing improved with new or fixed tests",
116 "name": "test"
117 },
118 {
119 "emoji": "🔨",
120 "code": "🔨build-conf:",
121 "description": "更新一些配置文件",
122 "name": "build-conf"
123 },
124 {
125 "emoji": "💊",
126 "code": "💊revert:",
127 "description": "Reverts a previous commit",
128 "name": "revert"
129 }
130 ]
131 },
132 "commitizen": {
133 "path": "./node_modules/cz-emoji"
134 }
135 }
136 }
1 module.exports = {
2 // tab缩进大小,默认为2
3 tabWidth: 2,
4 // 使用tab缩进,默认false
5 useTabs: false,
6 // 使用分号, 默认true
7 semi: false,
8 // 使用单引号, 默认false(在jsx中配置无效, 默认都是双引号)
9 singleQuote: true,
10 // 行尾逗号,默认none,可选 none|es5|all
11 // es5 包括es5中的数组、对象
12 // all 包括函数对象等所有可选
13 TrailingCooma: 'none',
14 // 对象中的空格 默认true
15 // true: { foo: bar }
16 // false: {foo: bar}
17 bracketSpacing: true,
18 // JSX标签闭合位置 默认false
19 // false: <div
20 // className=""
21 // style={{}}
22 // >
23 // true: <div
24 // className=""
25 // style={{}} >
26 jsxBracketSameLine: false,
27 // 箭头函数参数括号 默认avoid 可选 avoid| always
28 // avoid 能省略括号的时候就省略 例如x => x
29 // always 总是有括号
30 arrowParens: 'avoid'
31 }
No preview for this file type
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="utf-8" />
5 <meta http-equiv="X-UA-Compatible" content="IE=edge" />
6 <meta name="viewport" content="width=device-width,initial-scale=1.0" />
7 <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
8 <title>云销</title>
9 <!-- strophe删除待定 -->
10 <!-- <script src="./libs/strophe/strophe.js"></script>
11 <script src="./libs/strophe/strophe.disco.min.js?v=1"></script>
12
13 <script src="./libs/jquery-2.1.1.min.js"></script>
14 <script src="./libs/lib-jitsi-meet.min.js"></script> -->
15 </head>
16 <body>
17 <noscript>
18 <strong
19 >We're sorry but smartimageplatform doesn't work properly without
20 JavaScript enabled. Please enable it to continue.</strong
21 >
22 </noscript>
23 <div id="app"></div>
24 <!-- built files will be auto injected -->
25 </body>
26 </html>
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
1 Strophe.addConnectionPlugin("disco",{_connection:null,_identities:[],_features:[],_items:[],init:function(conn){this._connection=conn;this._identities=[];this._features=[];this._items=[];conn.addHandler(this._onDiscoInfo.bind(this),Strophe.NS.DISCO_INFO,"iq","get",null,null);conn.addHandler(this._onDiscoItems.bind(this),Strophe.NS.DISCO_ITEMS,"iq","get",null,null)},addIdentity:function(category,type,name,lang){for(var i=0;i<this._identities.length;i++){if(this._identities[i].category==category&&this._identities[i].type==type&&this._identities[i].name==name&&this._identities[i].lang==lang){return false}}this._identities.push({category:category,type:type,name:name,lang:lang});return true},addFeature:function(var_name){for(var i=0;i<this._features.length;i++){if(this._features[i]==var_name){return false}}this._features.push(var_name);return true},removeFeature:function(var_name){for(var i=0;i<this._features.length;i++){if(this._features[i]===var_name){this._features.splice(i,1);return true}}return false},addItem:function(jid,name,node,call_back){if(node&&!call_back){return false}this._items.push({jid:jid,name:name,node:node,call_back:call_back});return true},info:function(jid,node,success,error,timeout){var attrs={xmlns:Strophe.NS.DISCO_INFO};if(node){attrs.node=node}var info=$iq({from:this._connection.jid,to:jid,type:"get"}).c("query",attrs);this._connection.sendIQ(info,success,error,timeout)},items:function(jid,node,success,error,timeout){var attrs={xmlns:Strophe.NS.DISCO_ITEMS};if(node){attrs.node=node}var items=$iq({from:this._connection.jid,to:jid,type:"get"}).c("query",attrs);this._connection.sendIQ(items,success,error,timeout)},_buildIQResult:function(stanza,query_attrs){var id=stanza.getAttribute("id");var from=stanza.getAttribute("from");var iqresult=$iq({type:"result",id:id});if(from!==null){iqresult.attrs({to:from})}return iqresult.c("query",query_attrs)},_onDiscoInfo:function(stanza){var node=stanza.getElementsByTagName("query")[0].getAttribute("node");var attrs={xmlns:Strophe.NS.DISCO_INFO};if(node){attrs.node=node}var iqresult=this._buildIQResult(stanza,attrs);for(var i=0;i<this._identities.length;i++){var attrs={category:this._identities[i].category,type:this._identities[i].type};if(this._identities[i].name){attrs.name=this._identities[i].name}if(this._identities[i].lang){attrs["xml:lang"]=this._identities[i].lang}iqresult.c("identity",attrs).up()}for(var i=0;i<this._features.length;i++){iqresult.c("feature",{"var":this._features[i]}).up()}this._connection.send(iqresult.tree());return true},_onDiscoItems:function(stanza){var query_attrs={xmlns:Strophe.NS.DISCO_ITEMS};var node=stanza.getElementsByTagName("query")[0].getAttribute("node");if(node){query_attrs.node=node;var items=[];for(var i=0;i<this._items.length;i++){if(this._items[i].node==node){items=this._items[i].call_back(stanza);break}}}else{var items=this._items}var iqresult=this._buildIQResult(stanza,query_attrs);for(var i=0;i<items.length;i++){var attrs={jid:items[i].jid};if(items[i].name){attrs.name=items[i].name}if(items[i].node){attrs.node=items[i].node}iqresult.c("item",attrs).up()}this._connection.send(iqresult.tree());return true}});
...\ No newline at end of file ...\ No newline at end of file
This diff could not be displayed because it is too large.
1 <template>
2 <div id="app">
3 <router-view />
4 </div>
5 </template>
6
7 <script>
8 export default {
9 methods: {
10 onlineMethod() {
11 this.$notify({ title: '网络恢复正常', type: 'success' })
12 },
13 offlineMethod() {
14 this.$notify.error({ title: '网络连接异常' })
15 }
16 },
17 beforeMount() {
18 window.addEventListener('online', this.onlineMethod)
19 window.addEventListener('offline', this.offlineMethod)
20 },
21 beforeDestroy() {
22 window.removeEventListener('online', this.onlineMethod)
23 window.removeEventListener('offline', this.offlineMethod)
24 }
25 }
26 </script>
27
28 <style lang="scss">
29 @mixin cover {
30 width: 100%;
31 height: 100%;
32 }
33 html,
34 body {
35 @include cover;
36 padding: 0;
37 margin: 0;
38 }
39 #app {
40 font-family: 'Avenir', Helvetica, Arial, sans-serif;
41 -webkit-font-smoothing: antialiased;
42 -moz-osx-font-smoothing: grayscale;
43 text-align: center;
44 color: #2c3e50;
45 @include cover;
46 }
47 #nav {
48 padding: 30px;
49 a {
50 font-weight: bold;
51 color: #2c3e50;
52 &.router-link-exact-active {
53 color: #42b983;
54 }
55 }
56 }
57 .el-main {
58 text-align: left;
59 }
60 a:focus,
61 a:active {
62 outline: none;
63 }
64
65 a,
66 a:focus,
67 a:hover {
68 cursor: pointer;
69 color: inherit;
70 text-decoration: none;
71 }
72 </style>
1 import request from '@/utils/request'
2
3 /**
4 * 7天业务量
5 * @param {*} data
6 */
7 export function volumeCalls(data) {
8 return request({
9 url: '/chery/homepage/volumeCalls',
10 method: 'post',
11 data
12 })
13 }
14
15 /**
16 * 通话时长
17 * @param {*} data
18 */
19 export function durationsCalls(data) {
20 return request({
21 url: '/chery/homepage/durationsCalls',
22 method: 'post',
23 data
24 })
25 }
1 import request from '@/utils/request'
2
3 /**
4 * 删除订单
5 */
6 export function deleteOrder(data) {
7 return request({
8 url: '/chery/order/delete',
9 method: 'post',
10 data
11 })
12 }
13
14 /**
15 * 全部订单列表查询
16 */
17 export function queryOrderList(data) {
18 return request({
19 url: '/chery/order/query/list',
20 method: 'post',
21 data
22 })
23 }
24 /**
25 * 全部订单列表查询
26 */
27 export function queryMyOrderList(data) {
28 return request({
29 url: '/chery/order/query/mylist',
30 method: 'post',
31 data
32 })
33 }
34 /**
35 * 订单详情
36 */
37 export function getOrderDetail(data) {
38 return request({
39 url: '/chery/order/detail/get',
40 method: 'post',
41 data
42 })
43 }
1 import request from '@/utils/request'
2
3 /**
4 * 创建合作商
5 * @param {*} data
6 */
7 export function createPattern(data) {
8 return request({
9 url: '/chery/partner/create',
10 method: 'post',
11 data
12 })
13 }
14
15 /**
16 * 删除合作商
17 * @param {*} data
18 */
19 export function deletePattern(data) {
20 return request({
21 url: '/chery/partner/delete',
22 method: 'post',
23 data
24 })
25 }
26
27 /**
28 * 查询合作商
29 * @param {*} data
30 */
31 export function queryPattern(data) {
32 return request({
33 url: '/chery/partner/query',
34 method: 'post',
35 data
36 })
37 }
38 /**
39 * 合作商code是否存在
40 * @param {*} data
41 */
42 export function validateCode(data) {
43 return request({
44 url: '/chery/partner/valid-code',
45 method: 'post',
46 data
47 })
48 }
49
50 /**
51 * 报表列表查询
52 * @param {*} data
53 */
54 export function reportList(data) {
55 return request({
56 url: '/chery/order/report/list',
57 method: 'post',
58 data
59 })
60 }
61
62 /**
63 * 报表下载接口
64 * @param {*} data
65 */
66 export function reportDownload(data) {
67 return request({
68 url: '/chery/order/report/download',
69 method: 'post',
70 responseType: 'blob',
71 data
72 })
73 }
1 import request from '@/utils/request'
2
3 /**
4 * tts开关
5 * @param {*} data
6 */
7 export function ttsSwitch(data) {
8 return request({
9 url: '/chery/tts/option/switch',
10 method: 'post',
11 data
12 })
13 }
14
15 /**
16 * web查询话术结果
17 * @param {*} data
18 */
19 export function getTtsResult(data) {
20 return request({
21 url: '/chery/tts/result',
22 method: 'post',
23 data
24 })
25 }
26 /**
27 * 保存tts
28 * @param {*} data
29 */
30 export function saveTts(data) {
31 return request({
32 url: '/chery/tts/save',
33 method: 'post',
34 data
35 })
36 }
37 /**
38 * web查询话术配置
39 * @param {*} data
40 */
41 export function getTtsTemplate(data) {
42 return request({
43 url: '/chery/tts/getTemplate',
44 method: 'post',
45 data
46 })
47 }
48 /**
49 * 查询tts是否开放
50 * @param {*} data
51 */
52 export function getTtsStatus(data) {
53 return request({
54 url: '/chery/call/workTimeStatus',
55 method: 'post',
56 data
57 })
58 }
1 import request from '@/utils/request'
2
3 /**
4 * 登录
5 * @param {*} data
6 */
7 export function login(data) {
8 return request({
9 url: '/chery/account/login',
10 method: 'post',
11 data
12 })
13 }
14
15 /**
16 * 登出
17 */
18 export function logout() {
19 return request({
20 url: '/chery/account/logout',
21 method: 'post'
22 })
23 }
24
25 /**
26 * 注册
27 * @param {*} data
28 */
29 export function registry(data) {
30 return request({
31 url: '/chery/account/registry',
32 method: 'post',
33 data
34 })
35 }
36
37 /**
38 * 重置密码
39 * @param {*} data
40 */
41 export function resetPassword(data) {
42 return request({
43 url: '/chery/account/reset-password',
44 method: 'post',
45 data
46 })
47 }
48
49 /**
50 * 删除
51 * @param {*} data
52 */
53 export function deleteUser(data) {
54 return request({
55 url: '/chery/account/delete',
56 method: 'post',
57 data
58 })
59 }
60
61 /**
62 * 禁用账号
63 * @param {*} data
64 */
65 export function accountAvailable(data) {
66 return request({
67 url: '/chery/account/available',
68 method: 'post',
69 data
70 })
71 }
72
73 /**
74 * 账号列表查询
75 * @param {*} data
76 */
77 export function accountList(data) {
78 return request({
79 url: '/chery/account/list',
80 method: 'post',
81 data
82 })
83 }
84 /**
85 * 验证工号是否已存在
86 * @param {*} data
87 */
88 export function validUsername(data) {
89 return request({
90 url: '/chery/account/valid-username',
91 method: 'post',
92 data
93 })
94 }
95 /**
96 * 监控开启关闭
97 * @param {*} data
98 */
99 export function switchMonitor(data) {
100 return request({
101 url: '/chery/account/switch-monitor',
102 method: 'post',
103 data
104 })
105 }
1 import request from '@/utils/request'
2
3 /**
4 * 确认接通
5 * @param {*} data
6 */
7 export function callWebConfirm(data) {
8 return request({
9 url: '/chery/call/web/confirm',
10 method: 'post',
11 data
12 })
13 }
14 /**
15 * 挂断电话
16 * @param {*} data
17 */
18 export function callWebDisconnect(data) {
19 return request({
20 url: '/chery/call/web/disconnect',
21 method: 'post',
22 data
23 })
24 }
25
26 /**
27 * 拨打电话
28 * @param {*} data
29 */
30 export function callWebIn(data) {
31 return request({
32 url: '/chery/call/web/in',
33 method: 'post',
34 data
35 })
36 }
37 /**
38 * 创建订单
39 * @param {*} data
40 */
41 export function createOrder(data) {
42 return request({
43 url: 'chery/order/create',
44 method: 'post',
45 data
46 })
47 }
48 /**
49 * 删除订单
50 * @param {*} data
51 */
52 export function deleteOrder(data) {
53 return request({
54 url: '/chery/order-system/delete',
55 method: 'post',
56 data
57 })
58 }
59
60 /**
61 * web-推送消息到app
62 * @param {*} data
63 */
64 export function notifyApp(data) {
65 return request({
66 url: '/chery/notify/app',
67 method: 'post',
68 data
69 })
70 }
71 /**
72 * 工作台未沟通/已沟通列表
73 * @param {*} data
74 */
75 export function getCommunicationList(data) {
76 return request({
77 url: '/chery/order/web/list',
78 method: 'post',
79 data
80 })
81 }
82 /**
83 * WEB-获取排队列表
84 * @param {*} data
85 */
86 export function getQueueQuery(data) {
87 return request({
88 url: '/chery/call/web/queue/query',
89 method: 'post',
90 data
91 })
92 }
93 /**
94 *WEB-查询订单信息
95 * @param {*} data
96 */
97 export function getOrderInfo(data) {
98 return request({
99 url: '/chery/order/fetch/order-info',
100 method: 'post',
101 data
102 })
103 }
104 /**
105 * 二要素比图身份认证接口
106 * @param {*} data
107 */
108 export function twoElementFace(data) {
109 return request({
110 url: '/chery/external/two-element-face/verify',
111 method: 'post',
112 data
113 })
114 }
115 /**
116 *情绪程度识别
117 * @param {*} data
118 */
119 export function emotionRecognize(data) {
120 return request({
121 url: '/chery/external/emotion/recognize',
122 method: 'post',
123 data
124 })
125 }
126 /**
127 * WEB-等待接通
128 * @param {*} data
129 */
130 export function callWebWait(data) {
131 return request({
132 url: '/chery/call/web/wait',
133 method: 'post',
134 data
135 })
136 }
137 /**
138 * WEB-等待接通
139 * @param {*} data
140 */
141 export function callWebPoll(data) {
142 return request({
143 url: '/chery/call/web/poll',
144 method: 'post',
145 data
146 })
147 }
No preview for this file type
No preview for this file type
1 h1,
2 h2,
3 h3,
4 h4,
5 h5,
6 h6 {
7 padding: 0;
8 margin: 0;
9 }
10
11 .upload-cropper {
12 display: inline-block;
13 width: 300px;
14 background: #f2f2f2;
15 }
16 // 外边距
17 .mb5 {
18 margin-bottom: 5px;
19 }
20
21 .mb10 {
22 margin-bottom: 10px;
23 }
24
25 .mb20 {
26 margin-bottom: 20px;
27 }
28 .mr5 {
29 margin-right: 5px;
30 }
31
32 .text-align-center {
33 text-align: center;
34 }
35
36 .forbid {
37 background-color: #f5f7fa;
38 border-color: #e4e7ed;
39 color: #c0c4cc;
40 cursor: not-allowed;
41 }
42 // 全局修改card样式
43 .el-card .el-card__body {
44 padding: 5px;
45 }
46
47 // color
48 .white {
49 color: white;
50 }
51
52 // 图片资源
53
54 .username-icon {
55 background: center no-repeat url('./assets/image/username.png');
56 }
57 .password-icon {
58 background: center no-repeat url('./assets/image/password.png');
59 }
60 .validate-icon {
61 background: center no-repeat url('./assets/image/validate.png');
62 }
63 .login-form-bg {
64 background: center / cover no-repeat url('./assets/image/login-form-bg.png');
65 }
1 <template>
2 <div class="bread">
3 <div>
4 <slot name="title"></slot>
5 <span class="btn">
6 <slot name="btn"></slot>
7 </span>
8 </div>
9 <el-button
10 v-if="isShowBack"
11 type="text"
12 style="margin-right:50px;"
13 @click="handleClick"
14 >返回</el-button
15 >
16 </div>
17 </template>
18 <script>
19 export default {
20 name: 'Bread',
21 props: {
22 isShowBack: {
23 type: Boolean,
24 default: false
25 }
26 },
27 methods: {
28 handleClick() {
29 this.$router.go(-1)
30 }
31 }
32 }
33 </script>
34 <style lang="scss" scoped>
35 .bread {
36 display: flex;
37 align-items: center;
38 justify-content: space-between;
39 height: 50px;
40 border-left: 5px solid #3f51b5;
41 padding-left: 15px;
42 font-size: 16px;
43 font-weight: 700;
44 .btn {
45 display: inline-block;
46 color: #3f51b5;
47 margin-left: 15px;
48 font-size: 20px;
49 cursor: pointer;
50 }
51 }
52 </style>
1 import Bread from './Bread.vue'
2 export default Bread
1 <template>
2 <div class="card-com">
3 <div><slot name="title"></slot></div>
4 <slot></slot>
5 </div>
6 </template>
7
8 <script>
9 export default {}
10 </script>
11
12 <style lang="scss" scoped>
13 .card-com {
14 padding: 28px 24px;
15 box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
16 box-sizing: border-box;
17 background-color: #fff;
18 }
19 </style>
1 <template lang="pug">
2 span(ref="countUp")
3 </template>
4 <script>
5 import { CountUp } from 'countup.js'
6
7 export default {
8 name: 'CountUp',
9 props: {
10 // 目标数字
11 end: {
12 type: Number,
13 default: 0
14 },
15 // 默认配置
16 options: {
17 type: Object,
18 default: () => {
19 return {
20 startVal: 0,
21 decimalPlaces: 0,
22 duration: 1,
23 separator: ',',
24 decimal: '.'
25 }
26 }
27 }
28 },
29 data() {
30 return {
31 numAnim: null
32 }
33 },
34 watch: {
35 end: {
36 handler(newVal, oldVal) {
37 this.numAnim.update(newVal)
38 }
39 }
40 },
41 mounted() {
42 this.initCountUp()
43 },
44 beforeDestroy() {
45 this.numAnim = null
46 },
47 methods: {
48 initCountUp() {
49 this.numAnim = new CountUp(this.$refs.countUp, this.end, this.options)
50 if (!this.numAnim.error) {
51 this.numAnim.start()
52 } else {
53 console.error(this.numAnim.error)
54 }
55 }
56 }
57 }
58 </script>
1 <template>
2 <svg :class="svgClass" aria-hidden="true">
3 <use :xlink:href="iconName"></use>
4 </svg>
5 </template>
6
7 <script>
8 export default {
9 name: 'icon-svg',
10 props: {
11 iconClass: {
12 type: String,
13 required: true
14 },
15 className: {
16 type: String
17 }
18 },
19 computed: {
20 iconName() {
21 return `#icon-${this.iconClass}`
22 },
23 svgClass() {
24 if (this.className) {
25 return `svg-icon ${this.className}`
26 } else {
27 return `svg-icon`
28 }
29 }
30 }
31 }
32 </script>
33
34 <style>
35 .svg-icon {
36 width: 1em;
37 height: 1em;
38 fill: currentColor;
39 overflow: hidden;
40 }
41 </style>
1 <template lang="pug">
2 div(class="login-main login-form-bg")
3 div(class="title")
4 .main-content
5 el-form(:model="loginForm" ref="form" :rules="rules" @keydown.enter.native="login")
6 el-form-item(prop="username")
7 el-input(
8 ref="username"
9 size="medium"
10 class="login-input"
11 placeholder="请输入工号"
12 v-model.trim="loginForm.username"
13 )
14 i(slot="prefix" class="icon username-icon")
15 el-form-item(prop="password")
16 el-input(
17 ref="password"
18 type="password"
19 size="medium"
20 placeholder="请输入密码"
21 class="login-input"
22 v-model.trim="loginForm.password"
23 )
24 i(slot="prefix" class="icon password-icon")
25 el-form-item(prop="verificationCode")
26 .captcha
27 el-input(
28 size="medium"
29 placeholder="请输入验证码"
30 class="captcha-input"
31 v-model.trim="loginForm.verificationCode"
32 )
33 i(slot="prefix" class="icon validate-icon")
34 <canvas width="93" height="36" id="captcha1"></canvas>
35 el-form-item
36 .buton-warp
37 el-button(class="login-btn" type="primary" @click="login" :loading="loading")
38 span(class="login-btn-text") 登&nbsp;&nbsp;&nbsp;&nbsp;录
39 </template>
40
41 <script>
42 import Captcha from 'captcha-mini'
43 import { maxSizeValidate } from '@/views/validate'
44
45 export default {
46 name: 'LoginForm',
47 props: {
48 usernameRules: {
49 type: Array,
50 default: () => {
51 return [
52 { required: true, message: '账号不能为空', trigger: 'blur' },
53 maxSizeValidate
54 ]
55 }
56 },
57 passwordRules: {
58 type: Array,
59 default: () => {
60 return [
61 { required: true, message: '密码不能为空', trigger: 'blur' },
62 maxSizeValidate
63 ]
64 }
65 },
66 loading: {
67 type: Boolean,
68 default: false
69 }
70 },
71 data() {
72 return {
73 verCode: '',
74 captcha1: null,
75 loginForm: {
76 username: '',
77 password: '',
78 verificationCode: ''
79 }
80 }
81 },
82 computed: {
83 rules() {
84 return {
85 username: this.usernameRules,
86 password: this.passwordRules,
87 verificationCode: [
88 {
89 validator: (rule, value, callback) => {
90 if (value === '') {
91 return callback(new Error('验证码不能为空'))
92 }
93 if (value.toLowerCase() !== this.verCode.toLowerCase()) {
94 return callback(new Error('请输入正确的验证码'))
95 } else {
96 callback()
97 }
98 },
99 trigger: 'blur'
100 },
101 maxSizeValidate
102 ]
103 }
104 }
105 },
106 mounted() {
107 if (this.loginForm.username === '') {
108 this.$refs.username.focus()
109 }
110 this.captcha1 = new Captcha()
111 this.updateCaptcha()
112 },
113 methods: {
114 login() {
115 this.$refs.form.validate(valid => {
116 if (valid) {
117 this.$emit('on-success-valid', {
118 username: this.loginForm.username,
119 password: this.loginForm.password
120 })
121 } else {
122 this.updateCaptcha()
123 }
124 })
125 },
126 updateCaptcha() {
127 this.captcha1.draw(document.querySelector('#captcha1'), r => {
128 this.verCode = r
129 })
130 }
131 }
132 }
133 </script>
134
135 <style lang="scss">
136 .login-main {
137 height: 420px;
138 width: 420px;
139 display: flex;
140 flex-flow: column nowrap;
141 align-items: center;
142 padding: 0 48px;
143 box-sizing: border-box;
144 .title {
145 width: 292px;
146 height: 36px;
147 margin: 32px 0 36px 0;
148 }
149 .main-content {
150 .captcha {
151 display: flex;
152 }
153 .login-btn {
154 width: 100%;
155 height: 48px;
156 .login-btn-text {
157 font-size: 18px;
158 }
159 }
160 }
161 }
162 // 重置输入框 图标
163 .login-input {
164 .el-input__prefix {
165 display: inline-flex;
166 align-items: center;
167 }
168 .el-input__inner {
169 height: 44px;
170 width: 324px;
171 }
172 }
173 .captcha-input {
174 margin-right: 7px;
175 .el-input__prefix {
176 display: inline-flex;
177 align-items: center;
178 }
179 .el-input__inner {
180 height: 44px;
181 }
182 }
183 .login-input,
184 .captcha-input {
185 .el-input__inner {
186 background: #0f1f3b;
187 padding-left: 46px;
188 color: rgba(255, 255, 255, 1);
189 background: rgba(193, 225, 253, 0.03);
190 border-radius: 4px;
191 border: 1px solid rgba(24, 144, 255, 0.2);
192 }
193 .el-input__inner:active,
194 .el-input__inner:focus {
195 background: rgba(193, 225, 253, 0.03);
196 border-radius: 4px;
197 border: 1px solid rgba(94, 178, 255, 0.8);
198 }
199 .el-input__prefix {
200 left: 14px;
201 }
202 }
203 .icon {
204 width: 20px;
205 height: 20px;
206 display: inline-block;
207 }
208 </style>
1 import LoginForm from './LoginForm.vue'
2 export default LoginForm
1 <template>
2 <div
3 class="wrapper"
4 ref="wrapper"
5 @mousemove="mousemove"
6 @mouseenter="mouseenter"
7 @mouseleave="mouseleave"
8 @wheel="zoom"
9 >
10 <transition name="fade">
11 <div class="zoomed-container" v-show="isShow">
12 <div
13 class="transform-view"
14 :style="{
15 transform: `scale(${tempScale}, ${tempScale}) translate(${translateX}%, ${translateY}%)`
16 }"
17 >
18 <img :src="url" alt="" />
19 </div>
20 </div>
21 </transition>
22 <div class="view">
23 <img :src="url" alt="" />
24 </div>
25 </div>
26 </template>
27
28 <script>
29 import url from '@/assets/test.jpg'
30
31 export default {
32 props: {
33 scale: {
34 type: Number,
35 default: 2,
36 validator: val => {
37 if (val >= 1 && val <= 10) {
38 return val
39 } else {
40 return 1
41 }
42 }
43 }
44 },
45 data() {
46 return {
47 url,
48 translateX: 0,
49 translateY: 0,
50 tempScale: this.scale,
51 isShow: false
52 }
53 },
54 methods: {
55 zoom(e) {
56 e.preventDefault()
57 this.tempScale += e.deltaY * -0.01
58 this.tempScale = Math.min(Math.max(1, this.tempScale), 10)
59 },
60 mousemove(e) {
61 const {
62 left,
63 top,
64 width,
65 height
66 } = this.$refs.wrapper.getBoundingClientRect()
67 const x = e.clientX
68 const y = e.clientY
69 const percentW = (x - left) / width
70 const percentH = (y - top) / height
71 this.translateX = (0.4 - percentW) * 100
72 this.translateY = (0.4 - percentH) * 100
73 },
74 mouseenter() {
75 this.isShow = true
76 },
77 mouseleave() {
78 this.isShow = false
79 }
80 }
81 }
82 </script>
83
84 <style lang="scss" scoped>
85 // 过度效果
86 .fade-enter-active,
87 .fade-leave-active {
88 transition: opacity 0.5s;
89 }
90 .fade-enter,
91 .fade-leave-to {
92 opacity: 0;
93 }
94 .wrapper {
95 width: 400px;
96 height: 357px;
97 position: relative;
98 overflow: hidden;
99 box-sizing: border-box;
100 .zoomed-container {
101 background: #000;
102 position: absolute;
103 left: 5px;
104 top: 5px;
105 right: 5px;
106 bottom: 5px;
107 z-index: 9999;
108 overflow: hidden;
109 .transform-view {
110 position: absolute;
111 top: 0;
112 left: 0;
113 bottom: 0;
114 right: 0;
115 text-align: center;
116 img {
117 height: 100%;
118 }
119 }
120 }
121 .view {
122 position: absolute;
123 left: 5px;
124 top: 5px;
125 right: 5px;
126 bottom: 5px;
127 text-align: center;
128 img {
129 height: 100%;
130 }
131 }
132 }
133 </style>
1 <template lang="pug">
2 .play-audio
3 audio(ref="audio" :src="mp3")
4 </template>
5 <script>
6 import mp3 from '@/assets/ding.mp3'
7 export default {
8 name: 'PlayAudio',
9 props: {
10 mp3: {
11 type: [String, Blob, null],
12 default: mp3
13 }
14 },
15 data() {
16 return {
17 audioStatus: 'pause',
18 audioDuration: 0
19 }
20 },
21 methods: {
22 /**
23 * 播放提示音
24 * */
25 playMusic() {
26 if (this.audioStatus === 'pause') {
27 this.$refs.audio.play()
28 this.audioStatus = 'play'
29 } else {
30 this.$refs.audio.pause()
31 this.$refs.audio.currentTime = 0
32 this.audioStatus = 'pause'
33 }
34 }
35 },
36 mounted() {
37 this.$refs.audio.addEventListener('ended', () => {
38 this.$refs.audio.pause()
39 this.audioStatus = 'pause'
40 })
41 }
42 }
43 </script>
1 <template lang="pug">
2 .start-step
3 el-button(type="primary" icon="el-icon-caret-right" class="btn" v-on="buttonListeners") 开始
4 </template>
5 <script>
6 export default {
7 computed: {
8 buttonListeners() {
9 return Object.assign({}, this.$listeners)
10 }
11 }
12 }
13 </script>
14 <style lang="scss" scoped>
15 .start-step {
16 display: flex;
17 justify-content: center;
18 align-items: center;
19 width: 100%;
20 height: 100%;
21 background-color: #eee;
22 .btn {
23 display: flex;
24 justify-content: flex-start;
25 align-items: center;
26 width: 100px;
27 height: 70px;
28 font-size: 23px;
29 font-weight: 900;
30 padding: 0 10px;
31 border-radius: 13px;
32 box-shadow: 4px 5px 3px;
33 .el-icon-caret-right {
34 font-size: 50px;
35 }
36 }
37 }
38 </style>
39 <style lang="scss">
40 .start-step {
41 .btn {
42 .el-icon-caret-right {
43 font-size: 50px;
44 margin-left: -20px;
45 }
46 }
47 }
48 </style>
1 <template lang="pug">
2 .title-line
3 .header-wrapper
4 .left
5 slot(name="title")
6 .info
7 slot(name="info")
8 .right
9 slot(name="right")
10 .main
11 slot
12 </template>
13 <script>
14 export default {
15 name: 'TitleLine'
16 }
17 </script>
18 <style lang="scss" scoped>
19 .title-line{
20 width: 100%;
21 font-size: 18px;
22 .header-wrapper{
23 color: #fff;
24 display: flex;
25 justify-content: flex-start;
26 align-items: center;
27 background: #a3add8;
28 height: 30px;
29 padding: 5px 10px;
30 .left{
31 padding-right: 5px;
32 }
33 .right{
34 flex: auto;
35 display: flex;
36 justify-content: flex-end;
37 }
38 }
39 .main{
40 padding: 10px 5px;
41 }
42 }
43 </style>
1 <template lang="pug">
2 .top-tesk-detail
3 .status-text {{statusText}}
4 el-switch(
5 :value="copyValue"
6 @change="change"
7 )
8 template(v-if="isOpen")
9 .task-info
10 .over-task.mr5 剩余任务
11 .mr5 已完成
12 .already.mr5 {{completed}}
13 .mr5 待质检
14 .wait.mr5 {{wait}}
15 .countDown(v-if="copyCountDownTime !== 0") {{countDownText}}
16 </template>
17 <script>
18 export default {
19 name: 'TopTeskDetails',
20 props: {
21 isOpen: {
22 type: Boolean,
23 required: true
24 },
25 completed: {
26 type: [Number, String],
27 default: 0
28 },
29 wait: {
30 type: [Number, String],
31 default: 0
32 },
33 countDownTime: {
34 type: Number,
35 default: 0
36 }
37 },
38 data() {
39 return {
40 timer: null, // 计时器
41 second: this.timeout, // 倒计时时间
42 copyValue: this.isOpen,
43 copyCountDownTime: this.countDownTime
44 }
45 },
46 computed: {
47 statusText() {
48 return this.isOpen ? '进行中' : '开始'
49 },
50 countDownText() {
51 return this.copyCountDownTime === 0 ? '-' : this.copyCountDownTime
52 }
53 },
54 watch: {
55 isOpen: {
56 handler(val) {
57 if (val && this.copyCountDownTime) {
58 this.startTimeout()
59 }
60 },
61 immediate: true
62 }
63 },
64 methods: {
65 startTimeout() {
66 setTimeout(this.nextSecond, 1000)
67 },
68 nextSecond() {
69 this.copyCountDownTime--
70 if (this.copyCountDownTime === 0) {
71 this.$emit('update:isOpen', false)
72 return
73 }
74 setTimeout(this.nextSecond, 1000)
75 },
76 change(val) {
77 this.$nextTick(() => {
78 this.$emit('update:isOpen', val)
79 })
80 }
81 }
82 }
83 </script>
84 <style lang="scss" scoped>
85 .top-tesk-detail {
86 height: 35px;
87 display: flex;
88 flex-flow: row nowrap;
89 justify-content: flex-start;
90 align-items: center;
91 .status-text {
92 width: 70px;
93 text-align: center;
94 font-size: 16px;
95 color: #333;
96 font-weight: 600;
97 }
98 .task-info {
99 margin: 0 5px;
100 font-size: 14px;
101 display: flex;
102 align-items: center;
103 .over-task {
104 font-weight: 500;
105 }
106 .already {
107 padding: 0 5px;
108 border-radius: 3px;
109 background-color: #52c3f1;
110 }
111 .wait {
112 padding: 0 5px;
113 border-radius: 3px;
114 background-color: #f19b12;
115 }
116 }
117 /* 倒计时*/
118 .countDown {
119 width: 35px;
120 height: 35px;
121 display: flex;
122 justify-content: center;
123 align-items: center;
124 font-size: 12px;
125 border-radius: 50%;
126 border: 3px solid #3f51b5;
127 box-sizing: border-box;
128 }
129 }
130 </style>
1 <template>
2 <div class="upload-wrapper">
3 <label>{{ placeholderCopy }}</label>
4 <div class="uw-right">
5 <el-button class="uw-btn">
6 <slot></slot>
7 </el-button>
8 <input
9 class="uw-input"
10 type="file"
11 id="image_uploads"
12 name="image_uploads"
13 :accept="accept"
14 :multiple="multiple"
15 @change="handleChange"
16 />
17 </div>
18 </div>
19 </template>
20
21 <script>
22 export default {
23 props: {
24 placeholder: {
25 type: String,
26 default: '上传图片,可多选'
27 },
28 accept: {
29 type: String,
30 default: '.jpg, .jpeg, .png, .JPG, .JPEG, .PNG, .bmp, .BMP'
31 },
32 multiple: {
33 type: Boolean,
34 default: false
35 },
36 onExceed: {
37 type: Function,
38 default: () => {}
39 },
40 limit: {
41 type: Number
42 },
43 onChange: {
44 type: Function,
45 default: () => {}
46 }
47 },
48 data() {
49 return {
50 placeholderCopy: this.placeholder
51 }
52 },
53 methods: {
54 handleChange(e) {
55 const files = e.currentTarget.files
56 const length = files.length
57 if (!this.isValidator(files)) {
58 this.$emit('onFail', files)
59 return
60 }
61 if (this.limit && length > this.limit) {
62 this.onExceed()
63 return
64 }
65 if (files.length > 0) {
66 this.placeholderCopy = files[0].name
67 this.onChange(Array.from(files))
68 }
69 },
70 getAcceptType() {
71 const arr = this.accept
72 .toLowerCase()
73 .split(',')
74 .map(item => `image/${item.slice(item.indexOf('.') + 1)}`)
75 return Array.from(new Set(arr))
76 },
77 isValidator(files) {
78 return Array.from(files).every(file =>
79 this.getAcceptType().includes(file.type)
80 )
81 }
82 },
83 mounted() {
84 this.getAcceptType()
85 }
86 }
87 </script>
88
89 <style lang="scss" scoped>
90 .upload-wrapper {
91 width: 300px;
92 height: 42px;
93 background: #f2f2f2;
94 display: inline-block;
95 position: relative;
96 label {
97 font-size: 12px;
98 line-height: 42px;
99 width: 100%;
100 display: inline-block;
101 height: 100%;
102 overflow: hidden;
103 }
104 .uw-right {
105 position: absolute;
106 top: 0;
107 bottom: 0;
108 right: 0;
109 width: 70px;
110 }
111 input {
112 position: absolute;
113 top: 0;
114 bottom: 0;
115 right: 0;
116 width: 100%;
117 height: 100%;
118 opacity: 0;
119 cursor: pointer;
120 }
121 }
122 </style>
1 /* eslint-disable */
2 const Exif = {}
3
4 Exif.getData = img =>
5 new Promise((reslove, reject) => {
6 let obj = {}
7 getImageData(img)
8 .then(data => {
9 obj.arrayBuffer = data
10 obj.orientation = getOrientation(data)
11 reslove(obj)
12 })
13 .catch(error => {
14 reject(error)
15 })
16 })
17
18 // 这里的获取exif要将图片转ArrayBuffer对象,这里假设获取了图片的baes64
19 // 步骤一
20 // base64转ArrayBuffer对象
21 function getImageData(img) {
22 let data = null
23 return new Promise((reslove, reject) => {
24 if (img.src) {
25 if (/^data\:/i.test(img.src)) {
26 // Data URI
27 data = base64ToArrayBuffer(img.src)
28 reslove(data)
29 } else if (/^blob\:/i.test(img.src)) {
30 // Object URL
31 var fileReader = new FileReader()
32 fileReader.onload = function(e) {
33 data = e.target.result
34 reslove(data)
35 }
36 objectURLToBlob(img.src, function(blob) {
37 fileReader.readAsArrayBuffer(blob)
38 })
39 } else {
40 var http = new XMLHttpRequest()
41 http.onload = function() {
42 if (this.status == 200 || this.status === 0) {
43 data = http.response
44 reslove(data)
45 } else {
46 throw 'Could not load image'
47 }
48 http = null
49 }
50 http.open('GET', img.src, true)
51 http.responseType = 'arraybuffer'
52 http.send(null)
53 }
54 } else {
55 reject('img error')
56 }
57 })
58 }
59
60 function objectURLToBlob(url, callback) {
61 var http = new XMLHttpRequest()
62 http.open('GET', url, true)
63 http.responseType = 'blob'
64 http.onload = function(e) {
65 if (this.status == 200 || this.status === 0) {
66 callback(this.response)
67 }
68 }
69 http.send()
70 }
71
72 function base64ToArrayBuffer(base64) {
73 base64 = base64.replace(/^data\:([^\;]+)\;base64,/gim, '')
74 var binary = atob(base64)
75 var len = binary.length
76 var buffer = new ArrayBuffer(len)
77 var view = new Uint8Array(buffer)
78 for (var i = 0; i < len; i++) {
79 view[i] = binary.charCodeAt(i)
80 }
81 return buffer
82 }
83 // 步骤二,Unicode码转字符串
84 // ArrayBuffer对象 Unicode码转字符串
85 function getStringFromCharCode(dataView, start, length) {
86 var str = ''
87 var i
88 for (i = start, length += start; i < length; i++) {
89 str += String.fromCharCode(dataView.getUint8(i))
90 }
91 return str
92 }
93
94 // 步骤三,获取jpg图片的exif的角度(在ios体现最明显)
95 function getOrientation(arrayBuffer) {
96 var dataView = new DataView(arrayBuffer)
97 var length = dataView.byteLength
98 var orientation
99 var exifIDCode
100 var tiffOffset
101 var firstIFDOffset
102 var littleEndian
103 var endianness
104 var app1Start
105 var ifdStart
106 var offset
107 var i
108 // Only handle JPEG image (start by 0xFFD8)
109 if (dataView.getUint8(0) === 0xff && dataView.getUint8(1) === 0xd8) {
110 offset = 2
111 while (offset < length) {
112 if (
113 dataView.getUint8(offset) === 0xff &&
114 dataView.getUint8(offset + 1) === 0xe1
115 ) {
116 app1Start = offset
117 break
118 }
119 offset++
120 }
121 }
122 if (app1Start) {
123 exifIDCode = app1Start + 4
124 tiffOffset = app1Start + 10
125 if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') {
126 endianness = dataView.getUint16(tiffOffset)
127 littleEndian = endianness === 0x4949
128
129 if (littleEndian || endianness === 0x4d4d /* bigEndian */) {
130 if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002a) {
131 firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian)
132
133 if (firstIFDOffset >= 0x00000008) {
134 ifdStart = tiffOffset + firstIFDOffset
135 }
136 }
137 }
138 }
139 }
140 if (ifdStart) {
141 length = dataView.getUint16(ifdStart, littleEndian)
142
143 for (i = 0; i < length; i++) {
144 offset = ifdStart + i * 12 + 2
145 if (
146 dataView.getUint16(offset, littleEndian) === 0x0112 /* Orientation */
147 ) {
148 // 8 is the offset of the current tag's value
149 offset += 8
150
151 // Get the original orientation value
152 orientation = dataView.getUint16(offset, littleEndian)
153
154 // Override the orientation with its default value for Safari (#120)
155 // if (IS_SAFARI_OR_UIWEBVIEW) {
156 // dataView.setUint16(offset, 1, littleEndian);
157 // }
158 break
159 }
160 }
161 }
162 return orientation
163 }
164
165 export default Exif
1 import VueCropper from './vueCropper.vue'
2 export default VueCropper
1 import permission from './permission'
2
3 const install = function(Vue) {
4 Vue.directive('permission', permission)
5 }
6
7 if (window.Vue) {
8 window['permission'] = permission
9 Vue.use(install) // eslint-disable-line
10 }
11
12 permission.install = install
13 export default permission
1 import store from '@/store'
2
3 export default {
4 inserted(el, binding, vnode) {
5 const { value } = binding
6 const roles = store.state.roles
7 if (value && value instanceof Array && value.length > 0) {
8 const permissionRoles = value
9 const hasPermission = roles.some(role => {
10 return permissionRoles.includes(role)
11 })
12 if (!hasPermission) {
13 el.parentNode && el.parentNode.removeChild(el)
14 }
15 } else {
16 throw new Error(`need roles! Like v-permission="['factory','normal']"`)
17 }
18 }
19 }
1 /* 改变主题色变量 */
2 $--color-primary: #409eff;
3
4 /* 改变 icon 字体路径变量,必需 */
5 $--font-path: '~element-ui/lib/theme-chalk/fonts';
6
7 @import '~element-ui/packages/theme-chalk/src/index';
1 import Vue from 'vue'
2 import SvgIcon from '@/components/iconComponent'
3
4 Vue.component('svg-icon', SvgIcon)
5
6 const req = require.context('./svg', false, /\.svg$/)
7 const requireAll = requireContext => requireContext.keys().map(requireContext)
8 requireAll(req)
1 <?xml version="1.0" encoding="UTF-8"?>
2 <svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3 <!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
4 <title>账号管理-白</title>
5 <desc>Created with Sketch.</desc>
6 <g id="奇瑞后台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7 <g id="图标" transform="translate(-23.000000, -131.000000)">
8 <g id="编组-4" transform="translate(23.000000, 131.000000)">
9 <g id="账号管理" fill="#FFFFFF" fill-rule="nonzero">
10 <path d="M10.2230216,8.05755396 C9.4851496,8.02906906 8.80393552,8.45160855 8.50160716,9.12530285 C8.19927879,9.79899715 8.33644267,10.5887935 8.84821755,11.1211026 C9.35999242,11.6534116 10.1437849,11.8215235 10.8288455,11.545918 C11.5139061,11.2703125 11.9629036,10.6062391 11.9634532,9.86781775 C11.9494922,9.39289432 11.7753247,8.93665107 11.4692566,8.57323741 C11.129455,8.25694548 10.6869616,8.07384474 10.2230216,8.05755396 L10.2230216,8.05755396 Z M10.2230216,10.6467146 C9.81930162,10.6131005 9.50875278,10.2756205 9.50875278,9.8705036 C9.50875278,9.46538668 9.81930162,9.12790668 10.2230216,9.09429257 C10.4178006,9.11007026 10.6040891,9.18085988 10.7601918,9.29841727 C10.9065942,9.44997563 10.9792327,9.65807506 10.9589448,9.86781775 C10.9431396,10.2702783 10.6250454,10.595338 10.2230216,10.6198561 L10.2230216,10.6467146 Z" id="形状"></path>
11 <path d="M13.7790887,8.96 C13.3974741,8.86313379 13.0711026,8.61635671 12.873916,8.27557784 C12.6767294,7.93479897 12.625418,7.52886251 12.7316067,7.14973621 C12.7397811,7.07569471 12.7206831,7.00121265 12.6778897,6.94023981 C12.331848,6.62256644 11.9266321,6.37615136 11.4853717,6.21505995 C11.4130369,6.20722007 11.340353,6.22634744 11.281247,6.26877698 C11.0209363,6.57522731 10.6357013,6.7471014 10.233765,6.73611511 C9.83422948,6.73546094 9.45365256,6.56566509 9.18628297,6.26877698 C9.12953599,6.225711 9.05824525,6.20644323 8.98752998,6.21505995 C8.54460609,6.37602801 8.13760745,6.62241732 7.78964029,6.94023981 C7.72248855,6.98754531 7.70166323,7.07778837 7.74129496,7.14973621 C7.84086816,7.53447 7.78693155,7.94284719 7.59088729,8.28853717 C7.40923551,8.63687962 7.07923085,8.88388909 6.69381295,8.96 C6.64546763,8.96 6.5971223,9.01371703 6.54340528,9.11577938 C6.44660599,9.59438721 6.44660599,10.0875313 6.54340528,10.5661391 C6.54340528,10.6198561 6.5971223,10.6682014 6.69381295,10.7219185 C7.07608824,10.8050007 7.40343248,11.0500189 7.59088729,11.3933813 C7.78725971,11.7409174 7.84117696,12.1510736 7.74129496,12.537554 C7.73460668,12.6090549 7.75159257,12.6807731 7.78964029,12.7416787 C8.13760745,13.0595011 8.54460609,13.3058905 8.98752998,13.4668585 L9.041247,13.4668585 C9.0944142,13.4734903 9.14772828,13.4557189 9.18628297,13.4185132 C9.44559503,13.1168804 9.82528379,12.9457254 10.2230216,12.9511751 C10.634041,12.9446659 11.0270554,13.1195573 11.2973621,13.4292566 C11.3510791,13.4776019 11.3994245,13.4776019 11.5014868,13.4776019 C11.9427472,13.3165105 12.3479631,13.0700954 12.6940048,12.7524221 C12.7477218,12.698705 12.7960671,12.6503597 12.7477218,12.5482974 C12.6182907,12.1794361 12.6506553,11.7730677 12.8368394,11.4293432 C13.0230235,11.0856187 13.3457101,10.8365079 13.7253717,10.7434053 C13.7790887,10.7434053 13.8274341,10.6896882 13.8757794,10.5876259 C13.9779384,10.1095695 13.9779384,9.61532259 13.8757794,9.13726619 C13.8757794,9.06743405 13.8274341,9.01371703 13.7790887,8.96 Z M12.9088729,10.2545803 C12.5570203,10.3738745 12.2571941,10.6110788 12.0601439,10.9260432 C11.8674513,11.2354631 11.812917,11.6113602 11.9097362,11.9627818 C11.6995825,12.1612408 11.4427762,12.3035004 11.1630695,12.3764029 C10.9001251,12.1084012 10.539367,11.9590551 10.1639329,11.9627818 C9.79228538,11.9773991 9.4380279,12.124054 9.16479616,12.3764029 C8.90552032,12.2581748 8.65587259,12.1198807 8.4181295,11.9627818 C8.52125061,11.6117806 8.46633703,11.2332691 8.26772182,10.9260432 C8.07378679,10.6083049 7.77282806,10.3702047 7.41899281,10.2545803 C7.37050545,9.96292879 7.37050545,9.66527265 7.41899281,9.3736211 C7.78078559,9.26252636 8.0899869,9.0239451 8.28920863,8.70215827 C8.48447126,8.39368341 8.53916815,8.01666554 8.43961631,7.66541966 C8.65057904,7.46806986 8.90708761,7.32597519 9.18628297,7.25179856 C9.44922742,7.51980025 9.80998552,7.66914635 10.1854197,7.66541966 C10.5570671,7.65080237 10.9113246,7.50414739 11.1845564,7.25179856 C11.4444148,7.36886747 11.6941537,7.50721202 11.931223,7.66541966 C11.8309713,8.01661891 11.8857103,8.393927 12.0816307,8.70215827 C12.2702379,9.01594747 12.5630021,9.25358071 12.9088729,9.3736211 C12.9573603,9.66527265 12.9573603,9.96292879 12.9088729,10.2545803 L12.9088729,10.2545803 Z M1.51545602,10.8776978 L2.50925659,10.8776978 C2.485191,9.19597558 3.81990192,7.80854717 5.50129496,7.76748201 C5.95305398,7.76791383 6.39837238,7.87464303 6.801247,8.07904077 C6.98750594,7.78214723 7.20348599,7.50497283 7.44585132,7.25179856 C7.35677722,7.2113638 7.27364289,7.15895303 7.198753,7.09601918 C7.74475372,6.60874162 8.06220635,5.9154095 8.07434053,5.18369305 C8.07434053,4.29321926 7.59927844,3.47038755 6.82810553,3.02515066 C6.05693261,2.57991376 5.1068084,2.57991376 4.33563548,3.02515066 C3.56446257,3.47038755 3.08940047,4.29321926 3.08940048,5.18369305 C3.0690725,5.91658356 3.38100313,6.61941459 3.9381295,7.09601918 C2.45694705,7.77021525 1.50876239,9.25030837 1.51545602,10.8776978 L1.51545602,10.8776978 Z M5.50129496,3.63125663 C5.90873661,3.62948611 6.2992156,3.79426079 6.58220695,4.08739519 C6.86519829,4.3805296 7.01612586,4.77656673 7,5.18369305 C7.03332384,5.73956249 6.75569599,6.26807752 6.27908764,6.55608065 C5.80247929,6.84408378 5.20548234,6.84408378 4.72887399,6.55608065 C4.25226564,6.26807752 3.97463779,5.73956249 4.00796163,5.18369305 C3.99340666,4.7779193 4.14411589,4.38360482 4.42560278,4.09097996 C4.70708967,3.7983551 5.09526202,3.63246535 5.50129496,3.63125663 L5.50129496,3.63125663 Z" id="形状"></path>
12 <path d="M12.978705,0 L1.01592326,0 C0.74521743,0.00563905362 0.487846369,0.118615445 0.30045916,0.314062318 C0.113071952,0.509509191 0.0110275373,0.771407006 0.0167865707,1.04211031 L0.0167865707,11.3933813 C0.0077943878,11.9550253 0.454330229,12.4183663 1.01592326,12.4301199 L6.24796163,12.4301199 C6.15347803,12.0905554 6.08700419,11.7438135 6.04920863,11.3933813 L1.51549161,11.3933813 C1.23359784,11.3736011 1.01523013,11.1387971 1.01592326,10.856211 L1.01592326,1.55779376 C1.01523013,1.27520772 1.23359784,1.04040373 1.51549161,1.0206235 L12.4791367,1.0206235 C12.7610305,1.04040373 12.9793982,1.27520772 12.978705,1.55779376 L12.978705,6.1129976 C13.3416127,6.27160518 13.6798936,6.48144788 13.9832134,6.73611511 L13.9832134,1.04211031 C13.9889659,0.770492956 13.8861881,0.507791018 13.6976439,0.312188988 C13.5090997,0.116586957 13.2503504,0.00422874936 12.978705,0 Z" id="路径"></path>
13 <path d="M9.48709832,3.63127098 L11.9795683,3.63127098 C12.1204387,3.63685572 12.2567289,3.58067135 12.3527387,3.47743498 C12.4487485,3.37419862 12.4949119,3.23419632 12.4791367,3.09410072 C12.4968375,2.95359324 12.4513335,2.81246879 12.3548898,2.70876591 C12.2584461,2.60506303 12.120989,2.54945504 11.9795683,2.55693046 L9.48709832,2.55693046 C9.34659209,2.55109685 9.21064377,2.60742026 9.11543115,2.71091224 C9.02021852,2.81440422 8.97539973,2.9545668 8.99290168,3.09410072 C8.97728866,3.23323418 9.02275873,3.37230344 9.1175512,3.47533874 C9.21234368,3.57837404 9.3471483,3.63525552 9.48709832,3.63127098 L9.48709832,3.63127098 Z M9.48709832,5.6993765 L10.9858034,5.6993765 C11.1266737,5.70496124 11.2629639,5.64877687 11.3589737,5.5455405 C11.4549835,5.44230413 11.5011469,5.30230183 11.4853717,5.16220624 C11.5011469,5.02211064 11.4549835,4.88210834 11.3589737,4.77887197 C11.2629639,4.6756356 11.1266737,4.61945123 10.9858034,4.62503597 L9.48709832,4.62503597 C9.3471483,4.62105144 9.21234368,4.67793291 9.1175512,4.78096821 C9.02275873,4.88400351 8.97728866,5.02307277 8.99290168,5.16220624 C8.97539973,5.30174015 9.02021852,5.44190273 9.11543115,5.54539471 C9.21064377,5.64888669 9.34659209,5.70521011 9.48709832,5.6993765 L9.48709832,5.6993765 Z" id="形状"></path>
14 </g>
15 <rect id="账号管理-灰" x="0" y="0" width="14" height="14"></rect>
16 </g>
17 </g>
18 </g>
19 </svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8"?>
2 <svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3 <!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
4 <title>账号管理-灰</title>
5 <desc>Created with Sketch.</desc>
6 <g id="奇瑞后台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7 <g id="图标" transform="translate(-57.000000, -131.000000)">
8 <g id="编组-4" transform="translate(57.000000, 131.000000)">
9 <g id="账号管理" fill="#A6ADB4" fill-rule="nonzero">
10 <path d="M10.2230216,8.05755396 C9.4851496,8.02906906 8.80393552,8.45160855 8.50160716,9.12530285 C8.19927879,9.79899715 8.33644267,10.5887935 8.84821755,11.1211026 C9.35999242,11.6534116 10.1437849,11.8215235 10.8288455,11.545918 C11.5139061,11.2703125 11.9629036,10.6062391 11.9634532,9.86781775 C11.9494922,9.39289432 11.7753247,8.93665107 11.4692566,8.57323741 C11.129455,8.25694548 10.6869616,8.07384474 10.2230216,8.05755396 L10.2230216,8.05755396 Z M10.2230216,10.6467146 C9.81930162,10.6131005 9.50875278,10.2756205 9.50875278,9.8705036 C9.50875278,9.46538668 9.81930162,9.12790668 10.2230216,9.09429257 C10.4178006,9.11007026 10.6040891,9.18085988 10.7601918,9.29841727 C10.9065942,9.44997563 10.9792327,9.65807506 10.9589448,9.86781775 C10.9431396,10.2702783 10.6250454,10.595338 10.2230216,10.6198561 L10.2230216,10.6467146 Z" id="形状"></path>
11 <path d="M13.7790887,8.96 C13.3974741,8.86313379 13.0711026,8.61635671 12.873916,8.27557784 C12.6767294,7.93479897 12.625418,7.52886251 12.7316067,7.14973621 C12.7397811,7.07569471 12.7206831,7.00121265 12.6778897,6.94023981 C12.331848,6.62256644 11.9266321,6.37615136 11.4853717,6.21505995 C11.4130369,6.20722007 11.340353,6.22634744 11.281247,6.26877698 C11.0209363,6.57522731 10.6357013,6.7471014 10.233765,6.73611511 C9.83422948,6.73546094 9.45365256,6.56566509 9.18628297,6.26877698 C9.12953599,6.225711 9.05824525,6.20644323 8.98752998,6.21505995 C8.54460609,6.37602801 8.13760745,6.62241732 7.78964029,6.94023981 C7.72248855,6.98754531 7.70166323,7.07778837 7.74129496,7.14973621 C7.84086816,7.53447 7.78693155,7.94284719 7.59088729,8.28853717 C7.40923551,8.63687962 7.07923085,8.88388909 6.69381295,8.96 C6.64546763,8.96 6.5971223,9.01371703 6.54340528,9.11577938 C6.44660599,9.59438721 6.44660599,10.0875313 6.54340528,10.5661391 C6.54340528,10.6198561 6.5971223,10.6682014 6.69381295,10.7219185 C7.07608824,10.8050007 7.40343248,11.0500189 7.59088729,11.3933813 C7.78725971,11.7409174 7.84117696,12.1510736 7.74129496,12.537554 C7.73460668,12.6090549 7.75159257,12.6807731 7.78964029,12.7416787 C8.13760745,13.0595011 8.54460609,13.3058905 8.98752998,13.4668585 L9.041247,13.4668585 C9.0944142,13.4734903 9.14772828,13.4557189 9.18628297,13.4185132 C9.44559503,13.1168804 9.82528379,12.9457254 10.2230216,12.9511751 C10.634041,12.9446659 11.0270554,13.1195573 11.2973621,13.4292566 C11.3510791,13.4776019 11.3994245,13.4776019 11.5014868,13.4776019 C11.9427472,13.3165105 12.3479631,13.0700954 12.6940048,12.7524221 C12.7477218,12.698705 12.7960671,12.6503597 12.7477218,12.5482974 C12.6182907,12.1794361 12.6506553,11.7730677 12.8368394,11.4293432 C13.0230235,11.0856187 13.3457101,10.8365079 13.7253717,10.7434053 C13.7790887,10.7434053 13.8274341,10.6896882 13.8757794,10.5876259 C13.9779384,10.1095695 13.9779384,9.61532259 13.8757794,9.13726619 C13.8757794,9.06743405 13.8274341,9.01371703 13.7790887,8.96 Z M12.9088729,10.2545803 C12.5570203,10.3738745 12.2571941,10.6110788 12.0601439,10.9260432 C11.8674513,11.2354631 11.812917,11.6113602 11.9097362,11.9627818 C11.6995825,12.1612408 11.4427762,12.3035004 11.1630695,12.3764029 C10.9001251,12.1084012 10.539367,11.9590551 10.1639329,11.9627818 C9.79228538,11.9773991 9.4380279,12.124054 9.16479616,12.3764029 C8.90552032,12.2581748 8.65587259,12.1198807 8.4181295,11.9627818 C8.52125061,11.6117806 8.46633703,11.2332691 8.26772182,10.9260432 C8.07378679,10.6083049 7.77282806,10.3702047 7.41899281,10.2545803 C7.37050545,9.96292879 7.37050545,9.66527265 7.41899281,9.3736211 C7.78078559,9.26252636 8.0899869,9.0239451 8.28920863,8.70215827 C8.48447126,8.39368341 8.53916815,8.01666554 8.43961631,7.66541966 C8.65057904,7.46806986 8.90708761,7.32597519 9.18628297,7.25179856 C9.44922742,7.51980025 9.80998552,7.66914635 10.1854197,7.66541966 C10.5570671,7.65080237 10.9113246,7.50414739 11.1845564,7.25179856 C11.4444148,7.36886747 11.6941537,7.50721202 11.931223,7.66541966 C11.8309713,8.01661891 11.8857103,8.393927 12.0816307,8.70215827 C12.2702379,9.01594747 12.5630021,9.25358071 12.9088729,9.3736211 C12.9573603,9.66527265 12.9573603,9.96292879 12.9088729,10.2545803 L12.9088729,10.2545803 Z M1.51545602,10.8776978 L2.50925659,10.8776978 C2.485191,9.19597558 3.81990192,7.80854717 5.50129496,7.76748201 C5.95305398,7.76791383 6.39837238,7.87464303 6.801247,8.07904077 C6.98750594,7.78214723 7.20348599,7.50497283 7.44585132,7.25179856 C7.35677722,7.2113638 7.27364289,7.15895303 7.198753,7.09601918 C7.74475372,6.60874162 8.06220635,5.9154095 8.07434053,5.18369305 C8.07434053,4.29321926 7.59927844,3.47038755 6.82810553,3.02515066 C6.05693261,2.57991376 5.1068084,2.57991376 4.33563548,3.02515066 C3.56446257,3.47038755 3.08940047,4.29321926 3.08940048,5.18369305 C3.0690725,5.91658356 3.38100313,6.61941459 3.9381295,7.09601918 C2.45694705,7.77021525 1.50876239,9.25030837 1.51545602,10.8776978 L1.51545602,10.8776978 Z M5.50129496,3.63125663 C5.90873661,3.62948611 6.2992156,3.79426079 6.58220695,4.08739519 C6.86519829,4.3805296 7.01612586,4.77656673 7,5.18369305 C7.03332384,5.73956249 6.75569599,6.26807752 6.27908764,6.55608065 C5.80247929,6.84408378 5.20548234,6.84408378 4.72887399,6.55608065 C4.25226564,6.26807752 3.97463779,5.73956249 4.00796163,5.18369305 C3.99340666,4.7779193 4.14411589,4.38360482 4.42560278,4.09097996 C4.70708967,3.7983551 5.09526202,3.63246535 5.50129496,3.63125663 L5.50129496,3.63125663 Z" id="形状"></path>
12 <path d="M12.978705,0 L1.01592326,0 C0.74521743,0.00563905362 0.487846369,0.118615445 0.30045916,0.314062318 C0.113071952,0.509509191 0.0110275373,0.771407006 0.0167865707,1.04211031 L0.0167865707,11.3933813 C0.0077943878,11.9550253 0.454330229,12.4183663 1.01592326,12.4301199 L6.24796163,12.4301199 C6.15347803,12.0905554 6.08700419,11.7438135 6.04920863,11.3933813 L1.51549161,11.3933813 C1.23359784,11.3736011 1.01523013,11.1387971 1.01592326,10.856211 L1.01592326,1.55779376 C1.01523013,1.27520772 1.23359784,1.04040373 1.51549161,1.0206235 L12.4791367,1.0206235 C12.7610305,1.04040373 12.9793982,1.27520772 12.978705,1.55779376 L12.978705,6.1129976 C13.3416127,6.27160518 13.6798936,6.48144788 13.9832134,6.73611511 L13.9832134,1.04211031 C13.9889659,0.770492956 13.8861881,0.507791018 13.6976439,0.312188988 C13.5090997,0.116586957 13.2503504,0.00422874936 12.978705,0 Z" id="路径"></path>
13 <path d="M9.48709832,3.63127098 L11.9795683,3.63127098 C12.1204387,3.63685572 12.2567289,3.58067135 12.3527387,3.47743498 C12.4487485,3.37419862 12.4949119,3.23419632 12.4791367,3.09410072 C12.4968375,2.95359324 12.4513335,2.81246879 12.3548898,2.70876591 C12.2584461,2.60506303 12.120989,2.54945504 11.9795683,2.55693046 L9.48709832,2.55693046 C9.34659209,2.55109685 9.21064377,2.60742026 9.11543115,2.71091224 C9.02021852,2.81440422 8.97539973,2.9545668 8.99290168,3.09410072 C8.97728866,3.23323418 9.02275873,3.37230344 9.1175512,3.47533874 C9.21234368,3.57837404 9.3471483,3.63525552 9.48709832,3.63127098 L9.48709832,3.63127098 Z M9.48709832,5.6993765 L10.9858034,5.6993765 C11.1266737,5.70496124 11.2629639,5.64877687 11.3589737,5.5455405 C11.4549835,5.44230413 11.5011469,5.30230183 11.4853717,5.16220624 C11.5011469,5.02211064 11.4549835,4.88210834 11.3589737,4.77887197 C11.2629639,4.6756356 11.1266737,4.61945123 10.9858034,4.62503597 L9.48709832,4.62503597 C9.3471483,4.62105144 9.21234368,4.67793291 9.1175512,4.78096821 C9.02275873,4.88400351 8.97728866,5.02307277 8.99290168,5.16220624 C8.97539973,5.30174015 9.02021852,5.44190273 9.11543115,5.54539471 C9.21064377,5.64888669 9.34659209,5.70521011 9.48709832,5.6993765 L9.48709832,5.6993765 Z" id="形状"></path>
14 </g>
15 <rect id="账号管理-灰" x="0" y="0" width="14" height="14"></rect>
16 </g>
17 </g>
18 </g>
19 </svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8"?>
2 <svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3 <!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
4 <title>首页-白</title>
5 <desc>Created with Sketch.</desc>
6 <g id="奇瑞后台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7 <g id="图标" transform="translate(-23.000000, -263.000000)">
8 <g id="编组" transform="translate(23.000000, 263.000000)">
9 <path d="M13.8237634,5.9772172 L7.90871505,1.30222645 C7.39952808,0.899009055 6.60060637,0.899506723 6.09185284,1.30222645 L0.177318171,5.9772172 C-0.0247159515,6.1373194 -0.0592632085,6.43084278 0.100325266,6.6328769 C0.259913757,6.83497523 0.54696755,6.86952251 0.749081932,6.70995006 L0.933376855,6.55869338 L0.933376855,12.2114426 C0.933376855,13.0127402 1.77769805,13.6115061 2.52014332,13.6115061 L11.8542158,13.6115061 C12.5879118,13.6115061 13.0676887,13.0487002 13.0676887,12.2114426 L13.0676887,6.58062254 L13.238017,6.70995006 C13.3239196,6.77759978 13.4293755,6.81028485 13.5306414,6.81028485 C13.6683007,6.81028485 13.8064577,6.74961843 13.8983804,6.6328769 C14.0584826,6.43084278 14.0262952,6.1373194 13.8237634,5.9772172 L13.8237634,5.9772172 Z M6.53379144,12.6781036 L6.53379144,10.0907185 C6.53379144,9.96193677 6.76716211,9.89754593 7.00053278,9.89754593 C7.23390345,9.89754593 7.46725807,9.96193677 7.46725807,10.0907185 L7.46725807,12.6781036 L6.53379144,12.6781036 L6.53379144,12.6781036 Z M12.1342863,12.2114265 C12.1342863,12.5208429 12.0488331,12.6781036 11.8542158,12.6781036 L8.40997157,12.6781036 C8.40997157,12.6711043 8.40064444,12.6655176 8.40064444,12.6585344 L8.40064444,10.0907185 C8.40064444,9.54794743 7.96289584,8.96361372 7.00053278,8.96361372 C6.03821788,8.96361372 5.60040506,9.54794743 5.60040506,10.0907185 L5.60040506,12.6585504 C5.60040506,12.6655337 5.61302317,12.6711203 5.61302317,12.6781036 L2.52014335,12.6781036 C2.22755107,12.6781036 1.86676326,12.4251637 1.86676326,12.2114426 L1.86676326,5.82083943 L6.66405007,2.03452587 C6.8362406,1.89821505 7.14706974,1.89821505 7.31977399,2.03452587 L12.1342863,5.84276861 L12.1342863,12.2114265 L12.1342863,12.2114265 Z" id="形状" fill="#FFFFFF" fill-rule="nonzero"></path>
10 <rect id="首页-白" x="0" y="0" width="14" height="14"></rect>
11 </g>
12 </g>
13 </g>
14 </svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8"?>
2 <svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3 <!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
4 <title>首页-灰</title>
5 <desc>Created with Sketch.</desc>
6 <g id="奇瑞后台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7 <g id="图标" transform="translate(-57.000000, -263.000000)">
8 <g id="编组" transform="translate(57.000000, 263.000000)">
9 <path d="M13.8237634,5.9772172 L7.90871505,1.30222645 C7.39952808,0.899009055 6.60060637,0.899506723 6.09185284,1.30222645 L0.177318171,5.9772172 C-0.0247159515,6.1373194 -0.0592632085,6.43084278 0.100325266,6.6328769 C0.259913757,6.83497523 0.54696755,6.86952251 0.749081932,6.70995006 L0.933376855,6.55869338 L0.933376855,12.2114426 C0.933376855,13.0127402 1.77769805,13.6115061 2.52014332,13.6115061 L11.8542158,13.6115061 C12.5879118,13.6115061 13.0676887,13.0487002 13.0676887,12.2114426 L13.0676887,6.58062254 L13.238017,6.70995006 C13.3239196,6.77759978 13.4293755,6.81028485 13.5306414,6.81028485 C13.6683007,6.81028485 13.8064577,6.74961843 13.8983804,6.6328769 C14.0584826,6.43084278 14.0262952,6.1373194 13.8237634,5.9772172 L13.8237634,5.9772172 Z M6.53379144,12.6781036 L6.53379144,10.0907185 C6.53379144,9.96193677 6.76716211,9.89754593 7.00053278,9.89754593 C7.23390345,9.89754593 7.46725807,9.96193677 7.46725807,10.0907185 L7.46725807,12.6781036 L6.53379144,12.6781036 L6.53379144,12.6781036 Z M12.1342863,12.2114265 C12.1342863,12.5208429 12.0488331,12.6781036 11.8542158,12.6781036 L8.40997157,12.6781036 C8.40997157,12.6711043 8.40064444,12.6655176 8.40064444,12.6585344 L8.40064444,10.0907185 C8.40064444,9.54794743 7.96289584,8.96361372 7.00053278,8.96361372 C6.03821788,8.96361372 5.60040506,9.54794743 5.60040506,10.0907185 L5.60040506,12.6585504 C5.60040506,12.6655337 5.61302317,12.6711203 5.61302317,12.6781036 L2.52014335,12.6781036 C2.22755107,12.6781036 1.86676326,12.4251637 1.86676326,12.2114426 L1.86676326,5.82083943 L6.66405007,2.03452587 C6.8362406,1.89821505 7.14706974,1.89821505 7.31977399,2.03452587 L12.1342863,5.84276861 L12.1342863,12.2114265 L12.1342863,12.2114265 Z" id="形状" fill="#A6ADB4" fill-rule="nonzero"></path>
10 <rect id="首页-灰" x="0" y="0" width="14" height="14"></rect>
11 </g>
12 </g>
13 </g>
14 </svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8"?>
2 <svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3 <!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
4 <title>角色权限-白</title>
5 <desc>Created with Sketch.</desc>
6 <g id="奇瑞后台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7 <g id="图标" transform="translate(-23.000000, -87.000000)" fill="#FFFFFF" fill-rule="nonzero">
8 <g id="角色权限-白" transform="translate(23.000000, 87.000000)">
9 <path d="M11.6451085,6.69136043 C10.6179505,6.69136043 9.78247041,7.52752414 9.78247043,8.55563911 C9.78247043,9.02540014 9.95828902,9.45387252 10.2458057,9.78213104 L9.2224759,10.8062812 L8.6996685,10.2863449 C8.5089477,10.0974014 8.20188039,10.0983584 8.01252677,10.2885323 C7.82344659,10.4791164 7.82467704,10.787004 8.01471424,10.9763577 L8.53533417,11.4941065 L8.02633523,12.0035156 L6.91058441,10.8868078 C6.72082064,10.6969073 6.41347988,10.6969073 6.22371612,10.8868078 C6.03395235,11.0767082 6.03395235,11.3843224 6.22371612,11.5742229 L7.33946694,12.6909308 L6.86068255,13.1701253 C6.67091879,13.3600258 6.67091879,13.66764 6.86068255,13.8575405 C6.95556444,13.9525591 7.07984056,14 7.20411669,14 C7.32839282,14 7.45266895,13.9525591 7.54755084,13.8575405 L11.0729461,10.3290007 C11.2534131,10.387379 11.4453643,10.4197811 11.6449718,10.4197811 C12.6721297,10.4197811 13.5076098,9.58361734 13.5076098,8.55550239 C13.5076098,7.52738744 12.6722664,6.69136043 11.6451085,6.69136043 L11.6451085,6.69136043 Z M11.6451085,9.4474468 C11.1536094,9.4474468 10.7539844,9.04741165 10.7539844,8.55550239 C10.7539844,8.06359313 11.1537461,7.66355797 11.6451085,7.66355797 C12.1366076,7.66355797 12.5362326,8.06359313 12.5362326,8.55550239 C12.5362326,9.04741165 12.1364709,9.4474468 11.6451085,9.4474468 Z" id="形状"></path>
10 <path d="M5.08841471,13.0200096 L0.992497666,13.0200096 C1.23722184,10.1929669 3.59395664,7.96789094 6.45558885,7.96789094 C6.51752184,7.96789094 6.57631033,7.95517622 6.63086058,7.93398502 C8.7374025,7.84060703 10.4238118,6.09062412 10.4238118,3.94703177 C10.4238118,1.77049052 8.64361436,0 6.45558885,0 C4.26770006,0 2.48763931,1.77049052 2.48763931,3.94689505 C2.48763931,5.38393181 3.24737798,6.64241561 4.38117552,7.346647 C1.8374113,8.22081816 6.5953125e-05,10.648646 6.5953125e-05,13.50604 C6.5953125e-05,13.7744163 0.217583365,13.9922071 0.485822928,13.9922071 L5.08841471,13.9922071 C5.35665427,13.9922071 5.57417168,13.7744163 5.57417168,13.50604 C5.57417168,13.2376637 5.35665427,13.0200096 5.08841471,13.0200096 Z M3.45915326,3.94689505 C3.45915326,2.30669623 4.80322217,0.972334248 6.45558885,0.972334248 C8.10795553,0.972334248 9.45229787,2.30669622 9.45229787,3.94689505 C9.45229787,5.61430064 8.10795553,6.9705374 6.45558885,6.9705374 C4.80322217,6.9705374 3.45915326,5.61430064 3.45915326,3.94689505 Z" id="形状"></path>
11 </g>
12 </g>
13 </g>
14 </svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8"?>
2 <svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3 <!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
4 <title>角色权限-灰</title>
5 <desc>Created with Sketch.</desc>
6 <g id="奇瑞后台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7 <g id="图标" transform="translate(-57.000000, -87.000000)" fill="#A6ADB4" fill-rule="nonzero">
8 <g id="角色权限-灰" transform="translate(57.000000, 87.000000)">
9 <path d="M11.6451085,6.69136043 C10.6179505,6.69136043 9.78247041,7.52752414 9.78247043,8.55563911 C9.78247043,9.02540014 9.95828902,9.45387252 10.2458057,9.78213104 L9.2224759,10.8062812 L8.6996685,10.2863449 C8.5089477,10.0974014 8.20188039,10.0983584 8.01252677,10.2885323 C7.82344659,10.4791164 7.82467704,10.787004 8.01471424,10.9763577 L8.53533417,11.4941065 L8.02633523,12.0035156 L6.91058441,10.8868078 C6.72082064,10.6969073 6.41347988,10.6969073 6.22371612,10.8868078 C6.03395235,11.0767082 6.03395235,11.3843224 6.22371612,11.5742229 L7.33946694,12.6909308 L6.86068255,13.1701253 C6.67091879,13.3600258 6.67091879,13.66764 6.86068255,13.8575405 C6.95556444,13.9525591 7.07984056,14 7.20411669,14 C7.32839282,14 7.45266895,13.9525591 7.54755084,13.8575405 L11.0729461,10.3290007 C11.2534131,10.387379 11.4453643,10.4197811 11.6449718,10.4197811 C12.6721297,10.4197811 13.5076098,9.58361734 13.5076098,8.55550239 C13.5076098,7.52738744 12.6722664,6.69136043 11.6451085,6.69136043 L11.6451085,6.69136043 Z M11.6451085,9.4474468 C11.1536094,9.4474468 10.7539844,9.04741165 10.7539844,8.55550239 C10.7539844,8.06359313 11.1537461,7.66355797 11.6451085,7.66355797 C12.1366076,7.66355797 12.5362326,8.06359313 12.5362326,8.55550239 C12.5362326,9.04741165 12.1364709,9.4474468 11.6451085,9.4474468 Z" id="形状"></path>
10 <path d="M5.08841471,13.0200096 L0.992497666,13.0200096 C1.23722184,10.1929669 3.59395664,7.96789094 6.45558885,7.96789094 C6.51752184,7.96789094 6.57631033,7.95517622 6.63086058,7.93398502 C8.7374025,7.84060703 10.4238118,6.09062412 10.4238118,3.94703177 C10.4238118,1.77049052 8.64361436,0 6.45558885,0 C4.26770006,0 2.48763931,1.77049052 2.48763931,3.94689505 C2.48763931,5.38393181 3.24737798,6.64241561 4.38117552,7.346647 C1.8374113,8.22081816 6.5953125e-05,10.648646 6.5953125e-05,13.50604 C6.5953125e-05,13.7744163 0.217583365,13.9922071 0.485822928,13.9922071 L5.08841471,13.9922071 C5.35665427,13.9922071 5.57417168,13.7744163 5.57417168,13.50604 C5.57417168,13.2376637 5.35665427,13.0200096 5.08841471,13.0200096 Z M3.45915326,3.94689505 C3.45915326,2.30669623 4.80322217,0.972334248 6.45558885,0.972334248 C8.10795553,0.972334248 9.45229787,2.30669622 9.45229787,3.94689505 C9.45229787,5.61430064 8.10795553,6.9705374 6.45558885,6.9705374 C4.80322217,6.9705374 3.45915326,5.61430064 3.45915326,3.94689505 Z" id="形状"></path>
11 </g>
12 </g>
13 </g>
14 </svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8"?>
2 <svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3 <!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
4 <title>合作商管理-白</title>
5 <desc>Created with Sketch.</desc>
6 <g id="奇瑞后台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7 <g id="图标" transform="translate(-23.000000, -175.000000)">
8 <g id="编组-5" transform="translate(23.000000, 175.000000)">
9 <g id="二级-管理员首页" fill="#FFFFFF" fill-rule="nonzero">
10 <path d="M8.75273438,7 C9.80273438,6.3 10.5902344,5.1625 10.5902344,3.7625 C10.5027344,1.6625 8.84023437,0 6.74023438,0 C4.64023437,0 2.97773437,1.6625 2.97773437,3.7625 C2.97773437,5.1625 3.67773438,6.3 4.81523438,7 C2.01523438,7.875 0.002734375,10.5 0.002734375,13.5625 C0.002734375,13.825 0.177734375,14 0.440234375,14 C0.702734375,14 0.877734375,13.825 0.877734375,13.5625 C0.877734375,10.4125 3.32773438,7.875 6.30273438,7.6125 C6.04023438,8.225 5.42773438,9.8875 5.42773438,11.2 C5.42773438,13.0375 6.56523438,13.5625 6.65273437,13.5625 L7.00273438,13.5625 C7.09023437,13.5625 8.22773438,13.0375 8.22773438,11.2 C8.22773438,9.8875 7.61523438,8.225 7.35273438,7.6125 C10.4152344,7.875 12.7777344,10.4125 12.7777344,13.5625 C12.7777344,13.825 12.9527344,14 13.2152344,14 C13.4777344,14 13.6527344,13.825 13.6527344,13.5625 C13.5652344,10.5 11.5527344,7.875 8.75273438,7 Z M3.85273438,3.7625 C3.85273438,2.1875 5.16523438,0.875 6.74023438,0.875 C8.31523438,0.875 9.62773438,2.1875 9.62773438,3.7625 C9.62773438,5.3375 8.31523438,6.7375 6.74023438,6.7375 C5.16523438,6.7375 3.85273438,5.425 3.85273438,3.7625 Z M6.74023438,12.6875 C6.56523438,12.5125 6.21523438,12.075 6.21523438,11.2875 C6.21523438,10.5 6.47773438,9.5375 6.74023438,8.8375 C7.00273438,9.5375 7.26523438,10.5 7.26523438,11.2875 C7.26523438,12.075 6.91523437,12.5125 6.74023438,12.6875 L6.74023438,12.6875 Z" id="形状"></path>
11 </g>
12 <rect id="合作商管理-灰" x="0" y="0" width="14" height="14"></rect>
13 </g>
14 </g>
15 </g>
16 </svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8"?>
2 <svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3 <!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
4 <title>合作商管理-灰</title>
5 <desc>Created with Sketch.</desc>
6 <g id="奇瑞后台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7 <g id="图标" transform="translate(-57.000000, -175.000000)">
8 <g id="编组-5" transform="translate(57.000000, 175.000000)">
9 <g id="二级-管理员首页" fill="#A6ADB4" fill-rule="nonzero">
10 <path d="M8.75273438,7 C9.80273438,6.3 10.5902344,5.1625 10.5902344,3.7625 C10.5027344,1.6625 8.84023437,0 6.74023438,0 C4.64023437,0 2.97773437,1.6625 2.97773437,3.7625 C2.97773437,5.1625 3.67773438,6.3 4.81523438,7 C2.01523438,7.875 0.002734375,10.5 0.002734375,13.5625 C0.002734375,13.825 0.177734375,14 0.440234375,14 C0.702734375,14 0.877734375,13.825 0.877734375,13.5625 C0.877734375,10.4125 3.32773438,7.875 6.30273438,7.6125 C6.04023438,8.225 5.42773438,9.8875 5.42773438,11.2 C5.42773438,13.0375 6.56523438,13.5625 6.65273437,13.5625 L7.00273438,13.5625 C7.09023437,13.5625 8.22773438,13.0375 8.22773438,11.2 C8.22773438,9.8875 7.61523438,8.225 7.35273438,7.6125 C10.4152344,7.875 12.7777344,10.4125 12.7777344,13.5625 C12.7777344,13.825 12.9527344,14 13.2152344,14 C13.4777344,14 13.6527344,13.825 13.6527344,13.5625 C13.5652344,10.5 11.5527344,7.875 8.75273438,7 Z M3.85273438,3.7625 C3.85273438,2.1875 5.16523438,0.875 6.74023438,0.875 C8.31523438,0.875 9.62773438,2.1875 9.62773438,3.7625 C9.62773438,5.3375 8.31523438,6.7375 6.74023438,6.7375 C5.16523438,6.7375 3.85273438,5.425 3.85273438,3.7625 Z M6.74023438,12.6875 C6.56523438,12.5125 6.21523438,12.075 6.21523438,11.2875 C6.21523438,10.5 6.47773438,9.5375 6.74023438,8.8375 C7.00273438,9.5375 7.26523438,10.5 7.26523438,11.2875 C7.26523438,12.075 6.91523437,12.5125 6.74023438,12.6875 L6.74023438,12.6875 Z" id="形状"></path>
11 </g>
12 <rect id="合作商管理-灰" x="0" y="0" width="14" height="14"></rect>
13 </g>
14 </g>
15 </g>
16 </svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8"?>
2 <svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3 <!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
4 <title>报表管理-白</title>
5 <desc>Created with Sketch.</desc>
6 <g id="奇瑞后台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7 <g id="图标" transform="translate(-23.000000, -219.000000)">
8 <g id="编组-6" transform="translate(23.000000, 219.000000)">
9 <g id="Group-5-Copy" transform="translate(0.000000, 1.000000)" fill="#FFFFFF" fill-rule="nonzero">
10 <g id="列表" transform="translate(0.000000, 1.000000)">
11 <path d="M13.015625,0 L0.984375,0 C0.440234375,0 0,0.461197917 0,1.03125 L0,4.23958333 L0,5.15625 L0,7.10416667 L0,8.02083333 L0,9.96875 C0,10.5388021 0.440234375,11 0.984375,11 L4.375,11 L5.25,11 L8.75,11 L9.625,11 L13.015625,11 C13.5597656,11 14,10.5388021 14,9.96875 L14,8.02083333 L14,7.10416667 L14,5.15625 L14,4.23958333 L14,1.03125 C14,0.461197917 13.5597656,0 13.015625,0 Z M5.25,4.23958333 L5.25,2.29166667 L8.75,2.29166667 L8.75,4.23958333 L5.25,4.23958333 Z M8.75,5.15625 L8.75,7.10416667 L5.25,7.10416667 L5.25,5.15625 L8.75,5.15625 Z M0.984375,2.29166667 L4.375,2.29166667 L4.375,4.23958333 L0.984375,4.23958333 L0.984375,2.29166667 Z M0.984375,5.15625 L4.375,5.15625 L4.375,7.10416667 L0.984375,7.10416667 L0.984375,5.15625 Z M0.984375,9.96875 L0.984375,8.02083333 L4.375,8.02083333 L4.375,9.96875 L0.984375,9.96875 Z M5.25,9.96875 L5.25,8.02083333 L8.75,8.02083333 L8.75,9.96875 L5.25,9.96875 Z M13.015625,9.96875 L9.625,9.96875 L9.625,8.02083333 L13.015625,8.02083333 L13.015625,9.96875 Z M13.015625,7.10416667 L9.625,7.10416667 L9.625,5.15625 L13.015625,5.15625 L13.015625,7.10416667 Z M9.625,4.23958333 L9.625,2.29166667 L13.015625,2.29166667 L13.015625,4.23958333 L9.625,4.23958333 Z" id="Shape"></path>
12 </g>
13 </g>
14 <rect id="报表管理-灰" x="0" y="0" width="14" height="14"></rect>
15 </g>
16 </g>
17 </g>
18 </svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8"?>
2 <svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3 <!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
4 <title>报表管理-灰</title>
5 <desc>Created with Sketch.</desc>
6 <g id="奇瑞后台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7 <g id="图标" transform="translate(-57.000000, -219.000000)">
8 <g id="编组-6" transform="translate(57.000000, 219.000000)">
9 <g id="Group-5-Copy" opacity="0.65" transform="translate(0.000000, 1.000000)" fill="#FFFFFF" fill-rule="nonzero">
10 <g id="列表" transform="translate(0.000000, 1.000000)">
11 <path d="M13.015625,0 L0.984375,0 C0.440234375,0 0,0.461197917 0,1.03125 L0,4.23958333 L0,5.15625 L0,7.10416667 L0,8.02083333 L0,9.96875 C0,10.5388021 0.440234375,11 0.984375,11 L4.375,11 L5.25,11 L8.75,11 L9.625,11 L13.015625,11 C13.5597656,11 14,10.5388021 14,9.96875 L14,8.02083333 L14,7.10416667 L14,5.15625 L14,4.23958333 L14,1.03125 C14,0.461197917 13.5597656,0 13.015625,0 Z M5.25,4.23958333 L5.25,2.29166667 L8.75,2.29166667 L8.75,4.23958333 L5.25,4.23958333 Z M8.75,5.15625 L8.75,7.10416667 L5.25,7.10416667 L5.25,5.15625 L8.75,5.15625 Z M0.984375,2.29166667 L4.375,2.29166667 L4.375,4.23958333 L0.984375,4.23958333 L0.984375,2.29166667 Z M0.984375,5.15625 L4.375,5.15625 L4.375,7.10416667 L0.984375,7.10416667 L0.984375,5.15625 Z M0.984375,9.96875 L0.984375,8.02083333 L4.375,8.02083333 L4.375,9.96875 L0.984375,9.96875 Z M5.25,9.96875 L5.25,8.02083333 L8.75,8.02083333 L8.75,9.96875 L5.25,9.96875 Z M13.015625,9.96875 L9.625,9.96875 L9.625,8.02083333 L13.015625,8.02083333 L13.015625,9.96875 Z M13.015625,7.10416667 L9.625,7.10416667 L9.625,5.15625 L13.015625,5.15625 L13.015625,7.10416667 Z M9.625,4.23958333 L9.625,2.29166667 L13.015625,2.29166667 L13.015625,4.23958333 L9.625,4.23958333 Z" id="Shape"></path>
12 </g>
13 </g>
14 <rect id="报表管理-灰" x="0" y="0" width="14" height="14"></rect>
15 </g>
16 </g>
17 </g>
18 </svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8"?>
2 <svg width="48px" height="20px" viewBox="0 0 48 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3 <!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
4 <title>近7天</title>
5 <desc>Created with Sketch.</desc>
6 <g id="奇瑞后台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7 <g id="标准列表" transform="translate(-1324.000000, -172.000000)" fill="#1890FF">
8 <g id="编组-7" transform="translate(280.000000, 142.000000)">
9 <g id="近7天" transform="translate(1044.000000, 30.000000)">
10 <rect id="矩形" stroke="#1890FF" stroke-width="0.5" fill-opacity="0.04" x="0.25" y="0.25" width="47.5" height="19.5" rx="2"></rect>
11 <text font-family="PingFangSC-Regular, PingFang SC" font-size="13" font-weight="normal" line-spacing="14" letter-spacing="1">
12 <tspan x="5.0085" y="16.624">近7天</tspan>
13 </text>
14 </g>
15 </g>
16 </g>
17 </g>
18 </svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8"?>
2 <svg width="18px" height="16px" viewBox="0 0 18 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3 <!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
4 <title>Group</title>
5 <desc>Created with Sketch.</desc>
6 <g id="奇瑞后台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7 <g id="标准列表" transform="translate(-281.000000, -24.000000)">
8 <g id="Group" transform="translate(290.000000, 32.000000) scale(-1, 1) translate(-290.000000, -32.000000) translate(280.000000, 22.000000)">
9 <rect id="Rectangle-9" x="0" y="0" width="20" height="20"></rect>
10 <rect id="Combined-Shape" fill-opacity="0.65" fill="#000000" x="1.25" y="2.5" width="17.5" height="1.875" rx="0.9375"></rect>
11 <rect id="Rectangle-Copy" fill-opacity="0.65" fill="#000000" x="1.25" y="9.0625" width="11.25" height="1.875" rx="0.9375"></rect>
12 <path d="M13.0947111,7.8250177 L17.3692475,7.53744049 C17.5414472,7.52585544 17.6904342,7.65605936 17.7020193,7.82825908 C17.7029688,7.8423724 17.7029589,7.85653391 17.7019898,7.87064589 L17.4088387,12.1393768 C17.4029264,12.2254685 17.3283424,12.2904668 17.2422507,12.2845545 C17.2045995,12.2819688 17.1691565,12.2658432 17.1424704,12.2391571 L12.994714,8.09140072 C12.9336946,8.0303813 12.9336946,7.93144927 12.994714,7.87042985 C13.021453,7.84369083 13.0569817,7.82755601 13.0947111,7.8250177 Z" id="Rectangle-6" fill-opacity="0.65" fill="#000000"></path>
13 <rect id="Rectangle-Copy-2" fill-opacity="0.65" fill="#000000" x="1.25" y="15.625" width="17.5" height="1.875" rx="0.9375"></rect>
14 </g>
15 </g>
16 </g>
17 </svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8"?>
2 <svg width="28px" height="28px" viewBox="0 0 28 28" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3 <!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
4 <title>用户</title>
5 <desc>Created with Sketch.</desc>
6 <defs>
7 <rect id="path-1" x="0" y="0" width="20.5333333" height="20.5333333" rx="10.2666667"></rect>
8 <filter x="-73.1%" y="-73.1%" width="246.1%" height="246.1%" filterUnits="objectBoundingBox" id="filter-3">
9 <feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
10 <feGaussianBlur stdDeviation="5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
11 <feColorMatrix values="0 0 0 0 0.839215686 0 0 0 0 0.839215686 0 0 0 0 0.839215686 0 0 0 0.56173514 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
12 </filter>
13 <path d="M9.12592593,0 C14.1660356,-9.25853135e-16 18.2518519,4.08581621 18.2518519,9.12592593 C18.2518519,14.1660356 14.1660356,18.2518519 9.12592593,18.2518519 C4.08581621,18.2518519 6.17235423e-16,14.1660356 0,9.12592593 C-6.17235423e-16,4.08581621 4.08581621,9.25853135e-16 9.12592593,0 Z" id="path-4"></path>
14 <linearGradient x1="37.9394531%" y1="0%" x2="50%" y2="137.329102%" id="linearGradient-6">
15 <stop stop-color="#E4E8F0" offset="0%"></stop>
16 <stop stop-color="#D4DDE6" offset="100%"></stop>
17 </linearGradient>
18 <linearGradient x1="36.9648438%" y1="30.46875%" x2="56.9830204%" y2="68.7200429%" id="linearGradient-7">
19 <stop stop-color="#DFE5EC" offset="0%"></stop>
20 <stop stop-color="#D6DDED" offset="100%"></stop>
21 </linearGradient>
22 </defs>
23 <g id="奇瑞后台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
24 <g id="标准列表" transform="translate(-1305.000000, -18.000000)">
25 <g id="编组-5" transform="translate(1305.000000, 18.000000)">
26 <g id="编组-3" transform="translate(3.733333, 3.733333)">
27 <mask id="mask-2" fill="white">
28 <use xlink:href="#path-1"></use>
29 </mask>
30 <g id="Mask">
31 <use fill="black" fill-opacity="1" filter="url(#filter-3)" xlink:href="#path-1"></use>
32 <use fill="#FFFFFF" fill-rule="evenodd" xlink:href="#path-1"></use>
33 </g>
34 <g id="Group" mask="url(#mask-2)">
35 <g transform="translate(1.140741, 1.140741)">
36 <mask id="mask-5" fill="white">
37 <use xlink:href="#path-4"></use>
38 </mask>
39 <use id="Rectangle-16" stroke="none" fill="#F2F4F9" fill-rule="evenodd" xlink:href="#path-4"></use>
40 <g id="通用" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" mask="url(#mask-5)">
41 <g transform="translate(2.281481, 3.137037)" id="编组-2">
42 <g transform="translate(0.095062, 0.095062)">
43 <path d="M6.70185182,0 C8.07732435,0 9.34831338,0.73380583 10.0360497,1.92499998 C10.7237859,3.11619414 10.7237859,4.58380586 10.0360497,5.77500002 C9.34831338,6.96619417 8.07732435,7.7 6.70185182,7.7 C4.57555555,7.7 2.85185185,5.97629629 2.85185185,3.85 C2.85185185,1.72370371 4.57555555,0 6.70185182,0 Z" id="路径" fill="url(#linearGradient-6)" fill-rule="nonzero"></path>
44 <path d="M0.000589300402,15.2355823 C-0.0387694808,11.3476639 1.89836705,8.9336627 4.32663273,7.98518519 L6.81992595,12.0661566 L9.44669678,8.07919358 C11.7893999,9.08642633 13.6512414,11.4718892 13.6888889,15.2389398 C9.38166923,16.9143036 4.84171938,17.0351715 0.000589300402,15.2355823 L0.000589300402,15.2355823 Z" id="路径" fill="url(#linearGradient-7)" fill-rule="nonzero"></path>
45 </g>
46 </g>
47 </g>
48 </g>
49 </g>
50 </g>
51 <rect id="客户" x="0" y="0" width="28" height="28"></rect>
52 </g>
53 </g>
54 </g>
55 </svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8"?>
2 <svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3 <!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
4 <title>任务管理-白</title>
5 <desc>Created with Sketch.</desc>
6 <g id="奇瑞后台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7 <g id="图标" transform="translate(-23.000000, -42.000000)">
8 <g id="编组-3" transform="translate(23.000000, 42.000000)">
9 <g id="任务" transform="translate(1.000000, 0.000000)" fill="#FFFFFF" fill-rule="nonzero">
10 <path d="M8.17930744,8.04981368 C8.13130606,7.87535135 8.06135226,7.71009841 7.97349567,7.55611875 C8.07323534,7.4212771 8.41800092,6.91859168 8.16951953,6.67036046 L8.04226116,6.53597224 C7.83011697,6.32364042 7.28793596,6.65510009 7.15623707,6.74098659 C7.00053749,6.65253584 6.8329392,6.58248823 6.65624098,6.53481521 C6.6280343,6.36627878 6.50426268,5.77745669 6.15507221,5.77745669 L6.01525843,5.77745669 C5.71525765,5.77745669 5.54321884,6.38632365 5.50498973,6.53902119 C5.33038668,6.58761672 5.165337,6.65788323 5.01196713,6.74600562 C4.89077539,6.65591314 4.37142239,6.29695041 4.11804705,6.55032575 L3.98331485,6.66349642 C3.76257106,6.88449038 4.12947669,7.46710512 4.19683497,7.56908068 C4.11177716,7.72062118 4.04371527,7.88273137 3.99660513,8.05416039 C3.85025566,8.07723857 3.22503383,8.19797689 3.22503383,8.55789339 L3.22503383,8.69761336 C3.22503383,9.00938777 3.88097967,9.18258361 4.00076421,9.21149389 C4.04810889,9.38128116 4.11638967,9.54248448 4.20149439,9.69271159 C4.13108716,9.8031773 3.77815978,10.3832591 3.99705856,10.6023768 L4.1245671,10.7083081 C4.41266917,10.9961757 5.01454701,10.5231354 5.01454701,10.5231354 L4.98655924,10.4933026 C5.14792218,10.5889706 5.32111447,10.6631036 5.50172189,10.7138119 C5.5317892,10.8366454 5.70473487,11.4879005 6.01525843,11.4879005 L6.15507221,11.4879005 C6.56253666,11.4879005 6.66346464,10.7273367 6.66346464,10.7273367 L6.62617366,10.7266174 C6.81079915,10.6796324 6.98609017,10.6083183 7.14809091,10.5174128 C7.27559945,10.6019077 7.80869616,10.9358221 8.02126251,10.7229118 L8.16298384,10.5812843 C8.4471301,10.2972475 7.98489404,9.71600867 7.97207283,9.6998258 C8.05996069,9.54609631 8.13010212,9.38117171 8.17857256,9.20681883 C8.33758689,9.1663851 8.93544637,8.99492481 8.93544637,8.69761336 L8.93544637,8.55789339 C8.93544637,8.16323452 8.2238377,8.05645882 8.17930744,8.04981368 Z M6.0811626,9.78898015 C5.4427443,9.78898015 4.92547084,9.27186304 4.92547084,8.63349165 C4.92547084,7.99512026 5.4427443,7.4778937 6.08117824,7.4778937 C6.71917438,7.4778937 7.23641656,7.99515153 7.23641656,8.63350729 C7.23641656,9.27186304 6.71919001,9.78898015 6.08117824,9.78898015 L6.0811626,9.78898015 Z M10.6902641,1.99694963 L10.6902641,1.24392218 C10.6902641,0.502449457 10.2222116,0.0595703125 9.43852268,0.0595703125 C8.65533411,0.0595703125 8.18725033,0.502465093 8.18725033,1.24392218 L8.18725033,1.99693399 L7.33923645,1.99693399 L7.33923645,1.24392218 C7.33923645,0.502449457 6.87163738,0.0595703125 6.08794846,0.0595703125 C5.30429082,0.0595703125 4.83667612,0.502465093 4.83667612,1.24392218 L4.83667612,1.99693399 L3.98819316,1.99693399 L3.98819316,1.24392218 C3.98819316,0.502449457 3.52060973,0.0595703125 2.73692081,0.0595703125 C1.95373224,0.0595703125 1.4856641,0.502465093 1.4856641,1.24392218 L1.4856641,1.99693399 L0.048828125,1.99693399 L0.048828125,14.0595703 L12.1117146,14.0595703 L12.1117146,1.99694963 L10.6902485,1.99694963 L10.6902641,1.99694963 Z M8.85762786,1.24392218 C8.85762786,0.878079768 9.02546068,0.7297133 9.43852268,0.7297133 C9.85249155,0.7297133 10.0198709,0.878064133 10.0198709,1.24392218 L10.0198709,3.25826005 C10.0198709,3.62397737 9.85249155,3.77248456 9.43853832,3.77248456 C9.02547632,3.77248456 8.85762786,3.62400864 8.85762786,3.25826005 L8.85762786,1.24392218 L8.85762786,1.24392218 Z M5.50706927,1.24392218 C5.50706927,0.878079768 5.67443303,0.7297133 6.08793283,0.7297133 C6.50147954,0.7297133 6.66931236,0.878064133 6.66931236,1.24392218 L6.66931236,3.25826005 C6.66931236,3.62397737 6.50147954,3.77248456 6.08794846,3.77248456 C5.67443303,3.77248456 5.50706927,3.62400864 5.50706927,3.25826005 L5.50706927,1.24392218 L5.50706927,1.24392218 Z M2.15557255,1.24392218 C2.15557255,0.878079768 2.32340538,0.7297133 2.73690518,0.7297133 C3.15045188,0.7297133 3.31873814,0.878064133 3.31873814,1.24392218 L3.31873814,3.25826005 C3.31873814,3.62397737 3.15043625,3.77248456 2.73690518,3.77248456 C2.32340538,3.77248456 2.15557255,3.62400864 2.15557255,3.25826005 L2.15557255,1.24392218 Z M11.106594,13.054606 L1.05394879,13.054606 L1.05394879,4.67758412 L11.106594,4.67758412 L11.106594,13.054606 L11.106594,13.054606 Z" id="形状"></path>
11 </g>
12 <rect id="矩形" x="0" y="0" width="14" height="14"></rect>
13 </g>
14 </g>
15 </g>
16 </svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8"?>
2 <svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3 <!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
4 <title>任务管理-灰</title>
5 <desc>Created with Sketch.</desc>
6 <g id="奇瑞后台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7 <g id="图标" transform="translate(-57.000000, -42.000000)">
8 <g id="编组-3" transform="translate(57.000000, 42.000000)">
9 <g id="任务" transform="translate(1.000000, 0.000000)" fill="#A6ADB4" fill-rule="nonzero">
10 <path d="M8.17930744,8.04981368 C8.13130606,7.87535135 8.06135226,7.71009841 7.97349567,7.55611875 C8.07323534,7.4212771 8.41800092,6.91859168 8.16951953,6.67036046 L8.04226116,6.53597224 C7.83011697,6.32364042 7.28793596,6.65510009 7.15623707,6.74098659 C7.00053749,6.65253584 6.8329392,6.58248823 6.65624098,6.53481521 C6.6280343,6.36627878 6.50426268,5.77745669 6.15507221,5.77745669 L6.01525843,5.77745669 C5.71525765,5.77745669 5.54321884,6.38632365 5.50498973,6.53902119 C5.33038668,6.58761672 5.165337,6.65788323 5.01196713,6.74600562 C4.89077539,6.65591314 4.37142239,6.29695041 4.11804705,6.55032575 L3.98331485,6.66349642 C3.76257106,6.88449038 4.12947669,7.46710512 4.19683497,7.56908068 C4.11177716,7.72062118 4.04371527,7.88273137 3.99660513,8.05416039 C3.85025566,8.07723857 3.22503383,8.19797689 3.22503383,8.55789339 L3.22503383,8.69761336 C3.22503383,9.00938777 3.88097967,9.18258361 4.00076421,9.21149389 C4.04810889,9.38128116 4.11638967,9.54248448 4.20149439,9.69271159 C4.13108716,9.8031773 3.77815978,10.3832591 3.99705856,10.6023768 L4.1245671,10.7083081 C4.41266917,10.9961757 5.01454701,10.5231354 5.01454701,10.5231354 L4.98655924,10.4933026 C5.14792218,10.5889706 5.32111447,10.6631036 5.50172189,10.7138119 C5.5317892,10.8366454 5.70473487,11.4879005 6.01525843,11.4879005 L6.15507221,11.4879005 C6.56253666,11.4879005 6.66346464,10.7273367 6.66346464,10.7273367 L6.62617366,10.7266174 C6.81079915,10.6796324 6.98609017,10.6083183 7.14809091,10.5174128 C7.27559945,10.6019077 7.80869616,10.9358221 8.02126251,10.7229118 L8.16298384,10.5812843 C8.4471301,10.2972475 7.98489404,9.71600867 7.97207283,9.6998258 C8.05996069,9.54609631 8.13010212,9.38117171 8.17857256,9.20681883 C8.33758689,9.1663851 8.93544637,8.99492481 8.93544637,8.69761336 L8.93544637,8.55789339 C8.93544637,8.16323452 8.2238377,8.05645882 8.17930744,8.04981368 Z M6.0811626,9.78898015 C5.4427443,9.78898015 4.92547084,9.27186304 4.92547084,8.63349165 C4.92547084,7.99512026 5.4427443,7.4778937 6.08117824,7.4778937 C6.71917438,7.4778937 7.23641656,7.99515153 7.23641656,8.63350729 C7.23641656,9.27186304 6.71919001,9.78898015 6.08117824,9.78898015 L6.0811626,9.78898015 Z M10.6902641,1.99694963 L10.6902641,1.24392218 C10.6902641,0.502449457 10.2222116,0.0595703125 9.43852268,0.0595703125 C8.65533411,0.0595703125 8.18725033,0.502465093 8.18725033,1.24392218 L8.18725033,1.99693399 L7.33923645,1.99693399 L7.33923645,1.24392218 C7.33923645,0.502449457 6.87163738,0.0595703125 6.08794846,0.0595703125 C5.30429082,0.0595703125 4.83667612,0.502465093 4.83667612,1.24392218 L4.83667612,1.99693399 L3.98819316,1.99693399 L3.98819316,1.24392218 C3.98819316,0.502449457 3.52060973,0.0595703125 2.73692081,0.0595703125 C1.95373224,0.0595703125 1.4856641,0.502465093 1.4856641,1.24392218 L1.4856641,1.99693399 L0.048828125,1.99693399 L0.048828125,14.0595703 L12.1117146,14.0595703 L12.1117146,1.99694963 L10.6902485,1.99694963 L10.6902641,1.99694963 Z M8.85762786,1.24392218 C8.85762786,0.878079768 9.02546068,0.7297133 9.43852268,0.7297133 C9.85249155,0.7297133 10.0198709,0.878064133 10.0198709,1.24392218 L10.0198709,3.25826005 C10.0198709,3.62397737 9.85249155,3.77248456 9.43853832,3.77248456 C9.02547632,3.77248456 8.85762786,3.62400864 8.85762786,3.25826005 L8.85762786,1.24392218 L8.85762786,1.24392218 Z M5.50706927,1.24392218 C5.50706927,0.878079768 5.67443303,0.7297133 6.08793283,0.7297133 C6.50147954,0.7297133 6.66931236,0.878064133 6.66931236,1.24392218 L6.66931236,3.25826005 C6.66931236,3.62397737 6.50147954,3.77248456 6.08794846,3.77248456 C5.67443303,3.77248456 5.50706927,3.62400864 5.50706927,3.25826005 L5.50706927,1.24392218 L5.50706927,1.24392218 Z M2.15557255,1.24392218 C2.15557255,0.878079768 2.32340538,0.7297133 2.73690518,0.7297133 C3.15045188,0.7297133 3.31873814,0.878064133 3.31873814,1.24392218 L3.31873814,3.25826005 C3.31873814,3.62397737 3.15043625,3.77248456 2.73690518,3.77248456 C2.32340538,3.77248456 2.15557255,3.62400864 2.15557255,3.25826005 L2.15557255,1.24392218 Z M11.106594,13.054606 L1.05394879,13.054606 L1.05394879,4.67758412 L11.106594,4.67758412 L11.106594,13.054606 L11.106594,13.054606 Z" id="形状"></path>
11 </g>
12 <rect id="矩形" x="0" y="0" width="14" height="14"></rect>
13 </g>
14 </g>
15 </g>
16 </svg>
...\ No newline at end of file ...\ No newline at end of file
1 <template>
2 <section class="app-main">
3 <transition name="fade-transform" mode="out-in">
4 <router-view :key="key" />
5 </transition>
6 <ResetPassDialog></ResetPassDialog>
7 </section>
8 </template>
9
10 <script>
11 import ResetPassDialog from '@/views/components/ResetPassDialog'
12
13 export default {
14 name: 'AppMain',
15 components: {
16 ResetPassDialog
17 },
18 data() {
19 return {
20 visible: true
21 }
22 },
23 computed: {
24 key() {
25 return this.$route.fullPath
26 }
27 }
28 }
29 </script>
30
31 <style scoped>
32 .app-main {
33 /* height: calc(100% - 35px); */
34 padding: 24px 24px 0 24px;
35 background-color: #f0f2f5;
36 }
37 /* 定义过渡时间 */
38 .fade-transform-enter-active,
39 .fade-transform-live-active {
40 transition: all 0.5s;
41 }
42
43 .fade-transform-enter,
44 .fade-transform-live-to {
45 opacity: 0;
46 }
47 </style>
1 <template lang="pug">
2 div(class="header")
3 .logo
4 span(@click="expanMenu")
5 <svg-icon className="toggle-icon" icon-class='togglemenu' />
6 .right-menu
7 el-dropdown(trigger="click" @command="handleCommand")
8 span(class="el-dropdown-link")
9 <svg-icon className="icon" icon-class='user' />
10 span(class="userInfo-name userInfo-discription") {{name}}
11 i(class="el-icon-arrow-down el-icon-caret-bottom")
12 el-dropdown-menu(slot="dropdown")
13 el-dropdown-item(command="pass")
14 span(class="userInfo-operation userInfo-discription") 修改密码
15 el-dropdown-item(command="logout")
16 span(class="userInfo-operation userInfo-discription") 退出
17 </template>
18
19 <script>
20 import { mapState, mapActions, mapMutations } from 'vuex'
21
22 export default {
23 name: 'CommHeader',
24 computed: {
25 ...mapState('app', ['sidebar']),
26 ...mapState(['name', 'userId']),
27 isCollapse() {
28 return this.sidebar.opened
29 }
30 },
31 data() {
32 return {
33 visible: true,
34 resetObj: null
35 }
36 },
37 mounted() {},
38 methods: {
39 ...mapMutations(['TOGGLE_UPDATEPASS_DIALOG']),
40 ...mapActions(['logout']),
41 ...mapActions('app', ['toggleSideBar']),
42 handleLogout() {
43 try {
44 this.logout()
45 this.$router.push('/login')
46 } catch (error) {
47 console.log(error)
48 }
49 },
50 handleUpdatepass() {
51 this.TOGGLE_UPDATEPASS_DIALOG({
52 name: this.name,
53 username: this.userId
54 })
55 },
56 expanMenu() {
57 this.toggleSideBar()
58 },
59 handleCommand(data) {
60 if (data === 'pass') {
61 this.handleUpdatepass()
62 } else if (data === 'logout') {
63 this.handleLogout()
64 }
65 }
66 }
67 }
68 </script>
69
70 <style lang="scss" scoped>
71 .header {
72 display: flex;
73 justify-content: space-between;
74 align-items: center;
75 height: 64px;
76 box-shadow: 0px 1px 4px 0px rgba(0, 21, 41, 0.12);
77 padding: 0 20px 0 24px;
78 }
79 .logo {
80 display: flex;
81 justify-content: flex-start;
82 align-items: center;
83 .toggle-icon {
84 width: 20px;
85 height: 20px;
86 }
87 span {
88 font-size: 14px;
89 cursor: pointer;
90 .rotate {
91 transform: rotate(90deg);
92 }
93 }
94 }
95 .right-menu {
96 .el-dropdown-link {
97 display: flex;
98 flex-flow: row nowrap;
99 justify-content: center;
100 align-items: center;
101 height: 100%;
102 .icon {
103 height: 28px;
104 width: 28px;
105 margin-right: 6px;
106 }
107 }
108 .user-icon {
109 font-size: 20px;
110 margin-right: 10px;
111 }
112 .userInfo-name {
113 margin-right: 10px;
114 color: #666666;
115 }
116 }
117 </style>
1 <template>
2 <span>
3 <svg-icon v-if="icon" className="icon" :icon-class="ComIcon" />
4 <span v-if="title" slot="title">{{ title }}</span>
5 </span>
6 </template>
7
8 <script>
9 import { mapState } from 'vuex'
10
11 export default {
12 name: 'MenuItem',
13 props: {
14 icon: {
15 type: String,
16 default: ''
17 },
18 title: {
19 type: String,
20 default: ''
21 },
22 item: {
23 type: Object
24 }
25 },
26 computed: {
27 ...mapState('permission', ['routes']),
28 ComIcon() {
29 const { path } = this.$route
30 if (path.indexOf(this.item.path) > -1) {
31 return `${this.icon}-active`
32 } else {
33 return this.icon
34 }
35 }
36 }
37 }
38 </script>
39 <style lang="scss" scoped>
40 .icon {
41 width: 14px;
42 height: 14px;
43 }
44 </style>
1
2 <template>
3 <!-- eslint-disable vue/require-component-is -->
4 <component v-bind="linkProps(to)">
5 <slot/>
6 </component>
7 </template>
8
9 <script>
10 import { isExternal } from '@/utils/validate'
11
12 export default {
13 props: {
14 to: {
15 type: String,
16 required: true
17 }
18 },
19 methods: {
20 linkProps(url) {
21 if (isExternal(url)) {
22 return {
23 is: 'a',
24 href: url,
25 target: '_blank',
26 rel: 'noopener'
27 }
28 }
29 return {
30 is: 'router-link',
31 to: url
32 }
33 }
34 }
35 }
36 </script>
1 <template>
2 <div v-if="!item.hidden">
3 <template
4 v-if="hasOneShowingChild(item.children, item) && !item.alwaysShow"
5 >
6 <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
7 <el-menu-item :index="resolvePath(onlyOneChild.path)">
8 <item
9 :icon="onlyOneChild.meta.icon || (item.meta && item.meta.icon)"
10 :title="onlyOneChild.meta.title"
11 :item="onlyOneChild"
12 />
13 </el-menu-item>
14 </app-link>
15 </template>
16 <el-submenu v-else :index="resolvePath(item.path)" popper-append-to-body>
17 <template slot="title">
18 <item
19 v-if="item.meta"
20 :icon="item.meta && item.meta.icon"
21 :title="item.meta.title"
22 :item="item"
23 />
24 </template>
25 <sidebar-item
26 v-for="child in item.children"
27 :key="child.path"
28 :is-nest="true"
29 :item="child"
30 :base-path="resolvePath(child.path)"
31 />
32 </el-submenu>
33 </div>
34 </template>
35 <script>
36 import path from 'path'
37 import Item from './Item'
38 import { isExternal } from '@/utils/validate'
39 import AppLink from './Link'
40
41 export default {
42 name: 'SidebarItem',
43 components: {
44 Item,
45 AppLink
46 },
47 props: {
48 item: {
49 type: Object,
50 require: true
51 },
52 basePath: {
53 type: String,
54 default: ''
55 }
56 },
57 data() {
58 // To fix https://github.com/PanJiaChen/vue-admin-template/issues/237
59 this.onlyOneChild = null
60 return {}
61 },
62 methods: {
63 hasOneShowingChild(children = [], parent) {
64 const showingChildren = children.filter(item => {
65 if (item.hidden) {
66 return false
67 } else {
68 // Temp set(will be used if only has one showing child)
69 this.onlyOneChild = item
70 return true
71 }
72 })
73
74 // When there is only one child router, the child router is displayed by default
75 if (showingChildren.length === 1) {
76 return true
77 }
78
79 // Show parent if there are no child router to display
80 if (showingChildren.length === 0) {
81 this.onlyOneChild = { ...parent, path: '', noShowingChildren: true }
82 return true
83 }
84
85 return false
86 },
87 resolvePath(routePath) {
88 if (isExternal(routePath)) {
89 return routePath
90 }
91 if (isExternal(this.basePath)) {
92 return this.basePath
93 }
94 return path.resolve(this.basePath, routePath)
95 }
96 }
97 }
98 </script>
99 <style lang="scss"></style>
1 <template>
2 <div class="sidebar-container">
3 <div class="home-title">
4 <div class="title title-icon" v-if="!isCollapse"></div>
5 </div>
6 <el-scrollbar>
7 <el-menu
8 mode="vertical"
9 :default-active="activeMenu"
10 :collapse="isCollapse"
11 :unique-opened="false"
12 :collapse-transition="false"
13 >
14 <sidebar-item
15 v-for="route in routes"
16 :key="route.path"
17 :item="route"
18 :base-path="route.path"
19 />
20 </el-menu>
21 </el-scrollbar>
22 </div>
23 </template>
24 <script>
25 import SidebarItem from './SidebarItem'
26 import { mapState, mapMutations } from 'vuex'
27
28 export default {
29 components: {
30 SidebarItem
31 },
32 data() {
33 return {
34 menuBg: '#304156',
35 menuText: '#bfcbd9',
36 menuActiveText: '#409EFF'
37 }
38 },
39 computed: {
40 ...mapState('app', ['sidebar']),
41 ...mapState('permission', ['routes']),
42 activeMenu() {
43 const route = this.$route
44 const { meta, path } = route
45 if (meta.activeMenu) {
46 return meta.activeMenu
47 }
48 return path
49 },
50 isCollapse() {
51 return this.sidebar.opened
52 }
53 },
54 methods: {
55 ...mapMutations('app', ['SET_IS_COLLAPSE'])
56 }
57 }
58 </script>
59 <style lang="scss">
60 .sidebar-container {
61 width: 100%;
62 height: 100%;
63 .home-title {
64 background: #002140;
65 height: 64px;
66 display: flex;
67 justify-content: center;
68 align-items: center;
69 .title {
70 width: 166px;
71 height: 24px;
72 background-size: contain;
73 }
74 }
75 .el-scrollbar {
76 height: calc(100% - 64px);
77 background-color: #001529;
78 .el-scrollbar__wrap {
79 overflow-x: hidden !important;
80 // 导航栏间距
81 .el-scrollbar__view {
82 > .el-menu {
83 > div {
84 margin: 10px 0;
85 }
86 }
87 }
88 .el-menu {
89 width: 100%;
90 background: #001529;
91 border-right: 0;
92 .el-submenu.is-active {
93 .el-submenu__title {
94 span {
95 color: #fff;
96 }
97 }
98 }
99 .el-submenu,
100 .el-menu-item > span {
101 .icon {
102 margin-right: 14px;
103 }
104 }
105 .el-menu-item,
106 .el-submenu__title {
107 color: #999;
108 background: #001529;
109 text-align: left;
110 }
111 .el-menu-item.is-active {
112 color: #fff;
113 background: #1890ff;
114 }
115 span {
116 font-size: 14px;
117 font-weight: 500;
118 }
119 }
120 .el-menu--collapse {
121 .el-submenu > .el-submenu__title > span {
122 display: inline-flex;
123 flex-flow: row nowrap;
124 justify-content: center;
125 align-items: center;
126 height: 20px;
127 width: 20px;
128 overflow: visible;
129 visibility: visible;
130 .icon {
131 margin: 0;
132 }
133 span {
134 display: none;
135 }
136 }
137 .el-menu-item > span {
138 span {
139 display: none;
140 }
141 }
142 }
143 }
144 }
145 }
146
147 .el-menu--collapse {
148 .el-submenu {
149 & > .el-submenu__title {
150 & > span {
151 height: 0;
152 width: 0;
153 overflow: hidden;
154 visibility: hidden;
155 display: inline-block;
156 }
157 .el-submenu__icon-arrow {
158 display: none;
159 }
160 }
161 }
162 }
163 </style>
1 <template lang="pug">
2 el-breadcrumb(separator="/" class="app-breadcrumb")
3 transition-group(name="breadcrumb")
4 el-breadcrumb-item(v-for="(item,index) in levelList" :key="item.path")
5 span(v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect") {{ item.meta.title }}
6 a(v-else @click.prevent="handleLink(item)") {{ item.meta.title }}
7 </template>
8
9 <script>
10 import pathToRegexp from 'path-to-regexp'
11
12 export default {
13 data() {
14 return {
15 levelList: null
16 }
17 },
18 watch: {
19 $route() {
20 this.getBreadcrumb()
21 }
22 },
23 created() {
24 this.getBreadcrumb()
25 },
26 methods: {
27 getBreadcrumb() {
28 // only show routes with meta.title
29 let matched = this.$route.matched.filter(
30 item => item.meta && item.meta.title
31 )
32 // const first = matched[0]
33
34 // if (this.isWhoRoute(first, 'dayBillingInquiry')) {
35 // matched = [{ path: '/billing', meta: { title: '账单查询' } }].concat(
36 // matched
37 // )
38 // }
39 // if (this.isWhoRoute(first, 'billingDetail')) {
40 // matched = [
41 // { path: '/billing', meta: { title: '账单查询' } },
42 // { path: '/billing/dayBillingInquiry', meta: { title: '日调用量' } }
43 // ].concat(matched)
44 // }
45
46 this.levelList = matched.filter(
47 item => item.meta && item.meta.title && item.meta.breadcrumb !== false
48 )
49 },
50 isWhoRoute(route, str) {
51 const name = route && route.name
52 if (!name) {
53 return false
54 }
55 return name.trim().toLocaleLowerCase() === str.toLocaleLowerCase()
56 },
57 pathCompile(path) {
58 // To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
59 const { params } = this.$route
60 const toPath = pathToRegexp.compile(path)
61 return toPath(params)
62 },
63 handleLink(item) {
64 const { redirect, path } = item
65 if (redirect) {
66 this.$router.push(redirect)
67 return
68 }
69 this.$router.push(this.pathCompile(path))
70 }
71 }
72 }
73 </script>
74
75 <style lang="scss" scoped>
76 .app-breadcrumb.el-breadcrumb {
77 height: 54px;
78 font-size: 14px;
79 padding-left: 32px;
80 display: flex;
81 align-items: center;
82 .no-redirect {
83 color: #666;
84 cursor: text;
85 }
86 }
87 /* breadcrumb transition */
88 .breadcrumb-enter-active,
89 .breadcrumb-leave-active {
90 transition: all 0.5s;
91 }
92
93 .breadcrumb-enter,
94 .breadcrumb-leave-active {
95 opacity: 0;
96 transform: translateX(20px);
97 }
98
99 .breadcrumb-move {
100 transition: all 0.5s;
101 }
102
103 .breadcrumb-leave-active {
104 position: absolute;
105 }
106 </style>
107 <style lang="scss" scoped>
108 .app-breadcrumb {
109 .el-breadcrumb__inner.is-link,
110 .el-breadcrumb__inner a {
111 color: rgba(0, 0, 0, 0.45);
112 }
113 .el-breadcrumb__inner .no-redirect {
114 color: rgba(0, 0, 0, 0.65);
115 font-weight: 400;
116 }
117 .el-breadcrumb__inner.is-link:hover,
118 .el-breadcrumb__inner a:hover {
119 cursor: auto;
120 color: rgba(0, 0, 0, 0.45);
121 }
122 }
123 </style>
1 export { default as Sidebar } from './Sidebar'
2 export { default as AppMain } from './AppMain'
3 export { default as Header } from './Header'
1 <template lang="pug">
2 .app
3 el-container
4 el-aside(:width="asideWidth")
5 sidebar
6 el-container
7 el-header(height='118px')
8 Header
9 Breadcrumb
10 el-main
11 AppMain
12 </template>
13 <script>
14 import { Sidebar, AppMain, Header } from './components'
15 import Breadcrumb from './components/breadcrumb'
16
17 import { mapState } from 'vuex'
18 export default {
19 name: 'Layout',
20 components: {
21 Sidebar,
22 Header,
23 AppMain,
24 Breadcrumb
25 },
26 computed: {
27 ...mapState('app', ['sidebar']),
28 siderbar() {
29 return this.$store.state.app.siderbar
30 },
31 asideWidth() {
32 return this.sidebar.opened ? '64px' : '256px'
33 }
34 }
35 }
36 </script>
37 <style lang="scss" scope>
38 .app {
39 height: 100%;
40 > .el-container {
41 height: 100%;
42 }
43 .el-header {
44 padding: 0;
45 }
46 .el-main {
47 padding: 0;
48 }
49 .el-aside {
50 transition: width 0.2s ease-in;
51 box-shadow: 2px 0px 6px 0px rgba(0, 21, 41, 0.35);
52 }
53 }
54 </style>
1 import Vue from 'vue'
2 import App from './App.vue'
3 import router from './router'
4 import store from './store'
5 import VueParticles from 'vue-particles'
6 import ElementUI from 'element-ui'
7 import './element-variables.scss'
8 import './base.scss'
9 import './permission'
10 import '@/icons'
11 import 'animate.css'
12 import 'video.js/dist/video-js.css'
13
14 import VeLine from 'v-charts/lib/line.common'
15 import VeHistogram from 'v-charts/lib/histogram.common'
16
17 import Card from '_c/card'
18
19 Vue.config.productionTip = false
20 Vue.use(ElementUI)
21 Vue.use(VueParticles)
22
23 Vue.component('Card', Card)
24 Vue.component(VeLine.name, VeLine)
25 Vue.component(VeHistogram.name, VeHistogram)
26
27 new Vue({
28 router,
29 store,
30 render: h => h(App)
31 }).$mount('#app')
1 import router from './router'
2 import NProgress from 'nprogress' // progress bar
3 import 'nprogress/nprogress.css' // progress bar style
4 import { getToken } from '@/utils/auth' // get token from cookie
5 import store from './store'
6
7 NProgress.configure({ showSpinner: false }) // NProgress Configuration
8 const whiteList = ['/login']
9
10 router.beforeEach((to, from, next) => {
11 let routerTemp = store.state.resetRouterTemp
12 // start progress bar
13 NProgress.start()
14 // determine whether the user has logged in
15 const hasToken = getToken()
16 if (hasToken) {
17 if (routerTemp) {
18 next()
19 } else {
20 store.commit('SET_ROUTER_TEMP', 'TEMP')
21 let roles = store.state.roles
22 store.commit('permission/SET_ROUTES', { roles })
23 router.addRoutes(store.state.permission.routes)
24 // hack method to ensure that addRoutes is complete
25 // set the replace: true, so the navigation will not leave a history record
26 next({ ...to, replace: true })
27 }
28 } else {
29 // other pages that do not have permission to access are redirected to the login page.
30 if (whiteList.indexOf(to.path) !== -1) {
31 next()
32 } else {
33 next(`/login?redirect=${to.path}`) // 重定向到登录页
34 NProgress.done()
35 }
36 }
37 })
38
39 router.afterEach(() => {
40 // finish progress bar
41 NProgress.done()
42 })
1 import Vue from 'vue'
2 import Router from 'vue-router'
3
4 import Layout from '@/layout'
5 import { PERMISSION_USER_MAP } from '@/utils/mappingData'
6
7 const originalPush = Router.prototype.push
8 Router.prototype.push = function push(location) {
9 return originalPush.call(this, location).catch(err => err)
10 }
11
12 Vue.use(Router)
13
14 /**
15 * Note: sub-menu only appear when route children.length >= 1
16 * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
17 *
18 * hidden: true if set true, item will not show in the sidebar(default is false)
19 * alwaysShow: true if set true, will always show the root menu
20 * if not set alwaysShow, when item has more than one children route,
21 * it will becomes nested mode, otherwise not show the root menu
22 * redirect: noRedirect if set noRedirect will no redirect in the breadcrumb
23 * name:'router-name' the name is used by <keep-alive> (must set!!!)
24 * meta : {
25 roles: ['admin','editor'] control the page roles (you can set multiple roles)
26 title: 'title' the name show in sidebar and breadcrumb (recommend set)
27 icon: 'svg-name' the icon show in the sidebar
28 noCache: true if set true, the page will no be cached(default is false)
29 affix: true if set true, the tag will affix in the tags-view
30 breadcrumb: false if set false, the item will hidden in breadcrumb(default is true)
31 activeMenu: '/example/list' if set path, the sidebar will highlight the path you set
32 }
33 */
34
35 /**
36 * constantRoutes
37 * a base page that does not have permission requirements
38 * all roles can be accessed
39 */
40
41 export const constantRoutes = [
42 {
43 path: '/login',
44 component: () => import('@/views/login/index'),
45 hidden: true
46 }
47 ]
48 /**
49 * asyncRoutes
50 * the routes that need to be dynamically loaded based on user roles
51 */
52 export const asyncRoutes = [
53 {
54 path: '/',
55 component: Layout,
56 redirect: '/monitor',
57 meta: {
58 roles: [
59 PERMISSION_USER_MAP.admin.code,
60 PERMISSION_USER_MAP.dataAnalyst.code
61 ]
62 },
63 children: [
64 {
65 path: 'monitor',
66 name: 'monitor',
67 component: () => import('@/views/monitor'),
68 meta: {
69 title: '资源监控',
70 icon: 'home'
71 }
72 },
73 {
74 path: 'monitor-details',
75 name: 'monitor-details',
76 hidden: true,
77 component: () => import('@/views/monitor'),
78 meta: {
79 title: '远程订单详情',
80 icon: 'home'
81 }
82 }
83 ]
84 },
85 {
86 path: '/404',
87 component: () => import('@/views/404'),
88 hidden: true
89 }
90 // { path: '*', redirect: '/404', hidden: true }
91 ]
92
93 const createRouter = () =>
94 new Router({
95 scrollBehavior: () => ({ y: 0 }),
96 routes: constantRoutes
97 })
98
99 const router = createRouter()
100
101 export default router
1 import Vue from 'vue'
2 import Vuex from 'vuex'
3
4 import app from './modules/app'
5 import permission from './modules/permisssion'
6
7 import { login, logout } from '@/api/user'
8 import { getToken, setToken, removeToken } from '@/utils/auth'
9 import { NAME, USER_TYPE, USER_ID, USER_PASS } from '@/utils/mappingData'
10
11 Vue.use(Vuex)
12
13 export default new Vuex.Store({
14 state: {
15 token: getToken(),
16 name: sessionStorage.getItem(NAME),
17 roles: JSON.parse(sessionStorage.getItem(USER_TYPE)) || '',
18 userId: sessionStorage.getItem(USER_ID),
19 resetRouterTemp: '',
20 userpass: JSON.parse(sessionStorage.getItem(USER_PASS)) || ''
21 },
22 mutations: {
23 SET_TOKEN: (state, token) => {
24 state.token = token
25 setToken(token)
26 },
27 SET_NAME: (state, name) => {
28 sessionStorage.setItem(NAME, name)
29 state.name = name
30 },
31 SET_USER_ID: (state, userId) => {
32 sessionStorage.setItem(USER_ID, userId)
33 state.userId = userId
34 },
35 SET_ROLES: (state, userType) => {
36 state.roles = userType
37 sessionStorage.setItem(USER_TYPE, JSON.stringify(userType))
38 },
39 SET_ROUTER_TEMP(state, payload) {
40 state.resetRouterTemp = payload
41 },
42 SET_USERPASS(state, payload) {
43 state.userpass = payload
44 sessionStorage.setItem(USER_PASS, payload)
45 }
46 },
47 actions: {
48 async login({ dispatch, commit }, userinfo) {
49 try {
50 const { username, password } = userinfo
51 const res = await login({
52 username: username.trim(),
53 password: password
54 })
55 if (res.code === 0) {
56 commit('SET_ROLES', res.result.roleCode)
57 commit('SET_NAME', res.result.name)
58 commit('SET_USER_ID', res.result.username)
59 commit('SET_TOKEN', res.result.token)
60 }
61 return res
62 } catch (error) {
63 console.log(error)
64 }
65 },
66 // remove token
67 resetToken({ commit }) {
68 return new Promise(resolve => {
69 removeToken()
70 sessionStorage.clear()
71 resolve()
72 })
73 },
74 async logout({ dispatch, commit }) {
75 try {
76 const res = await logout()
77 dispatch('resetToken')
78 return res
79 } catch (error) {
80 console.log(error)
81 }
82 }
83 },
84 modules: {
85 app,
86 permission
87 }
88 })
1 // import Cookies from 'js-cookie'
2
3 const state = {
4 sidebar: {
5 // string => num => boolean
6 opened: !!+sessionStorage.getItem('sidebarStatus'),
7 withoutAnimation: false
8 }
9 }
10
11 const mutations = {
12 TOGGLE_SIDEBAR: state => {
13 state.sidebar.opened = !state.sidebar.opened
14 state.sidebar.withoutAnimation = false
15 if (state.sidebar.opened) {
16 sessionStorage.setItem('sidebarStatus', 1)
17 } else {
18 sessionStorage.setItem('sidebarStatus', 0)
19 }
20 },
21 CLOSE_SIDEBAR: (state, withoutAnimation) => {
22 sessionStorage.setItem('sidebarStatus', 0)
23 state.sidebar.opened = false
24 state.sidebar.withoutAnimation = withoutAnimation
25 }
26 }
27
28 const actions = {
29 toggleSideBar({ commit }) {
30 commit('TOGGLE_SIDEBAR')
31 },
32 closeSideBar({ commit }, { withoutAnimation }) {
33 commit('CLOSE_SIDEBAR', withoutAnimation)
34 }
35 }
36
37 export default {
38 namespaced: true,
39 state,
40 mutations,
41 actions
42 }
1 import { constantRoutes, asyncRoutes } from '@/router'
2
3 function hasPermission(roles, route) {
4 if (route.meta && route.meta.roles) {
5 return route.meta.roles.includes(roles)
6 } else {
7 return true
8 }
9 }
10
11 function filterAsyncRoutes(routes, roles) {
12 const res = []
13 routes.forEach(route => {
14 const temp = { ...route }
15 if (hasPermission(roles, temp)) {
16 if (temp.children) {
17 temp.children = filterAsyncRoutes(temp.children, roles)
18 }
19 res.push(temp)
20 }
21 })
22 return res
23 }
24
25 const state = {
26 routes: [],
27 addRoutes: []
28 }
29
30 const mutations = {
31 SET_ROUTES: (state, payload) => {
32 state.addRoutes = filterAsyncRoutes(asyncRoutes, payload.roles)
33 state.routes = constantRoutes.concat(state.addRoutes)
34 }
35 }
36
37 export default {
38 namespaced: true,
39 state,
40 mutations
41 }
1 import Cookies from 'js-cookie'
2 import { USER_ID } from '@/utils/mappingData'
3
4 export function getToken() {
5 if (sessionStorage.getItem(USER_ID) === null) {
6 return ''
7 } else {
8 return Cookies.get(sessionStorage.getItem(USER_ID))
9 }
10 }
11
12 export function setToken(token) {
13 let expires = new Date(new Date().getTime() + 60 * 60 * 24 * 1000)
14 return Cookies.set(sessionStorage.getItem(USER_ID), token, {
15 expires: expires
16 })
17 }
18
19 export function removeToken() {
20 return Cookies.remove(sessionStorage.getItem(USER_ID))
21 }
1 // session key
2 export const NAME = 'name'
3 export const USER_ID = 'userId'
4 export const USER_TYPE = 'userType'
5 export const USER_PASS = 'userpass'
6
7 // 权限字段
8 export const PERMISSION_USER_MAP = {
9 admin: {
10 code: 'admin',
11 name: '管理员'
12 },
13 auditor: {
14 code: 'auditor',
15 name: '初级审核员'
16 },
17 dataAnalyst: {
18 code: 'dataAnalyst',
19 name: '数据分析员'
20 }
21 }
22
23 // contactCard const
24 export const CONTACT_CARD = {
25 ANSWER_END: 'answerEnd', // 接听挂断
26 ANSWER: 'answer', // 接听
27 CALL: 'call', // 呼叫
28 CALL_END: 'callEnd' // 呼叫挂断
29 }
1 import store from '@/store'
2
3 export default function checkPermission(value) {
4 if (value && value instanceof Array && value.length > 0) {
5 const roles = store.state.roles
6 const permissionRoles = value
7 const hasPermission = roles.some(role => {
8 return permissionRoles.includes(role)
9 })
10 if (hasPermission) {
11 return true
12 } else {
13 return false
14 }
15 } else {
16 console.error(`need roles! Like v-permission="['admin','editor']"`)
17 return false
18 }
19 }
1 import axios from 'axios'
2 // MessageBox
3 import { Message } from 'element-ui'
4 import store from '@/store'
5 import { getToken, removeToken } from '@/utils/auth'
6 import router from '@/router'
7
8 // create an axios instance
9 const service = axios.create({
10 // baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
11 withCredentials: false // send cookies when cross-domain requests
12 // timeout: 10000 // request timeout
13 })
14
15 // request interceptor
16 service.interceptors.request.use(
17 config => {
18 // do something before request is sent
19 if (store.state.token) {
20 // let each request carry token --['X-Token'] as a custom key.
21 // please modify it according to the actual situation.
22 config.headers['X-Source'] = 'web'
23 config.headers['x-auth-token'] = getToken()
24 }
25 return config
26 },
27 error => {
28 // do something with request error
29 console.log(error) // for debug
30 return Promise.reject(error)
31 }
32 )
33
34 // response interceptor
35 service.interceptors.response.use(
36 /**
37 * If you want to get information such as headers or status
38 * Please return response => response
39 */
40
41 /**
42 * Determine the request status by custom code
43 * Here is just an example
44 * You can also judge the status by HTTP Status Code.
45 */
46 response => {
47 const res = response.data
48 if (response.config.url.includes('download')) {
49 return res
50 }
51 if (response.config.url.includes('recognize')) {
52 return res
53 }
54 if (response.config.url.includes('verify')) {
55 return res
56 }
57
58 // 3703图片未识别 3730报表无数据
59 if (
60 (res && res.code === 0) ||
61 res.code === 2926 ||
62 res.code === 4001 ||
63 res.code === 3703 ||
64 res.code === 3730
65 ) {
66 return res
67 } else if (res && res.code === 2909) {
68 // 2909 登录超时
69 // cookie失效
70 Message({
71 message: res.msg || 'error',
72 type: 'error',
73 duration: 5 * 1000
74 })
75 removeToken()
76 router.push('/login')
77 } else if (res && res.code) {
78 Message({
79 message: res.msg || 'error',
80 type: 'error',
81 duration: 5 * 1000
82 })
83 }
84 return res
85 },
86 error => {
87 Message({
88 message: '网络连接异常',
89 type: 'error',
90 duration: 5 * 1000
91 })
92 console.log('err' + error) // for debug
93 return Promise.reject(error)
94 }
95 )
96
97 export default service
1 /**
2 * Parse the time to string
3 * @param {(Object|string|number)} time
4 * @param {string} cFormat
5 * @returns {string}
6 */
7 export function parseTime(time, cFormat) {
8 if (arguments.length === 0) {
9 return null
10 }
11 const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
12 let date
13 if (typeof time === 'object' && time) {
14 date = time
15 } else {
16 if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
17 time = parseInt(time)
18 }
19 if (typeof time === 'number' && time.toString().length === 10) {
20 time = time * 1000
21 }
22 date = new Date(time)
23 }
24 const formatObj = {
25 y: date.getFullYear(),
26 m: date.getMonth() + 1,
27 d: date.getDate(),
28 h: date.getHours(),
29 i: date.getMinutes(),
30 s: date.getSeconds(),
31 a: date.getDay()
32 }
33 const timeStr = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
34 let value = formatObj[key]
35 // Note: getDay() returns 0 on Sunday
36 if (key === 'a') {
37 return ['日', '一', '二', '三', '四', '五', '六'][value]
38 }
39 if (result.length > 0 && value < 10) {
40 value = '0' + value
41 }
42 return value || 0
43 })
44 return timeStr
45 }
46
47 /**
48 * @param {string} url
49 * @returns {Object}
50 */
51 export function getQueryObject(url) {
52 url = url == null ? window.location.href : url
53 const search = url.substring(url.lastIndexOf('?') + 1)
54 const obj = {}
55 const reg = /([^?&=]+)=([^?&=]*)/g
56 search.replace(reg, (rs, $1, $2) => {
57 const name = decodeURIComponent($1)
58 let val = decodeURIComponent($2)
59 val = String(val)
60 obj[name] = val
61 return rs
62 })
63 return obj
64 }
65
66 /**
67 * @param {string} input value
68 * @returns {number} output value
69 */
70 export function byteLength(str) {
71 // returns the byte length of an utf8 string
72 let s = str.length
73 for (var i = str.length - 1; i >= 0; i--) {
74 const code = str.charCodeAt(i)
75 if (code > 0x7f && code <= 0x7ff) s++
76 else if (code > 0x7ff && code <= 0xffff) s += 2
77 if (code >= 0xdc00 && code <= 0xdfff) i--
78 }
79 return s
80 }
81
82 /**
83 * @param {Array} actual
84 * @returns {Array}
85 */
86 export function cleanArray(actual) {
87 const newArray = []
88 for (let i = 0; i < actual.length; i++) {
89 if (actual[i]) {
90 newArray.push(actual[i])
91 }
92 }
93 return newArray
94 }
95
96 /**
97 * @param {Object} json
98 * @returns {Array}
99 */
100 export function param(json) {
101 if (!json) return ''
102 return cleanArray(
103 Object.keys(json).map(key => {
104 if (json[key] === undefined) return ''
105 return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
106 })
107 ).join('&')
108 }
109
110 /**
111 * @param {string} url
112 * @returns {Object}
113 */
114 export function param2Obj(url) {
115 const search = url.split('?')[1]
116 if (!search) {
117 return {}
118 }
119 return JSON.parse(
120 '{"' +
121 decodeURIComponent(search)
122 .replace(/"/g, '\\"')
123 .replace(/&/g, '","')
124 .replace(/=/g, '":"')
125 .replace(/\+/g, ' ') +
126 '"}'
127 )
128 }
129
130 /**
131 * Merges two objects, giving the last one precedence
132 * @param {Object} target
133 * @param {(Object|Array)} source
134 * @returns {Object}
135 */
136 export function objectMerge(target, source) {
137 if (typeof target !== 'object') {
138 target = {}
139 }
140 if (Array.isArray(source)) {
141 return source.slice()
142 }
143 Object.keys(source).forEach(property => {
144 const sourceProperty = source[property]
145 if (typeof sourceProperty === 'object') {
146 target[property] = objectMerge(target[property], sourceProperty)
147 } else {
148 target[property] = sourceProperty
149 }
150 })
151 return target
152 }
153
154 /**
155 * @param {string} type
156 * @returns {Date}
157 */
158 export function getTime(type) {
159 if (type === 'start') {
160 return new Date().getTime() - 3600 * 1000 * 24 * 90
161 } else {
162 return new Date(new Date().toDateString())
163 }
164 }
165
166 /**
167 * @param {Function} func
168 * @param {number} wait
169 * @param {boolean} immediate
170 * @return {*}
171 */
172 export function debounce(func, wait, immediate) {
173 let timeout, args, context, timestamp, result
174
175 const later = function() {
176 // 据上一次触发时间间隔
177 const last = +new Date() - timestamp
178
179 // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
180 if (last < wait && last > 0) {
181 timeout = setTimeout(later, wait - last)
182 } else {
183 timeout = null
184 // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
185 if (!immediate) {
186 result = func.apply(context, args)
187 if (!timeout) context = args = null
188 }
189 }
190 }
191
192 return function(...args) {
193 context = this
194 timestamp = +new Date()
195 const callNow = immediate && !timeout
196 // 如果延时不存在,重新设定延时
197 if (!timeout) timeout = setTimeout(later, wait)
198 if (callNow) {
199 result = func.apply(context, args)
200 context = args = null
201 }
202
203 return result
204 }
205 }
206
207 /**
208 * 节流
209 * @param {*} func
210 * @param {*} wait
211 * @param {*} immediate
212 */
213 export function throttle(fn, wait = 1000, immediate) {
214 let timer = null
215 let callNow = immediate
216 return function(...args) {
217 let context = this
218 if (callNow) {
219 fn.apply(context, args)
220 callNow = null
221 }
222 if (!timer) {
223 timer = setTimeout(() => {
224 fn.apply(context, args)
225 timer = null
226 }, wait)
227 }
228 }
229 }
230
231 /**
232 * @param {Array} arr
233 * @returns {Array}
234 */
235 export function uniqueArr(arr) {
236 return Array.from(new Set(arr))
237 }
238
239 /**
240 * @returns {string}
241 */
242 export function createUniqueString() {
243 const timestamp = +new Date() + ''
244 const randomNum = parseInt((1 + Math.random()) * 65536) + ''
245 return (+(randomNum + timestamp)).toString(32)
246 }
247 /**
248 * 延迟执行某个操作
249 * @param {} ms
250 */
251 export function timeout(ms) {
252 return new Promise((resolve, reject) => {
253 setTimeout(resolve, ms, 'done')
254 })
255 }
256 /**
257 * 二进制转文件
258 * @param {*} blobs blob对象
259 * @param {*} fileName 文件名
260 */
261 export function blob2File(blobs, fileName) {
262 const blob = new Blob([blobs])
263 const href = window.URL.createObjectURL(blob) // 创建下载的链接
264 const aEle = document.createElement('a') // 创建a标签
265 aEle.href = href
266 aEle.download = fileName // 下载后文件名
267 document.body.appendChild(aEle)
268 aEle.click() // 点击下载
269 document.body.removeChild(aEle) // 下载完成移除元素
270 window.URL.revokeObjectURL(href) // 释放掉blob对象
271 }
272 /**
273 * url下载文件
274 * @param {*} url
275 * @param {*} name
276 */
277 export function downFile(url, name) {
278 const a = document.createElement('a')
279 a.href = url
280 a.download = name
281 document.body.appendChild(a)
282 a.click()
283 document.body.removeChild(a)
284 }
285
286 /**
287 * 对象转换成formdata形式
288 * @param {*} data
289 */
290 export function obj2FormData(data) {
291 const form = new FormData()
292 Object.keys(data).forEach(key => {
293 if (data[key] !== undefined) {
294 form.append(key, data[key])
295 }
296 })
297 return form
298 }
299 function typeOf(obj) {
300 const toString = Object.prototype.toString
301 const map = {
302 '[object Boolean]': 'boolean',
303 '[object Number]': 'number',
304 '[object String]': 'string',
305 '[object Null]': 'null',
306 '[object Undefined]': 'undefined',
307 '[object Symbol]': 'symbol',
308 '[object Object]': 'object',
309 '[object Function]': 'function',
310 '[object Array]': 'array',
311 '[object Date]': 'date',
312 '[object RegExp]': 'regexp'
313 }
314 return map[toString.call(obj)]
315 }
316 /**
317 * 深克隆
318 * @param {*} data
319 */
320 export function deepClone(data) {
321 const type = typeOf(data)
322 let copy
323 if (type === 'array') {
324 copy = []
325 } else if (type === 'object') {
326 copy = {}
327 } else {
328 return data
329 }
330 if (type === 'array') {
331 for (let i = 0; i < data.length; i++) {
332 copy.push(deepClone(data[i]))
333 }
334 }
335 if (type === 'object') {
336 for (let key in data) {
337 copy[key] = deepClone(data[key])
338 }
339 }
340 return copy
341 }
342
343 /**
344 * filter undefined
345 * @param {*} temp
346 */
347 export function parseUndefined(temp) {
348 // 判断是否为0
349 if (temp === 0 || temp === '0') {
350 return temp
351 }
352 if (temp) {
353 return temp
354 } else {
355 return undefined
356 }
357 }
358 /**
359 * 获取目标的元素的截图
360 * @param {*} target
361 * @param {*} format
362 */
363 export function shotTargetToImage(target, format) {
364 const canvas = document.createElement('canvas') // 创建画布
365 canvas.width = target.videoWidth
366 canvas.height = target.videoHeight // 设定宽高比
367 canvas.getContext('2d').drawImage(target, 0, 0, canvas.width, canvas.height) // 将视频此刻帧数画入画布
368 return canvas.toDataURL(format)
369 }
370
371 // 去掉base头部
372 export function substringBasehead(base64) {
373 let length = 'data:image/png;base64,'.length
374 return base64.substring(length)
375 }
376
377 export function parseTimeSecond(time) {
378 let minutes = parseInt((time % (1000 * 60 * 60)) / (1000 * 60))
379 let second = parseInt((time % (1000 * 60)) / 1000)
380 if (minutes < 10) {
381 minutes = `0${minutes}`
382 }
383 if (second < 10) {
384 second = `0${second}`
385 }
386 return `${minutes}:${second}`
387 }
388
389 export function sleep(time) {
390 return new Promise(resolve => {
391 setTimeout(resolve, time)
392 })
393 }
1 /**
2 * Created by PanJiaChen on 16/11/18.
3 */
4
5 /**
6 * @param {string} path
7 * @returns {Boolean}
8 */
9 export function isExternal(path) {
10 return /^(https?:|mailto:|tel:)/.test(path)
11 }
12
13 /**
14 * @param {string} str
15 * @returns {Boolean}
16 */
17 export function validUsername(str) {
18 const validMap = ['admin', 'editor']
19 return validMap.indexOf(str.trim()) >= 0
20 }
21 /**
22 * 模型名称校验函数
23 * @param {*} rule
24 * @param {*} value
25 * @param {*} callback
26 */
27 export function validateName(rule, value, callback) {
28 if (!value) {
29 return callback(new Error('模型名称不能为空'))
30 }
31 if (/(^\s+)|(\s+$)/.test(value)) {
32 return callback(new Error('首字符和尾字符不得为空格'))
33 }
34 if (value.length < 2 || value.length > 10) {
35 return callback(new Error('长度在 2 到 10 个字符'))
36 }
37 callback()
38 }
39 /**
40 * 模型描述校验函数
41 * @param {*} rule
42 * @param {*} value
43 * @param {*} callback
44 */
45 export function validateDes(rule, value, callback) {
46 if (!value) {
47 return callback(new Error('模型描述不能为空'))
48 }
49 if (/(^\s+)|(\s+$)/.test(value)) {
50 return callback(new Error('首字符和尾字符不得为空格'))
51 }
52 if (value.length < 2 || value.length > 20) {
53 return callback(new Error('长度在 2 到 20 个字符'))
54 }
55 callback()
56 }
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!