Compare commits

...

230 Commits

Author SHA1 Message Date
5a3e16df1b Merge pull request 'fzq' (#32) from fzq into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #32
2023-09-12 15:37:15 +08:00
Fanzink
6815ac4cc4 '修改设备与PLC关联-新增-下拉框条数' 2023-09-12 12:44:54 +05:30
Fanzink
4ffbdaef8a '设备与PLC,设备获取所有' 2023-04-22 10:51:10 +05:30
36e6551465 Merge pull request ''厂务设备参数修改设备列表size,设备分析状态监控去掉默认产线工厂'' (#29) from fzq into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #29
2023-04-18 15:42:29 +08:00
Fanzink
b1ab1962b1 '厂务设备参数修改设备列表size,设备分析状态监控去掉默认产线工厂' 2023-04-18 09:48:13 +05:30
2cefabc24b Merge pull request ''修改日期选择器样式文件index.css'' (#28) from fzq into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #28
2023-03-30 15:40:27 +08:00
Fanzink
db47bffb18 '修改日期选择器样式文件index.css' 2023-03-30 11:28:14 +05:30
65b489d37c Merge pull request ''数据分析bug修改2次'' (#27) from fzq into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #27
2023-03-27 10:59:39 +08:00
Fanzink
5afadfb1ce '数据分析bug修改2次' 2023-03-24 17:23:26 +05:30
67612107ea Merge pull request ''改数据分析bug'' (#26) from fzq into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #26
2023-03-23 17:09:52 +08:00
Fanzink
e0d4e5327f '改数据分析bug' 2023-03-23 11:31:59 +05:30
7ec1c5f3fc Merge pull request ''修改数据分析/产品质量分析和产量分析'' (#25) from fzq into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #25
2023-03-21 14:20:58 +08:00
Fanzink
3da95fed21 '修改数据分析/产品质量分析和产量分析' 2023-03-18 13:58:14 +05:30
092d7da353 Merge pull request ''数据分析-产量分析,产品质量分析,设备产量时序图'' (#24) from fzq into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #24
2023-03-14 18:09:35 +08:00
Fanzink
683fc9169a '数据分析-产量分析,产品质量分析,设备产量时序图' 2023-03-14 15:24:30 +05:30
e81c4f6907 Merge pull request ''update'' (#23) from fzq into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #23
2023-02-14 12:00:34 +08:00
Fanzink
bc4cfdc990 'update' 2023-02-13 17:09:10 +08:00
1c67ef4c6a Merge pull request ''update'' (#22) from fzq into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #22
2023-02-09 15:08:04 +08:00
Fanzink
0b5740d41c 'update' 2023-02-09 15:06:33 +08:00
bd8bdfd9a8 Merge pull request ''update''' (#21) from fzq into develop
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #21
2023-02-09 10:32:51 +08:00
Fanzink
41e680b55d 'update'' 2023-02-09 10:31:00 +08:00
fa06c12ece Merge pull request 'fzq' (#20) from fzq into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #20
2023-02-08 19:42:10 +08:00
Fanzink
28303e4c5f 'update' 2023-02-08 18:13:08 +08:00
Fanzink
bbe5e63075 'update' 2023-02-06 10:25:01 +08:00
e964c643d8 Merge pull request 'fzq' (#19) from fzq into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #19
2023-02-03 16:52:39 +08:00
Fanzink
f9d40b3790 '改bug' 2023-02-03 16:44:47 +08:00
Fanzink
8ec42773cd 'update' 2023-01-31 10:48:38 +08:00
715bc73504 Merge pull request 'fzq' (#17) from fzq into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #17
2023-01-17 16:25:39 +08:00
Fanzink
2f4e9f31cd 'update新图标、新样式' 2023-01-17 16:20:28 +08:00
Fanzink
5798e5b6e0 '前后端内容修改、样式、中英文' 2023-01-13 16:54:26 +08:00
63a487dcd2 Merge pull request ''修改路由点击BUG,字段显示,按钮盒,基础样式'' (#16) from fzq into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #16
2023-01-06 15:52:37 +08:00
Fanzink
3265b4a580 '修改路由点击BUG,字段显示,按钮盒,基础样式' 2023-01-06 15:44:05 +08:00
ece96e5cab Merge pull request 'fzq' (#15) from fzq into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #15
2022-12-29 13:56:05 +08:00
Fanzink
a08af6774e '更改baseTable和content样式' 2022-12-16 20:48:44 +08:00
Fanzink
3c38763cf4 Merge branch 'develop' into fzq 2022-12-13 21:01:35 +08:00
Fanzink
23b7b85b39 'update' 2022-12-13 21:00:49 +08:00
2f2eaf4e20 Merge pull request 'fzq' (#14) from fzq into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #14
2022-12-12 16:28:34 +08:00
Fanzink
a5a4f93328 'update' 2022-12-11 20:56:46 +08:00
Fanzink
f7938f30e2 'update' 2022-12-11 20:36:21 +08:00
Fanzink
d23cb260a4 '更新navbar' 2022-12-11 20:32:10 +08:00
Fanzink
e5eb49a7b6 Merge branch 'develop' into fzq 2022-12-02 16:20:45 +08:00
Fanzink
35d5d91c23 '样式修改-登录/中英文' 2022-12-02 16:19:14 +08:00
f3a7e38d13 Merge pull request 'lb' (#10) from lb into develop
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #10
2022-11-25 11:06:50 +08:00
5d36eb676c update 小修改“ 2022-11-10 15:12:23 +08:00
14b933fb0c update 安灯检测盒 2022-11-02 13:34:11 +08:00
92f52ab553 update productLine 2022-10-28 14:50:09 +08:00
15210c2f12 update 2022-10-18 14:42:48 +08:00
8447b8f7ab Merge branch 'lb' of http://git.picaiba.com/mt-fe-group/mt-yd-ui into lb 2022-10-17 16:59:11 +08:00
ca7fda73e3 update i18n 2022-10-17 16:52:07 +08:00
1617bc347a Merge pull request 'update 数据分析' (#9) from lb into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #9
2022-10-17 15:51:26 +08:00
lb
762861a922 update 数据分析 2022-10-14 14:03:00 +08:00
68c271618a Merge pull request 'lb' (#8) from lb into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #8
2022-10-09 16:58:40 +08:00
127347fab0 update 修改当前检测数据的图例配置 2022-10-09 16:57:02 +08:00
b9ac64ab13 update 2022-10-09 16:45:03 +08:00
089a6517d3 update 2022-10-09 13:16:55 +08:00
1047dd78ec update 2022-10-09 11:31:54 +08:00
5a08d8c1dd fix some bugs 2022-10-09 10:36:18 +08:00
d0f113513c fix' 设备信息编辑时提示'请输入正确的数值'的bug 2022-10-08 14:42:16 +08:00
ff11e1d3fb Merge pull request 'lb' (#7) from lb into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #7
2022-10-08 14:16:26 +08:00
b54298fe09 update 质量当前检测数据产线名字段 2022-10-08 09:57:01 +08:00
5b2de3fb27 update AddOrUpdateConfig文档 2022-10-08 09:45:00 +08:00
9c13434c48 update 设备信息 2022-10-08 08:55:17 +08:00
86d3f63178 update request.sj 2022-09-30 17:03:40 +08:00
3f43f0c979 update 设备信息新增编辑 2022-09-30 17:01:47 +08:00
ae8a3668c8 update 设备的工段绑定 2022-09-30 15:04:19 +08:00
d5af6a01f5 update 文件上传组件 2022-09-29 10:34:27 +08:00
0b54133132 update 字典管理值列表入口分离到操作列 2022-09-29 10:25:00 +08:00
246baa1768 update AttrForm详情时屏蔽操作列 2022-09-29 10:09:09 +08:00
37c0c445a3 Merge pull request 'lb' (#6) from lb into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #6
2022-09-29 09:38:36 +08:00
72f9793edf update 设备自动code 2022-09-29 09:31:43 +08:00
b7002fe17a Merge branch 'develop' into lb 2022-09-28 17:00:57 +08:00
1b670dc0ac update 设备分组报警 2022-09-28 14:24:26 +08:00
3907f5161e update 查询逻辑“ 2022-09-28 11:23:39 +08:00
d493b34a5f update table 索引“ 2022-09-28 10:58:29 +08:00
747247aed6 bug fix 2022-09-27 16:52:07 +08:00
1caf68592a update dialog 2022-09-27 15:59:35 +08:00
5d32750d87 update 实时数据“ 2022-09-27 15:52:03 +08:00
a0253cc235 add 设备历史参数 2022-09-27 15:32:38 +08:00
13df2016b9 update 实时数据刷新 2022-09-27 11:05:04 +08:00
749e503f75 Merge pull request 'lb' (#4) from lb into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #4
2022-09-26 17:03:19 +08:00
1554562933 update 2022-09-26 17:01:15 +08:00
ea1c7de4ca update 2022-09-26 16:10:44 +08:00
9b0f724da2 update 报表几处国际化 2022-09-26 14:19:09 +08:00
f33d0c9048 Merge pull request 'lb' (#3) from lb into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #3
2022-09-23 15:16:53 +08:00
4c9ce641fa Merge branch 'develop' into lb 2022-09-23 15:11:56 +08:00
31834662c9 update icon 2022-09-23 15:02:13 +08:00
4f39481693 update 基本完成设备状态时序图 2022-09-22 15:02:38 +08:00
5a45aead7c update 基本完成设备状态时序图的展示 2022-09-22 14:20:03 +08:00
31f496cc13 update 设备状态时序图产线工段关联 2022-09-22 13:25:41 +08:00
399589bb3b update 设备状态时序图 2022-09-22 11:28:27 +08:00
1ad64efe59 update 设备异常分析 2022-09-22 10:03:23 +08:00
b21d91c8da Merge pull request 'build: :新增自动构建发布脚本' (#2) from cicd into develop
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #2
2022-09-21 17:13:43 +08:00
a95a7a20d3 build: :新增自动构建发布脚本 2022-09-21 17:10:00 +08:00
7ed4a512bc update 数据分析-设备效率分析的echarts 2022-09-21 16:58:26 +08:00
9187d56f6c add 设备效率分析的图表 2022-09-21 15:30:51 +08:00
41cd01ecb0 update 设备状态时序图页面 2022-09-21 13:25:58 +08:00
f590d09671 update 设备异常分析的顶部头和表格头 2022-09-21 11:09:09 +08:00
5158d9a315 update 设备效率分析接口联调 2022-09-21 10:59:35 +08:00
cc5aa4d72f update 设备效率表格头信息 2022-09-21 10:34:40 +08:00
a03d1db029 update 设备效率分析头部 2022-09-21 10:15:53 +08:00
3999e4e589 init 数据分析“ 2022-09-20 15:59:45 +08:00
a0fef0454d Merge pull request 'lb' (#1) from lb into develop
Reviewed-on: #1
2022-09-20 14:53:16 +08:00
e532989ddf update vuecli proxy 2022-09-19 16:30:50 +08:00
10e454eb2a update 设备参数状态监控,将‘参数近期值’导向“获取设备的历史参数值”(暂未实现) 2022-09-08 15:47:08 +08:00
ce9c0f9d76 update 设备参数状态监控 2022-09-08 14:50:09 +08:00
a2423905fd add 设备当前状态页面 2022-09-08 10:46:41 +08:00
04dc0bcc49 update base-table add tooltip 2022-09-08 08:48:21 +08:00
1006ef0d6a init cell container 2022-09-07 15:10:05 +08:00
d9ff6226b3 update 产品新增-加工时间提示文字;实时数据的报错方式修改 2022-09-07 15:08:38 +08:00
08aa78fdb1 update 更新upload组件样式,更新列表的index 2022-09-07 15:04:37 +08:00
2d557c8196 update 菜单国际化 2022-09-05 12:21:06 +08:00
gtz
e020c1e174 '强制变更文件名' 2022-09-02 16:35:28 +08:00
gtz
e46c392e0f '强制变更文件名,ureport国际化文件置入' 2022-09-02 16:34:14 +08:00
076eaa5f2a update 基本完成国际化 2022-09-02 15:16:23 +08:00
12556886b9 update 2022-09-02 11:33:34 +08:00
744f288b70 update 到qualityInspectionCurrent 2022-09-02 10:59:44 +08:00
64ee3cb64e update 完成设备页面的国际化 2022-09-02 09:49:14 +08:00
268207b383 update template 2022-09-02 09:02:34 +08:00
b71a61191b update 基本完成template里的国际化 2022-09-02 09:00:22 +08:00
a438bcad2f update template part 2022-09-01 16:52:42 +08:00
5b37798a20 update 2022-09-01 15:45:13 +08:00
70303f3f06 update i18n 2022-09-01 15:01:25 +08:00
666059af6e update 基本完成按钮的权限限定 2022-09-01 13:24:00 +08:00
90a93e4f8b update permissions 2022-09-01 11:28:13 +08:00
803248ca22 add icons dialog 2022-09-01 10:18:06 +08:00
cfa1cca44a update table height 2022-09-01 09:30:44 +08:00
2df5897f3d update timeFilter 2022-09-01 09:19:14 +08:00
3668f92731 clean code 2022-09-01 09:04:45 +08:00
1b17b760ae update job-schedule 2022-09-01 08:57:10 +08:00
6e06159250 update calcTableHeight 2022-09-01 08:50:46 +08:00
3fe0d26d8f update table 2022-08-31 11:33:54 +08:00
c0900dba9c add 计算表格最大高度util 2022-08-31 11:21:35 +08:00
974079296b init i18n 2022-08-31 10:58:23 +08:00
1e78bbf6ee update 工段设备关联 2022-08-30 10:29:56 +08:00
e690c90d74 update 2022-08-29 17:02:16 +08:00
349870ce5d update 查询提示信息 2022-08-29 09:36:42 +08:00
96cea7cc0d clear files & update title 2022-08-26 11:07:57 +08:00
38afe6cbb9 update 路由隐藏 2022-08-25 13:53:28 +08:00
9df5f3b336 update“ 2022-08-24 16:29:59 +08:00
626e543fa5 update 质量实时 2022-08-23 15:07:17 +08:00
2e40570969 update 产线实时 2022-08-23 14:16:05 +08:00
70485d293c update 设备实时 2022-08-23 14:02:27 +08:00
6bbc0d3d08 update 2022-08-23 11:27:32 +08:00
8f124e06b1 add spanMethod to base-table 2022-08-23 11:11:51 +08:00
4297798d44 update realtimedata 2022-08-22 16:59:23 +08:00
9a22601f5b update BaseTable 2022-08-22 15:17:12 +08:00
69dda72fab init 厂务生产监控实时数据 2022-08-22 14:25:01 +08:00
0b4433dd80 update 基本完成报表“ 2022-08-22 11:26:57 +08:00
a30e2e1ae2 update report-detail 2022-08-22 10:28:58 +08:00
37df2abcc5 update 2022-08-19 17:02:38 +08:00
fef9bca0ae init reportSheet 2022-08-19 16:07:00 +08:00
197b4734d5 update 基本完成设备数采 2022-08-18 16:43:16 +08:00
dedcedec06 update 设备plc信息 2022-08-18 14:00:15 +08:00
93b401071a update 基本完成质量管理和基础资料 2022-08-18 10:49:27 +08:00
a15e78dcaf update attr-form 的逻辑,TODO:检查产品池和设备信息的编辑子表单 2022-08-17 17:02:58 +08:00
3c4af47e2d update 基本完成当前检测数据 2022-08-17 16:42:04 +08:00
686002a48e init charts 2022-08-17 16:00:02 +08:00
4cae583333 init base-detail-page 2022-08-17 13:55:30 +08:00
8aaaf2c7ad update 在线检测数据“ 2022-08-17 13:38:06 +08:00
56ab0220e2 add SmallTitle & 质量在线检测数据 2022-08-17 10:23:34 +08:00
8943eb56b3 update 质量检测信息记录 2022-08-17 10:22:59 +08:00
6063b664a6 update README 2022-08-16 16:47:46 +08:00
3e42b99996 update 基本完成设备信息的编辑和新增 2022-08-16 16:35:25 +08:00
f17fab4749 update 设备信息, 更新字段的验证规则 2022-08-16 16:21:35 +08:00
566c900a24 update dialog: 上传组件的格式和大小验证 2022-08-16 16:11:46 +08:00
8ad162aab6 update dialog: 多上传组件上传、下载和更新 2022-08-16 15:49:51 +08:00
3d851e4362 update dialog: 多上传组件上传成功 2022-08-16 15:01:33 +08:00
23e508916e update dialog: 多上传组件分流 2022-08-16 14:36:25 +08:00
535004719c add CKEditor & update dialog 2022-08-16 14:07:33 +08:00
51022a6e6d update 基本完成下载文件 2022-08-15 10:53:32 +08:00
b4e00bbca0 update 基本完成上传 2022-08-15 10:23:51 +08:00
a9265d6708 update 上传 2022-08-12 17:03:55 +08:00
302d1832df update 上传组件 2022-08-12 16:09:07 +08:00
00343fa5b9 init upload 2022-08-12 14:48:36 +08:00
d1dd52fe90 update 设备类型 2022-08-12 14:26:46 +08:00
04f19e82e3 update 设备分组和设备分组报警 2022-08-12 13:45:34 +08:00
19730bb635 update 2022-08-12 11:38:47 +08:00
ba44951b71 update 产线和产品 2022-08-12 09:01:44 +08:00
b3aba50b09 update 质量检测基础数据 2022-08-11 16:52:37 +08:00
3f2e8e8b9e update 产品属性表 2022-08-11 16:24:14 +08:00
db5b5091e1 update 完成厂务,优化dialog 2022-08-11 16:08:01 +08:00
0ef30e1985 update 一些视图,并且优化dialog 2022-08-11 15:31:06 +08:00
cd9beb120a update dialog 2022-08-11 14:28:06 +08:00
a1056abe80 update 2022-08-11 14:22:23 +08:00
0ddba21e1c add 添加dialog配置手册 2022-08-11 11:39:45 +08:00
535cb490b1 update subform 2022-08-11 11:18:31 +08:00
c1e152405d update 2022-08-10 17:01:51 +08:00
c435901f3b update 2022-08-10 16:49:42 +08:00
174e5efae5 update dialog 2022-08-10 16:32:27 +08:00
bc08dffda2 update 2022-08-10 15:54:41 +08:00
e91520e99d update scrollbar style 2022-08-10 15:28:19 +08:00
83fb096f6d update“ 2022-08-10 14:49:17 +08:00
90e34584ec hint DELETE接口需要加上application/json头 2022-08-10 14:12:23 +08:00
9653474e2f update 2022-08-10 13:42:46 +08:00
df3b11b6dd add common filter 2022-08-10 10:58:21 +08:00
ffd095b6b8 update 数据字典相关逻辑“ 2022-08-10 10:47:12 +08:00
559cffc5f0 update 数据字典缓存&add momentjs 2022-08-10 09:43:17 +08:00
cfec6ff3f5 finish 基本完成dialog“ 2022-08-09 16:54:45 +08:00
5d8f537d05 update 改版完成 2022-08-09 16:24:18 +08:00
669c8f90c6 update 对dialog进行改版之前 2022-08-09 16:16:34 +08:00
lb
2557026002 update 2022-08-09 10:39:33 +08:00
lb
0733660c2f update dialog 2022-08-09 09:45:59 +08:00
lb
32dd90969a update dialog 2022-08-08 17:02:57 +08:00
lb
a150905840 update dialog 2022-08-08 16:22:58 +08:00
lb
2911cf2a90 init general dialog 2022-08-08 16:22:42 +08:00
lb
e3849933d9 delete 批量删除 2022-08-08 15:19:32 +08:00
lb
c15671c496 update 产品属性、报表和质量模块的字段 2022-08-08 15:07:32 +08:00
lb
1e118a6d5d update 更新设备模块 2022-08-08 14:34:30 +08:00
lb
f415f30f9e update 更新厂务模块字段 2022-08-08 13:54:23 +08:00
lb
56bbc2497a update table 2022-08-08 13:47:56 +08:00
lb
06193447c8 update table configs 2022-08-08 13:18:17 +08:00
lb
1b760cb844 init dialog 2022-08-08 11:01:15 +08:00
lb
afc4577335 apply base-table in equipment.vue 2022-08-08 10:55:44 +08:00
lb
333da8433e update base-table 2022-08-08 10:54:23 +08:00
lb
65c4ce9d45 update base-table 2022-08-08 10:39:14 +08:00
lb
93912aa193 apply base-table 2022-08-05 17:19:31 +08:00
lb
374da7b1e9 add basetable 2022-08-05 16:03:38 +08:00
lb
43f33be189 udpate 2022-08-05 13:16:13 +08:00
lb
ee27a93181 update 生成的文件名 2022-08-05 10:57:16 +08:00
lb
8f802c5580 update PUT-POST 2022-08-05 09:35:05 +08:00
lb
cf28335d9e update 更新接口大小写,和rest格式 2022-08-05 09:25:15 +08:00
lb
4bd6ad1f47 update 2022-08-04 17:02:22 +08:00
lb
b79efe0a19 format 2022-08-04 16:25:49 +08:00
lb
ffad1a2643 update 2022-08-04 16:20:07 +08:00
lb
affea8af59 update axios response的解析 2022-08-04 16:15:52 +08:00
lb
8b060b8bf1 add prettierrc & 一些全局替换 2022-08-04 15:42:36 +08:00
lb
d4e7bda03b 替换hasPermission 2022-08-04 15:12:26 +08:00
lb
3df2939fb4 update list response 2022-08-04 14:41:47 +08:00
lb
d3752c4f40 update request.js & routes 2022-08-04 13:45:49 +08:00
lb
0566808861 add comments 2022-08-02 17:06:11 +08:00
195 changed files with 25127 additions and 2827 deletions

7
.dockerignore Normal file
View File

@ -0,0 +1,7 @@
.vscode/
.idea/
node_modules/
dist/
**/*.log
LICENSE
README.md

52
.drone.yml Normal file
View File

@ -0,0 +1,52 @@
---
kind: pipeline
type: docker
name: default
steps:
- name: build
image: docker:dind
volumes:
- name: dockersock
path: /var/run/docker.sock
- name: dockerconfig
path: /root/.docker
commands:
- docker build -t harbor.picaiba.com/kszny/mes-ui:1.0.0-india ./ && docker push harbor.picaiba.com/kszny/mes-ui:1.0.0-india
- name: deploy
image: harbor.picaiba.com/tools/kubectl:1.19.8
commands:
- echo "172.27.0.20 lb.kubesphere.local" >> /etc/hosts
#- echo "52.74.223.119 github.com" >> /etc/hosts
- sleep 1
- kubectl scale --replicas=0 deployment/mes-ui -n mes-india
- sleep 3
- kubectl scale --replicas=1 deployment/mes-ui -n mes-india
depends_on:
- build
- name: notification
image: lddsb/drone-dingtalk-message
settings:
token: 37a6483274f6de648a26d6710e4d8160eb7d471752abb2d70f8b7958af58fe11
type: markdown
secret: SEC83b10f5fefd6127e4073360d4447bb7276a90386aeee1275b2797dd377a903e7
tpl: http://res.picaiba.com/msg/msg.md
tips_title: 你有新消息
success_color: 008800
failure_color: FF0000
volumes:
- name: dockersock
host:
path: /var/run/docker.sock
- name: dockerconfig
host:
path: /root/.docker
trigger:
branch:
- develop
event:
- push

12
.prettierrc Normal file
View File

@ -0,0 +1,12 @@
{
"singleQuote": true,
"tabWidth": 2,
"bracketSameLine": true,
"jsxBracketSameLine": true,
"embeddedLanguageFormatting": "auto",
"printWidth": 180,
"quoteProps": "consistent",
"trailingComma": "none",
"semi": false,
"useTabs": true
}

244
AddOrUpdateConfig.md Normal file
View File

@ -0,0 +1,244 @@
# Add Or Update Dialog Configs
> 通过传入合理的配置项来使用 addOrUpdate Dialog
## 用途
通过给对话框传递配置项,并自动根据这些配置项来初始化对话框的功能
## props
- configs 对象
```
<my-dialog :configs="SomeConfigs" ... />
type Operation = {
name: 'add' | 'edit' | 'detail' | 'delete' | ...,
url: string, /** 该操作需要的接口地址,如删除接口 */
showAlways: boolean,
showOnEdit: boolean,
permission: string,
}
type SubTableConfig = {
[_:string]: any,
title: string, /** 表格的名称 */
url: string, /** 涉及的接口 */
tableConfigs: {
[_:string]: any,
type?: 'index' | ...,
prop: string,
name: string,
rules?: any[],
fixed?: string,
width?: string,
subcomponent: VueComponent,
options: any[],
formField: boolean, /** 是否在新增编辑子表单里出现该字段 */
}[], /** 表格prop配置数组参考 components/base-table 组件和 element-ui 文档 */
}
type ExtraComponent = {
name: string,
label: string,
hasModel: boolean, /** 是否需要为该组件设置 v-model */
component: VueComponent, /** 动态加载的 vue 组件 */
props: {
[_:string]: string | object
extraParams?: { /** 上传组件使用 */
typeCode: string
}
}[]
}
type Field = {
[_:string]: string | boolean | object | object[],
name: string,
type?: 'input' | 'select' | ...,
options?: any[], /** 设置 type 为 select 时的选项数据 */
label?: string, /** 没有时会用 name 替代 */
placeholder?: string, /** 没有时会生成默认占位符 */
api?: string, /** 如果有该字段就自动从api地址获取数据并填充到对应的输入框里一般为 getCode 的接口 */
relatedField?: string, /** 关联字段,当设置此字段时,意味着需要在对话框组件上监听 select-change 事件,并当该字段数据被改变时刷新 relatedField 的列表,一般是像选择产线时更新工段列表这样的场景使用 */,
required?: boolean, /** 验证规则的简写,只需要限制必填项时,不需要其他验证规则时使用 */
rules?: object[], /** 规则设置参考 element-ui 的表单验证配置 */
}
type Configs = {
type: 'dialog',
infoUrl: string, /** 编辑时获取信息的接口地址 */
fields: Field[],
extraComponents?: ExtraComponent[],
subtable?: SubTableConfig[],
operations?: Operation[]
}
```
## 示例
```js
const addOrUpdateConfigs = {
type: 'dialog', // dialog | drawer | page
infoUrl: '/monitoring/product',
fields: [
'name',
{
name: 'code',
api: '/monitoring/product/getCode'
},
{
name: 'processTime',
label: '加工时间',
placeholder: '请输入加工时间',
type: 'number', // type: number(input+number) | default(input) | textarea | select(options在父组件里获取) | datetime
required: true,
rules: [
// 除了required之外的验证规则
{
type: 'number',
trigger: 'blur',
transform: val => Number(val),
message: '必须输入数字'
}
]
},
'remark',
'specifications',
{
name: 'typeDictValue',
rules: [{ required: true, trigger: 'blur' }],
label: '产品类型', // 对于非常见属性最好自己指定label
type: 'select',
options: [
// 动态获取
]
},
{
name: 'unitDictValue',
label: '单位',
type: 'select',
placeholder: '请选择单位',
options: [
// 动态获取
]
}
],
operations: [
// { name: 'reset', url: true },
{ name: 'cancel', url: true, showAlways: true },
{ name: 'save', url: '/monitoring/product', permission: '', showOnEdit: false },
{ name: 'update', url: '/monitoring/product', permission: '', showOnEdit: true }
],
subtable: {
// for i18n
title: '动态属性',
url: '/monitoring/productArrt',
tableConfigs: [
{ type: 'index', name: '序号' },
{ prop: 'createTime', name: '添加时间', filter: val => (val ? moment(val).format('YYYY-MM-DD hh:mm:ss') : '-') },
{ prop: 'name', name: '属性名', formField: true, rules: [{ required: true, message: '必填', trigger: 'blur' }] },
{ prop: 'code', name: '属性值', formField: true },
{ prop: 'operations', name: '操作', fixed: 'right', width: 180, subcomponent: TableOperateComponent, options: ['edit', 'delete'] }
]
},
extraComponents: [
{
name: 'CompName',
label: 'markdown编辑器',
component: () => import('xx.vue')
}
]
}
```
## 配置项解释
<br>
### type
类型: string
dialog | drawer | page
含义:对话框、抽屉、新页面
### infoUrl
类型string
含义:详情的接口,如 `/monitoring/product`
### fields
含义:设置新增、编辑时的字段
类型:`Array<string | object>`
- 当类型为 string 时,默认渲染 `<input>`
- 当类型为 object 时,有如下选项:
- name: 字段名
- label: 字段的 label
- api: 如果设置了该属性,则该字段会自动从服务器获取值,一般为 code 字段需要
- placeholder
- type: 渲染何种类型的组件,默认值: 'input'
- options: 当上一条 type 值为 'select' 时,需要自行动态获取并加载 options 列表
- required: 是否是必须填写的字段(或可用过 rules 做更加具体的设定,设定方式参考 async-validator
- rules: 验证规则数组,如果只有"必填"的需求,可直接用上一条
### operations
含义:设置对话框等组件里,需要哪些按钮
类型:`Array<object>`
属性:
- name按钮的类型决定按钮的文字和颜色
- url按钮操作的接口地址不需要的可以给 null 或 true
- permission该操作需要的权限如 "sys:xxx:add" 形式
- showOnEdit: boolean是否编辑页面展示不设置则始终展示
示例:
```js
operations: [
{ name: 'reset', url: true },
{ name: 'cancel', url: true, showAlways: true },
{ name: 'save', url: '/monitoring/product', permission: '', showOnEdit: false },
{ name: 'update', url: '/monitoring/product', permission: '', showOnEdit: true }
],
```
### subtable
含义:有些对话框里需要额外的表格来展示更深层次的数据,如“产品属性”
类型object
选项:
- title, 内嵌表格的标题
- url, 内嵌表格的数据地址
- tableConfigs内嵌表格的配置选项
- 类型:`Array<object>`
- 配置:
- type: 同 element-ui 的 table 属性的 type
- fixed: 同 element-ui 的 table 属性的 fixed
- width: 同 element-ui 的 table 属性的 width
- name: 表头显示的内容
- filter: 一般用于转换时间
- prop: 字段
- formField: boolean, 是否用于表单的填写
- rules: 表单验证规则详见async-validator
- subcomponent: 同 base-table 的 subcomponent
- options: 表格操作列需要哪些操作
- 值:`edit` | `delete` | `detail`,需要其他可自行添加(修改 base-table 组件)
### extraComponents
含义: 需要在对话框里使用的自定义组件列表
类型: Array<object>
对象选项:
- name: 该组件对应的 dataForm 字段(需要参照后端文档来指定)
- hasModel: boolean, 上传组件一般设置为 false设置是否和 dataForm 关联
- label
- fieldType: 设置该组件的数据将以什么数据类型形式来保存
- component: 组件
- props 传给组件的配置

10
Dockerfile Normal file
View File

@ -0,0 +1,10 @@
FROM node:12 AS builder
WORKDIR /app
ADD package.json /app/
RUN npm config set registry https://registry.npmmirror.com && npm install
ADD . /app
RUN npm run build:prod
FROM busybox
LABEL maintainer thomas.hairong@gmail.com
COPY --from=builder /app/dist /html

7
TODO.md Normal file
View File

@ -0,0 +1,7 @@
# TODO List
1. 按钮加权限
2. 国际化
3. 表格高度 √
4. 表格时间格式修改 √
5. icon列表 √

55
package-lock.json generated
View File

@ -2603,6 +2603,12 @@
"resolved": "https://registry.npm.taobao.org/@types/json-schema/download/@types/json-schema-7.0.5.tgz",
"integrity": "sha1-3M5EMOZLRDuolF8CkPtWStW6xt0="
},
"@types/lodash": {
"version": "4.14.182",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz",
"integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==",
"dev": true
},
"@types/minimatch": {
"version": "3.0.3",
"resolved": "https://registry.npm.taobao.org/@types/minimatch/download/@types/minimatch-3.0.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fminimatch%2Fdownload%2F%40types%2Fminimatch-3.0.3.tgz",
@ -5277,6 +5283,19 @@
"safe-buffer": "^5.0.1"
}
},
"ckeditor4-integrations-common": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/ckeditor4-integrations-common/-/ckeditor4-integrations-common-1.0.0.tgz",
"integrity": "sha512-OAoQT/gYrHkg0qgzf6MS/rndYhq3SScLVQ3rtXQeuCE8ju7nFHg3qZ7WGA2XpFxcZzsMP6hhugXqdel5vbcC3g=="
},
"ckeditor4-vue": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ckeditor4-vue/-/ckeditor4-vue-2.1.1.tgz",
"integrity": "sha512-BBmpT1BYxOmaA+qy9+hvhG0tDYCGqFve1eDSol0ZNwWCm1hZvmPAke809AhkHFUjb834dbNRlTwH3c2qedjtkQ==",
"requires": {
"ckeditor4-integrations-common": "^1.0.0"
}
},
"class-utils": {
"version": "0.3.6",
"resolved": "https://registry.npm.taobao.org/class-utils/download/class-utils-0.3.6.tgz",
@ -7101,6 +7120,22 @@
"safer-buffer": "^2.1.0"
}
},
"echarts": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/echarts/-/echarts-5.3.3.tgz",
"integrity": "sha512-BRw2serInRwO5SIwRviZ6Xgm5Lb7irgz+sLiFMmy/HOaf4SQ+7oYqxKzRHAKp4xHQ05AuHw1xvoQWJjDQq/FGw==",
"requires": {
"tslib": "2.3.0",
"zrender": "5.3.2"
},
"dependencies": {
"tslib": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
}
}
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz",
@ -10942,6 +10977,11 @@
"minimist": "^1.2.5"
}
},
"moment": {
"version": "2.29.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
},
"move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npm.taobao.org/move-concurrently/download/move-concurrently-1.0.1.tgz",
@ -17245,6 +17285,21 @@
"integrity": "sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA="
}
}
},
"zrender": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/zrender/-/zrender-5.3.2.tgz",
"integrity": "sha512-8IiYdfwHj2rx0UeIGZGGU4WEVSDEdeVCaIg/fomejg1Xu6OifAL1GVzIPHg2D+MyUkbNgPWji90t0a8IDk+39w==",
"requires": {
"tslib": "2.3.0"
},
"dependencies": {
"tslib": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
}
}
}
}
}

View File

@ -3,7 +3,8 @@
"version": "5.0.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"serve": "vue-cli-service serve --mode production",
"serve:dev": "vue-cli-service serve --mode development",
"build": "vue-cli-service build",
"build:prod": "vue-cli-service build --mode production",
"build:sit": "vue-cli-service build --mode production.sit",
@ -13,14 +14,17 @@
"axios": "^0.19.2",
"babel-eslint": "^8.0.1",
"babel-plugin-component": "^1.1.1",
"ckeditor4-vue": "^2.1.1",
"core-js": "^3.6.5",
"echarts": "^5.3.3",
"element-theme": "^2.0.1",
"element-ui": "^2.15.7",
"js-cookie": "^2.2.1",
"lodash": "^4.17.19",
"sass": "^1.26.5",
"moment": "^2.29.4",
"qs": "^6.9.4",
"quill": "^1.3.7",
"sass": "^1.26.5",
"sass-loader": "^9.0.2",
"screenfull": "^4.2.1",
"svg-sprite-loader": "^5.0.0",
@ -31,6 +35,7 @@
"vuex": "^3.5.1"
},
"devDependencies": {
"@types/lodash": "^4.14.182",
"@vue/cli-plugin-babel": "^4.4.6",
"@vue/cli-service": "^4.4.6",
"element-theme-chalk": "^2.15.7",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 24 KiB

BIN
public/favicon2.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
public/google.exe Normal file

Binary file not shown.

41
public/i18n.js Normal file
View File

@ -0,0 +1,41 @@
/*
* @Descripttion:
* @version:
* @Author: fzq
* @Date: 2022-11-25 09:51:46
* @LastEditors: fzq
* @LastEditTime: 2023-01-30 14:26:02
*/
/**
* Created by Jacky.Gao on 2017-10-01.
*/
import defaultI18nJsonData from './designer.json';
import en18nJsonData from './designer_en.json';
// export default function buildLocal () {
// let language = getCookie('language') || 'zh-CN';
// window.i18n = defaultI18nJsonData;
// if (language !== 'zh-CN') {
// window.i18n = en18nJsonData;
// }
// }
export default function buildLocal () {
let language = getCookie('language') || 'en';
window.i18n = defaultI18nJsonData;
if (language !== 'en') {
window.i18n = en18nJsonData;
}
}
function getCookie (name) {
var strcookie = document.cookie;//获取cookie字符串
var arrcookie = strcookie.split("; ");//分割
//遍历匹配
for (var i = 0; i < arrcookie.length; i++) {
var arr = arrcookie[i].split("=");
if (arr[0] == name){
return arr[1];
}
}
return "";
}

View File

@ -1,3 +1,11 @@
<!--
* @Descripttion:
* @version:
* @Author: fzq
* @Date: 2022-11-25 09:51:46
* @LastEditors: fzq
* @LastEditTime: 2023-02-09 14:40:52
-->
<!DOCTYPE html>
<html>
<head>
@ -10,6 +18,7 @@
window.SITE_CONFIG['version'] = 'v5.0.0';
window.SITE_CONFIG['nodeEnv'] = '<%= process.env.VUE_APP_NODE_ENV %>';
window.SITE_CONFIG['apiURL'] = ''; // api请求地址
window.SITE_CONFIG['projURL'] = ''; // api请求地址
window.SITE_CONFIG['storeState'] = {}; // vuex本地储存初始化状态用于不刷新页面的情况下也能重置初始化项目中所有状态
window.SITE_CONFIG['contentTabDefault'] = { // 内容标签页默认属性对象
'name': '', // 名称, 由 this.$route.name 自动赋值(默认,名称 === 路由名称 === 路由路径)
@ -30,25 +39,26 @@
<!-- 开发环境 -->
<% if (process.env.VUE_APP_NODE_ENV === 'dev') { %>
<script>
window.SITE_CONFIG['apiURL'] = 'http://localhost:8080/renren-admin';
// window.SITE_CONFIG['apiURL'] = 'http://192.168.1.8';
window.SITE_CONFIG['apiURL'] = 'http://india.mes.picaiba.com/';
</script>
<% } %>
<!-- 集成测试环境 -->
<% if (process.env.VUE_APP_NODE_ENV === 'prod:sit') { %>
<script>
window.SITE_CONFIG['apiURL'] = 'http://localhost:8080/renren-admin';
window.SITE_CONFIG['apiURL'] = 'http://india.mes.picaiba.com/';
</script>
<% } %>
<!-- 验收测试环境 -->
<% if (process.env.VUE_APP_NODE_ENV === 'prod:uat') { %>
<script>
window.SITE_CONFIG['apiURL'] = 'http://localhost:8080/renren-admin';
window.SITE_CONFIG['apiURL'] = 'http://india.mes.picaiba.com/';
</script>
<% } %>
<!-- 生产环境 -->
<% if (process.env.VUE_APP_NODE_ENV === 'prod') { %>
<script>
window.SITE_CONFIG['apiURL'] = 'http://localhost:8080/renren-admin';
window.SITE_CONFIG['apiURL'] = 'http://india.mes.picaiba.com/';
</script>
<% } %>
</head>

View File

@ -1,34 +1,47 @@
<!--
* @Descripttion:
* @version:
* @Author: fzq
* @Date: 2022-11-25 09:51:46
* @LastEditors: fzq
* @LastEditTime: 2023-01-13 15:13:05
-->
<template>
<transition name="el-fade-in-linear">
<router-view />
</transition>
<transition name="el-fade-in-linear" id="app">
<router-view />
</transition>
</template>
<style>
.el-table th.gutter{
display: table-cell!important;
}
.el-table th.gutter {
display: table-cell !important;
}
#app {
background-color: #f2f4f9;
}
</style>
<script>
import Cookies from 'js-cookie'
import { messages } from '@/i18n'
// import { messages } from '@/i18n'
export default {
watch: {
'$i18n.locale': 'i18nHandle'
},
created () {
this.i18nHandle(this.$i18n.locale)
},
methods: {
i18nHandle (val, oldVal) {
Cookies.set('language', val)
document.querySelector('html').setAttribute('lang', val)
document.title = messages[val].brand.lg
//
if (this.$route.name !== 'login' && oldVal) {
window.location.reload()
}
}
}
watch: {
'$i18n.locale': 'i18nHandle'
},
created() {
this.i18nHandle(this.$i18n.locale)
},
methods: {
i18nHandle(val, oldVal) {
Cookies.set('language', val)
document.querySelector('html').setAttribute('lang', val)
//
// document.title = messages[val].brand.lg
//
if (this.$route.name !== 'login' && oldVal) {
window.location.reload()
}
}
}
}
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
src/assets/img/cnbm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
src/assets/img/login.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 MiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
src/assets/img/logo2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
src/assets/img/logo3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

BIN
src/assets/img/logo@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
src/assets/img/logo@4x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -5,6 +5,8 @@
}
body {
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
// font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
// font-family: Avenir,Helvetica Neue,Arial,Helvetica,sans-serif;
font-size: $--font-size-base;
line-height: $base--line-height;
color: $--color-text-primary;
@ -15,8 +17,8 @@ a {
text-decoration: none;
&:focus,
&:hover {
color: $--color-primary;
text-decoration: underline;
color: #fff;
// text-decoration: underline;
}
}
img {
@ -217,6 +219,17 @@ img {
&__brand {
&-lg {
display: none;
// margin: 0;
// color: #fff;
// width: 189px;
// overflow: hidden;
// text-overflow: ellipsis;
// white-space: nowrap;
// font-weight: 500;
// line-height: 50px;
// font-size: 14px;
// font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
// vertical-align: middle;
}
&-mini {
display: inline-block;
@ -241,10 +254,14 @@ img {
margin-right: 0;
font-size: 18px;
}
&__close {
width: 0px;
}
}
.aui-content {
&__wrapper {
margin-left: $sidebar--width-fold;
background-color: #F2F4F9;
}
&--tabs > .el-tabs > .el-tabs__header {
left: $sidebar--width-fold;
@ -265,10 +282,24 @@ img {
align-items: stretch;
height: $navbar--height;
background-color: $--color-primary;
box-shadow: 0 1px 0 0 rgba(0, 0, 0, .05);
box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.05);
.home {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: 1030;
display: flex;
align-items: stretch;
height: $navbar--height;
background-color: #0b58ff;
box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.05);
}
&--colorful {
.aui-navbar__body {
// navbar body颜色
background-color: transparent;
// background-color: #304156;
}
.aui-navbar__menu {
> .el-menu-item,
@ -278,6 +309,7 @@ img {
&:hover {
color: #fff;
background-color: mix(#000, $--color-primary, 15%);
// background-color: #001528;
}
}
> .el-menu-item.is-active,
@ -285,7 +317,7 @@ img {
color: #fff;
&:focus,
&:hover {
color: #fff;
color: #263445;
}
}
.el-menu-item i,
@ -332,7 +364,18 @@ img {
color: #fff;
overflow: hidden;
transition: width .3s;
&-lg,
&-lg {
width: 238px;
height: 100%;
font-size: 18px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #FFFFFF;
line-height: 20px;
margin-top: 14px;
// 新加的
margin-left: 10px;
}
&-mini {
max-width: 100%;
color: #fff;
@ -370,10 +413,15 @@ img {
}
.el-menu-item.is-active,
.el-submenu.is-active > .el-submenu__title {
// 点击之后背景颜色
color: $--color-text-secondary;
// background-color: rgb(13,43,104);
&:focus,
&:hover {
// 点击之后图标颜色亮度
color: $--color-text-primary;
// color: #fff;
// background-color: rgb(13,43,104);
}
}
.el-menu-item {
@ -381,6 +429,7 @@ img {
&:hover {
.aui-navbar__icon-menu {
color: $--color-text-primary;
// color: #fff;
}
.el-dropdown {
color: $--color-text-primary;
@ -392,9 +441,10 @@ img {
* {
vertical-align: initial;
}
//
.aui-navbar__icon-menu {
vertical-align: middle;
font-size: 16px;
font-size: 22px;
}
.el-dropdown {
color: $--color-text-secondary;
@ -463,7 +513,8 @@ img {
bottom: 0;
z-index: 1020;
width: $sidebar--width;
background-color: #fff;
// background-color: #fff;
background-color:#304156;
box-shadow: 1px 0 2px 0 rgba(0, 0, 0, .05);
overflow: hidden;
transition: width .3s;
@ -471,23 +522,29 @@ img {
background-color: $sidebar--background-color-dark;
.aui-sidebar__menu,
> .el-menu--popup {
background-color: $sidebar--background-color-dark;
// background-color: $sidebar--background-color-dark;
background-color: #304156;;
.el-menu-item,
.el-submenu > .el-submenu__title {
color: $sidebar--text-color-dark;
// color: $sidebar--text-color-dark;
color: #f4f4f5;
&:focus,
&:hover {
color: mix(#fff, $sidebar--text-color-dark, 50%);
background-color: mix(#fff, $sidebar--background-color-dark, 2.5%);
// background-color: mix(#fff, $sidebar--background-color-dark, 2.5%);
background-color:#0B253F;
}
}
.el-menu,
.el-submenu.is-opened {
background-color: mix(#000, $sidebar--background-color-dark, 15%);
// background-color: mix(#000, $sidebar--background-color-dark, 15%);
background-color:#0B253F;
}
.el-menu-item.is-active,
.el-submenu.is-active > .el-submenu__title {
color: mix(#fff, $sidebar--text-color-dark, 80%);
// color: mix(#fff, $sidebar--text-color-dark, 80%);
// color: #409EFF;
color: #0B58FF;
}
}
}
@ -501,6 +558,10 @@ img {
overflow-y: scroll;
transition: width .3s;
}
.close {
width: 0px;
margin-left: 0 !important;
}
&__menu {
width: $sidebar--width;
border-right: 0;
@ -527,14 +588,21 @@ img {
/* Content
------------------------------ */
.aui-content {
position: relative;
padding: $content--padding;
min-height: calc(100vh - #{$navbar--height});
top: 16px;
margin:0 16px 0;
background-color: #fff;
border-radius: 4px;
padding: 16px 16px 0;
//此处修底部高度
height: calc(100vh - 85px);
overflow: auto;
&__wrapper {
position: relative;
// 注释掉可隐藏侧边栏,但需要在main.vue中加入main-content的限制条件
margin-left: $sidebar--width;
min-height: calc(100vh - #{$navbar--height});
background-color: $content--background-color;
//此处修改背景色
background-color: #F2F4F9;
transition: margin-left .3s;
}
> .aui-card--fill > .el-card__body {

View File

@ -1,6 +1,7 @@
.mod-home {
table {
width: 100%;
height: 10px;
border: 1px solid $--border-color-lighter;
border-collapse: collapse;
th,

View File

@ -5,15 +5,19 @@ $base--line-height: 1.15;
$navbar--height: 50px;
// Sidebar
$sidebar--width: 230px;
// $sidebar--width: 300px;
$sidebar--width: 248px;
$sidebar--width-fold: 64px;
$sidebar--background-color-dark: #263238;
// $sidebar--background-color-dark: #263238;
// $sidebar--background-color-dark: #001529;
$sidebar--background-color-dark: #304156;
$sidebar--text-color-dark: #8a979e;
$sidebar--menu-item-height: 48px;
// Content
$content--padding: 15px;
$content--background-color: #f1f4f5;
// $content--background-color: #f1f4f5;
$content--background-color: #fff;
$content--card-header-height: 60px;
$content--tabs-header-height: 38px;
// Content, 填充整屏高度(非tabs状态) = 整屏高度 - 导航条高度 - aui-content上下内边距高度

View File

@ -0,0 +1,93 @@
<!--
* @Author: your name
* @Date: 2021-01-27 10:07:42
* @LastEditTime: 2021-01-28 16:26:15
* @LastEditors: gtz
* @Description: In User Settings Edit
* @FilePath: \mt-bus-fe\src\components\Breadcrumb\index.vue
-->
<template>
<el-breadcrumb class="app-breadcrumb" separator="/">
<transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
<span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="isredirect">{{ item.meta.title }}</span>
<span v-else class="no-redirect">{{ item.meta.title }}</span>
<!-- @click.prevent="handleLink(item)" -->
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</template>
<script>
import pathToRegexp from 'path-to-regexp'
export default {
data() {
return {
levelList: null
}
},
watch: {
$route(route) {
// if you go to the redirect page, do not update the breadcrumbs
if (route.path.startsWith('/redirect/')) {
return
}
this.getBreadcrumb()
}
},
created() {
this.getBreadcrumb()
},
methods: {
getBreadcrumb() {
// only show routes with meta.title
const matched = this.$route.matched.filter(item => item.meta && item.meta.title)
// const first = matched[0]
// if (!this.isDashboard(first)) {
// matched = [{ path: '/dashboard', meta: { title: 'Dashboard' }}].concat(matched)
// }
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
},
isDashboard(route) {
const name = route && route.name
if (!name) {
return false
}
return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
},
pathCompile(path) {
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
const { params } = this.$route
var toPath = pathToRegexp.compile(path)
return toPath(params)
},
handleLink(item) {
const { redirect, path } = item
if (redirect) {
this.$router.push(redirect)
return
}
this.$router.push(this.pathCompile(path))
}
}
}
</script>
<style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
display: inline-block;
font-size: 14px;
line-height: 48px;
margin-left: 8px;
.isredirect {
color: rgba(0, 0, 0, 0.65);
}
.no-redirect {
color: #8C8C8C;
cursor: text;
}
}
</style>

View File

@ -0,0 +1,35 @@
<template>
<div style="padding: 5px 15px 5px 32px;" @click="toggleClick">
<svg-icon style="width: 24px; height: 24px" class="item-icon hamburger" :class="{'is-active':isActive}" icon-class="hamburgerBtn" />
</div>
</template>
<script>
export default {
name: 'Hamburger',
props: {
isActive: {
type: Boolean,
default: false
}
},
methods: {
toggleClick() {
this.$emit('toggleClick')
}
}
}
</script>
<style scoped>
.hamburger {
display: inline-block;
vertical-align: middle;
width: 20px;
height: 20px;
}
.hamburger.is-active {
transform: rotate(180deg);
}
</style>

View File

@ -0,0 +1,62 @@
<template>
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
import { isExternal } from '@/utils/validate'
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
isExternal() {
return isExternal(this.iconClass)
},
iconName() {
return `#icon-${this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
},
styleExternalIcon() {
return {
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
}
}
}
}
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover!important;
display: inline-block;
}
</style>

View File

@ -0,0 +1,548 @@
<template>
<div class="super-flexible-dialog" :title="isDetail ? title.detail : !dataForm.id ? title.add : title.edit" @close="handleClose">
<div style="max-height: 60vh; overflow-y: scroll; overflow-x: hidden;">
<el-form ref="dataForm" :model="dataForm" :rules="dataFormRules">
<!-- 如果需要更精细一点的布局可以根据配置项实现地再复杂一点但此处暂时全部采用一行两列布局 -->
<el-row v-for="n in rows" :key="n" :gutter="20">
<el-col v-for="c in COLUMN_PER_ROW" :key="`${n}+'col'+${c}`" :span="getSpan(n, c)">
<!-- <el-col v-for="c in COLUMN_PER_ROW" :key="`${n}+'col'+${c}`" :span="24 / COLUMN_PER_ROW"> -->
<!-- :class="{ 'hidden-input': configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].hidden }" -->
<el-form-item
v-if="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)]"
:prop="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name"
:key="`${n}-col-${c}-item`"
:label="getLabel(n, c)"
>
<!-- 暂时先不实现部分输入方式 -->
<el-input
v-if="getType(n, c) === 'input'"
:placeholder="getPlaceholder(n, c)"
v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
clearable
/>
<el-radio v-if="getType(n, c) === 'radio'" v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"></el-radio>
<el-checkbox v-if="getType(n, c) === 'check'" v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"></el-checkbox>
<el-select
v-if="getType(n, c) === 'select'"
:placeholder="getPlaceholder(n, c)"
v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
clearable
@change="emitSelectChange(configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name, $event)"
>
<el-option v-for="opt in configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].options" :key="opt.label" :label="opt.label" :value="opt.value" />
</el-select>
<el-switch v-if="getType(n, c) === 'switch'" v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"></el-switch>
<el-cascader
v-if="getType(n, c) === 'cascader'"
v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
:options="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].options"
:props="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].props"
></el-cascader>
<el-time-select v-if="getType(n, c) === 'time'" v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"></el-time-select>
<el-date-picker
v-if="getType(n, c) === 'date'"
v-bind="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].props"
:placeholder="getPlaceholder(n, c)"
v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
></el-date-picker>
</el-form-item>
</el-col>
</el-row>
<!-- extra components , like Markdown or RichEdit -->
<template v-if="configs.extraComponents && configs.extraComponents.length > 0">
<el-form-item v-for="(ec, index) in configs.extraComponents" :key="ec.name + index" :label="ec.label" class="extra-components">
<component style="margin-top: 40px;" v-if="ec.hasModel" :is="ec.component" v-bind="ec.props" v-model="dataForm[ec.name]" @ready="handleEditorReady" />
<!-- <component v-if="ec.hasModel" :is="ec.component" v-bind="ec.props" v-model="dataForm[ec.name]" /> -->
<component
v-else
:is="ec.component"
v-bind="ec.props"
@uploader-update-filelist="handleUploadListUpdate($event, ec.props.extraParams.typeCode)"
:uploader-inject-file-list="/*用于设备分流的*/ fileList[ec.props.extraParams.typeCode]"
/>
</el-form-item>
</template>
</el-form>
<template v-if="dataForm.id && configs.subtable">
<attr-form :pId="dataForm.id" v-bind="configs.subtable" />
</template>
</div>
<span slot="footer" class="dialog-footer">
<template v-for="(operate, index) in configs.operations">
<!-- {{ operate.name | btnNameFilter }} -->
<el-button
v-if="
operate.showAlways ||
(((dataForm.id && operate.showOnEdit) || (!dataForm.id && !operate.showOnEdit)) && (operate.permission ? $hasPermission(operate.permission) : true))
"
:key="`operate-${index}`"
:type="btnType[operate.name]"
@click="handleClick(operate)"
>{{ btnName[operate.name] }}</el-button
>
</template>
</span>
</div>
</template>
<script>
import AttrForm from '../AttrForm'
import { pick } from 'lodash/object'
// for i18n
const title = {
detail: i18n.t('detail'),
add: i18n.t('add'),
edit: '编辑'
}
//
const btnType = {
save: 'success',
update: 'primary',
reset: 'text'
// cancel: 'text'
// add more...
}
const btnName = {
// for i18n
save: '保存',
update: '更新',
reset: '重置',
cancel: i18n.t('cancel')
// add more...
}
//
const COLUMN_PER_ROW = 2
export default {
name: 'AddOrUpdateDialog',
components: { AttrForm },
props: {
configs: {
/**
* TODO: 定义及使用方式应改用README.md文件记录
* type: 'dialog' | 'drawer' | 'page'
* fields: Array<string|object>
* - fields.object: { name, type: 'number'|'textarea'|'select'|'date'|.., required: boolean, validator: boolean(是否需要验证), [options]: any[], api: string(自动获取数据的接口一般为getcode接口)}
* operations: Array[object], 操作名和对应的接口地址还有permission(sys:dict:update)
*/
type: Object,
default: () => ({}) // 使
}
},
filters: {
nameFilter: function(name) {
if (!name) return null
// for i18n
const defaultNames = {
name: i18n.t('name'),
code: i18n.t('code'),
remark: i18n.t('remark'),
description: i18n.t('desc'),
specifications: i18n.t('prod.spec')
// add more...
}
return defaultNames[name]
}
},
// provide() {
// return {
// _df: this.dataForm
// }
// },
data() {
return {
COLUMN_PER_ROW,
title,
/** 按钮相关属性 */
btnName,
btnType,
defaultNames: {
name: i18n.t('name'),
code: i18n.t('code'),
remark: i18n.t('remark'),
description: i18n.t('desc'),
specifications: i18n.t('prod.spec')
// add more...
},
defaultPlaceholders: {}, // defaultNames
/** 表单相关属性 */
visible: false,
isEdit: false,
isDetail: false,
dataForm: {},
dataFormRules: {},
tempForm: [], // code
shouldWait: null,
fileForm: {}, // typeCode
fileList: {} // typeCode
}
},
computed: {
rows() {
// ''
return Math.ceil(this.configs.fields.length / COLUMN_PER_ROW)
}
},
mounted() {
/** 计算 defaultPlaceholders */
const prefix = '请输入'
Object.entries(this.defaultNames).map(([key, value]) => {
this.defaultPlaceholders[key] = prefix + value
})
/** 转换 configs.fields 的结构,把纯字符串转为对象 */
this.$nextTick(() => {
this.configs.fields = this.configs.fields.map(item => {
if (typeof item === 'string') {
return { name: item }
}
return item
})
/** 动态设置dataForm字段 */
this.configs.fields.forEach(item => {
this.$set(this.dataForm, [item.name], '')
/** select 的默认值设置 */
if (item.type === 'select') {
const opts = item.options || []
const dft = opts.find(item => item.default || false)
if (dft) {
this.$set(this.dataForm, [item.name], dft.value)
}
}
if (item.api) {
/** 自动请求并填充 */
// or this.shouldWaitPool = []
this.shouldWait = this.$http({
url: this.$http.adornUrl(item.api),
method: 'POST' //
}).then(({ data: res }) => {
if (res && res.code === 0) {
// this.dataForm[item.name] = res.data // <===
this.tempForm.push({ name: item.name, data: res.data })
}
})
} // end if (item.api)
if (item.required) {
const requiredRule = {
required: true,
message: '请输入必填项',
trigger: 'change'
}
/** 检查是否已经存在该字段的规则 */
const exists = this.dataFormRules[item.name] || null
/** 设置验证规则 */
if (exists) {
const unset = true
for (const rule of exists) {
if (rule.required) unset = false
}
if (unset) {
exists.push(requiredRule)
}
} else {
/** 不存在已有规则 */
this.$set(this.dataFormRules, [item.name], [requiredRule])
}
} // end if (item.required)
if (item.rules) {
const exists = this.dataFormRules[item.name] || null
if (exists) {
//
exists.push(...item.rules)
} else {
this.$set(this.dataFormRules, [item.name], [...item.rules])
}
} // end if (item.rules)
})
/** 计算默认值 */
function calDefault(type) {
switch (type) {
case 'array':
return []
// more case...
default:
return ''
}
}
/** 检查是否需要额外的组件 */
this.configs.extraComponents &&
this.configs.extraComponents.forEach(item => {
if (Object.hasOwn(this.dataForm, [item.name])) {
console.log('有了!')
return
} else {
console.log('新建!')
this.$set(this.dataForm, [item.name], calDefault(item.fieldType))
}
console.log('component: ', item.component)
})
/** 单独设置 id */
this.$set(this.dataForm, 'id', null)
console.log('mounted: this.dataForm', JSON.stringify(this.dataForm))
})
},
methods: {
getSpan(n, c) {
const opt = this.configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)]
return opt && opt.span ? opt.span : 24 / COLUMN_PER_ROW
},
getLabel(n, c) {
const opt = this.configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)]
if (opt) {
// if opt is valid
return opt.label ? opt.label : this.defaultNames[opt.name]
}
},
getPlaceholder(n, c) {
const opt = this.configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)]
if (opt) {
// if opt is valid
return opt.placeholder
? opt.placeholder
: this.defaultPlaceholders[opt.name]
? this.defaultPlaceholders[opt.name]
: opt.label
? (opt.type === 'select' ? i18n.t('choose') : '请输入') + opt.label
: null
// : opt.type === 'select'
// ? i18n.t('choose')
// : ''
}
},
getType(n, c) {
const opt = this.configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)]
if (opt) {
if (!opt.type || ['input', 'number' /** add more.. */].includes(opt.type)) {
return 'input'
} else if (['select' /** add more.. */].includes(opt.type)) {
return 'select'
} else if (['cascader'].includes(opt.type)) {
return 'cascader'
} else if (['date'].includes(opt.type)) {
return 'date'
}
// add more...
} else {
return 'input'
}
},
init(id) {
this.visible = true
this.$nextTick(() => {
this.$refs['dataForm'].resetFields()
this.dataForm.id = id || null
if (this.dataForm.id) {
this.$http({
url: this.$http.adornUrl(`${this.configs.infoUrl}/${this.dataForm.id}`),
method: 'get'
}).then(({ data: res }) => {
if (res && res.code === 0) {
const dataFormKeys = Object.keys(this.dataForm)
console.log('data form keys: ', dataFormKeys, pick(res.data, dataFormKeys))
this.dataForm = pick(res.data, dataFormKeys)
// LABEL: FILE_RELATED
/** 对文件下载进行分流 */
this.fileList = {}
if (this.dataForm.files) {
console.log('files: ', this.dataForm.files)
this.dataForm.files.forEach(file => {
// const fileName = file.fileUrl.split('/').pop()
/** [1] 处理 fileList */
if (Object.hasOwn(this.fileList, file.typeCode)) {
/** 已存在 */
// this.fileList[file.typeCode].push({ id: file.id, name: fileName, typeCode: file.typeCode })
this.fileList[file.typeCode].push(file)
} else {
// this.fileList[file.typeCode] = [{ id: file.id, name: fileName, typeCode: file.typeCode }]
this.fileList[file.typeCode] = [file]
}
/** [2] 处理 fileForm */
if (Object.hasOwn(this.fileForm, file.typeCode)) {
this.fileForm[file.typeCode].push(file.id)
} else {
this.fileForm[file.typeCode] = [file.id]
}
})
console.log('after分流', this.fileList)
}
}
})
} else {
/** 如果不是编辑,就填充自动生成的数据 */
if (this.shouldWait)
this.shouldWait.then(() => {
if (this.tempForm.length) {
console.log('create new, tempform', JSON.stringify(this.tempForm.length))
this.tempForm.forEach(item => {
console.log('item data', item.data)
this.dataForm[item.name] = item.data
})
console.log('create new, dataform', JSON.stringify(this.dataForm))
}
})
}
})
},
emitSelectChange(name, id) {
this.$emit('select-change', { name, id })
},
handleEditorReady(val) {
console.log('editor rready..', val)
},
handleClick(btn) {
/** 提取url */
const urls = {}
this.configs.operations.map(item => {
urls[item.name] = {}
urls[item.name].url = item.url
urls[item.name].extraFields = item.extraFields || {}
})
/** 操作 */
switch (btn.name) {
case 'save':
case 'update':
/** 需要验证表单的操作 */
this.$refs['dataForm'].validate(valid => {
if (valid) {
/** 对于文件上传的单独处理(合并处理) */
if (Object.keys(this.fileForm).length) {
console.log('fileform 有值')
// LABEL: FILE_RELATED
let fileIds = []
for (const [key, item] of Object.entries(this.fileForm)) {
if (Array.isArray(item)) {
fileIds = fileIds.concat(item)
} else {
console.error('handleClick(): 上传文件数组类型不正确')
}
}
this.$set(this.dataForm, 'fileIds', fileIds)
}
console.log('before send: ', this.dataForm)
this.$http({
url: this.$http.adornUrl(urls[btn.name].url),
method: btn.name === 'save' ? 'POST' : 'PUT',
data: { ...this.dataForm, ...urls[btn.name].extraFields }
})
.then(({ data: res }) => {
if (res && res.code === 0) {
this.$message({
message: btn.name === 'save' ? i18n.t('prompt.success') : '更新成功!',
type: 'success',
duration: 1500,
onClose: () => {
this.$emit('refreshDataList')
this.visible = false
}
})
} else {
this.$message.error(res.msg)
}
})
.catch(err => {
this.$message({
message: err,
type: 'error',
duration: 2000
})
})
}
})
return
case 'reset':
for (const key of Object.keys(this.dataForm)) {
if (typeof this.dataForm[key] === 'string') {
this.dataForm[key] = ''
} else if (this.dataForm[key] instanceof Array) {
this.dataForm[key].splice(0)
} else {
this.dataForm[key] = null
}
}
break
case 'cancel':
this.visible = false
// add more..
}
},
// LABEL: FILE_RELATED
handleUploadListUpdate(filelist, typeCode = 'DefaultTypeCode') {
console.log('before handleUploadListUpdate(): ', JSON.parse(JSON.stringify(this.fileForm)))
// typeCode: EquipmentTypeFile
// typeCode: EquipmentInfoFile | EquipmentInfoImage
// dataForm
// this.$set(
// this.dataForm,
// 'fileIds',
// filelist.map(item => item.id)
// )
// console.log('handleUploadListUpdate(): ', this.dataForm)
//
this.$set(
this.fileForm,
typeCode,
filelist.map(item => item.id)
)
console.log('after handleUploadListUpdate(): ', this.fileForm)
},
handleClose() {
this.$emit('destory-dialog')
this.visible = false
}
}
}
</script>
<style scoped>
.super-flexible-dialog >>> .el-select,
.super-flexible-dialog >>> .el-cascader {
width: 100%;
}
.super-flexible-dialog >>> ::-webkit-scrollbar {
width: 4px;
border-radius: 4px;
background: #fff;
}
.super-flexible-dialog >>> ::-webkit-scrollbar-thumb {
width: 4px;
border-radius: 4px;
background: #ccc;
}
.super-flexible-dialog >>> .hidden-input {
display: none;
}
</style>

View File

@ -0,0 +1,300 @@
<template>
<div class="attr-form">
<h3>
<!-- <el-button style="margin-left: 8px" type="text" v-if="!isDetail && !showAddAttr" @click="showAddAttr = true">{{ $t('add') }}</el-button> 跟在{{ title }} 同行后面 -->
{{ title }}
</h3>
<div v-if="!showAddAttr">
<component
:top-btn-config="topBtnConfig"
key="sub-table"
:is="require('../../base-table/index.vue').default"
:table-head-configs="filterTableConfigs()"
:data="dataList"
:page="pageIndex"
:size="pageSize"
:max-height="calcMaxHeight(8)"
@clickTopBtn="clickTopBtn"
@operate-event="handleOperations" />
<el-pagination
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
:current-page="pageIndex"
:page-sizes="[5, 10, 20, 50]"
:page-size="pageSize"
:total="totalPage"
layout="total, sizes, prev, pager, next, jumper">
</el-pagination>
</div>
<div v-else style="background: #eee; border-radius: 8px; padding: 12px">
<el-row>
<el-col>
<el-form ref="AttrForm" :model="AttrForm" :rules="AttrFormRules" :inline="true" label-position="top">
<el-row :gutter="20" style="padding: 0 24px">
<el-col :span="attrFormFields.length > 6 ? 6 : 12" v-for="field in attrFormFields" :key="field.prop + 'col'">
<el-form-item :key="field.prop" :prop="field.prop" :label="field.name" style="width: 100%">
<el-input v-if="field.formType === 'input' || !field.formType" v-model="AttrForm[field.prop]" :placeholder="$t('hints.input')" clearable />
<el-select v-if="field.formType === 'select'" v-model="AttrForm[field.prop]" clearable>
<el-option v-for="opt in field.formOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
</el-select>
<!-- add more... -->
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-col>
</el-row>
<el-row style="text-align: right">
<el-button size="small" @click="handleCloseAttrForm">{{ $t('cancel') }}</el-button>
<el-button type="success" size="small" @click="handleSaveAttrForm">{{ $t('save') }}</el-button>
</el-row>
</div>
</div>
</template>
<script>
import i18n from '@/i18n'
import BaseTable from '@/components/base-table'
import { pick } from 'lodash/object'
import { calcMaxHeight } from '@/utils'
const topBtnConfig = [
{
type: 'add',
btnName: i18n.t('add')
}
]
export default {
name: 'AttrForm',
components: { BaseTable },
props: {
isDetail: {
type: Boolean,
default: false
},
visible: {
type: Boolean,
default: false
},
/** subtable 需要设置的属性 */
title: {
type: String,
default: ''
},
url: {
type: String,
default: ''
},
tableConfigs: {
type: Array,
default: () => []
},
/** 表单提交需要的属性 */
relatedId: {
type: String,
required: true,
default: null
},
relatedField: {
type: String,
required: true,
default: null
}
},
data() {
return {
calcMaxHeight,
topBtnConfig,
showAddAttr: false,
dataList: [],
pageIndex: 1,
pageSize: 10,
totalPage: 0,
AttrForm: {}, //
AttrFormRules: {} //
}
},
computed: {
attrFormFields() {
const _ = this.tableConfigs.filter((item) => item.formField)
/** 顺带配置 AttrForm */
_.forEach((item) => {
this.$set(this.AttrForm, [item.prop], '')
})
this.$set(this.AttrForm, 'id', null)
return _
}
},
mounted() {
this.getDataList()
/** 设置 AttrForm 的 rules */
for (const config of this.tableConfigs) {
if (config.rules) {
this.$set(this.AttrFormRules, [config.prop], config.rules)
}
}
},
// createdtopBtnConfig使? :
created() {
// if(!(!this.isDetail && !this.showAddAttr)) {
// this.topBtnConfig = []
// }
},
methods: {
filterTableConfigs() {
if (this.isDetail) {
/** 如果是查看详情,就屏蔽操作列 */
return this.tableConfigs.filter((opt) => opt.prop !== 'operations')
}
return this.tableConfigs
},
/** init dataform */
initAttrForm() {
Object.entries(this.AttrForm).forEach(([key, value]) => {
if (typeof value === 'object' || typeof value === 'number') {
this.AttrForm[key] = null
} else if (Array.isArray(value)) {
this.AttrForm[key] = []
} else {
this.AttrForm[key] = ''
}
})
},
/** requests */
getDataList() {
this.dataListLoading = true
//
this.$http({
url: this.$http.adornUrl(`${this.url}/page`),
method: 'get',
params: this.$http.adornParams({
page: this.pageIndex,
limit: this.pageSize,
[this.relatedField]: this.relatedId
// order: 'asc/desc',
// orderField: 'name'
})
}).then(({ data: res }) => {
if (res && res.code === 0) {
this.dataList = res.data.list
this.totalPage = res.data.total
} else {
this.dataList = []
this.totalPage = 0
}
this.dataListLoading = false
})
},
/** handlers */
handleOperations({ type, data: id }) {
switch (type) {
case 'edit':
{
this.showAddAttr = true
this.$nextTick(() => {
this.$http.get(this.$http.adornUrl(`${this.url}/${id}`)).then(({ data: res }) => {
if (res && res.code === 0 && res.data) {
const neededFields = [...this.attrFormFields.map((item) => item.prop), 'id']
const filtered = pick(res.data, neededFields)
for (let field of neededFields) {
this.AttrForm[field] = filtered[field]
}
}
})
})
}
break
case 'delete':
return this.deleteHandle(id)
}
},
deleteHandle(id) {
var ids = id ? [id] : []
this.$confirm(`${i18n.t('prompt.info', { handle: id ? i18n.t('delete').toLowerCase() : i18n.t('deleteBatch').toLowerCase() })}`, i18n.t('prompt.title'), {
confirmButtonText: i18n.t('confirm'),
cancelButtonText: i18n.t('cancel'),
type: 'warning'
}).then(() => {
this.$http({
url: this.$http.adornUrl(this.url),
method: 'delete',
data: this.$http.adornData(ids, false, 'raw')
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: i18n.t('prompt.success'),
type: 'success',
duration: 1500,
onClose: () => {
this.getDataList()
}
})
} else {
this.$message.error(data.msg)
}
})
})
},
handleCloseAttrForm() {
this.showAddAttr = false
this.initAttrForm()
},
handleSaveAttrForm() {
this.$refs['AttrForm'].validate((valid) => {
if (valid) {
this.$http({
// url: this.$http.adornUrl(`${this.url}/${!this.AttrForm.id ? '' : this.AttrForm.id}`),
url: this.$http.adornUrl(this.url),
method: this.AttrForm.id ? 'put' : 'post',
headers: {
'Content-Type': 'application/json'
},
data: JSON.stringify({ ...this.AttrForm, [this.relatedField]: this.relatedId })
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: i18n.t('prompt.success'),
type: 'success',
duration: 1500,
onClose: () => {
this.showAddAttr = false
this.getDataList()
this.initAttrForm()
}
})
} else {
this.$message.error(data.msg)
}
})
}
})
},
//
sizeChangeHandle(val) {
this.pageSize = val
this.pageIndex = 1
this.getDataList()
},
//
currentChangeHandle(val) {
this.pageIndex = val
this.getDataList()
},
clickTopBtn() {
this.showAddAttr = true
}
}
}
</script>
<style scoped>
.attr-form >>> .el-form .el-form-item__label {
padding: 0;
}
</style>

View File

@ -0,0 +1,615 @@
<template>
<el-dialog
class="super-flexible-dialog"
:title="isDetail ? title.detail : !dataForm.id ? title.add : title.edit"
:visible.sync="visible"
@close="handleClose"
:distory-on-close="true"
:close-on-click-modal="false">
<div style="max-height: 60vh; overflow-y: scroll; overflow-x: hidden">
<el-form ref="dataForm" :model="dataForm" :rules="dataFormRules">
<!-- 如果需要更精细一点的布局可以根据配置项实现地再复杂一点但此处暂时全部采用一行两列布局 -->
<el-row v-for="n in rows" :key="n" :gutter="20">
<el-col v-for="c in COLUMN_PER_ROW" :key="`${n}+'col'+${c}`" :span="getSpan(n, c)">
<!-- <el-col v-for="c in COLUMN_PER_ROW" :key="`${n}+'col'+${c}`" :span="24 / COLUMN_PER_ROW"> -->
<!-- :class="{ 'hidden-input': configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].hidden }" -->
<el-form-item
v-if="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)]"
:prop="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name"
:key="`${n}-col-${c}-item`"
:label="getLabel(n, c)">
<!-- 暂时先不实现部分输入方式 -->
<el-input
v-if="getType(n, c) === 'input'"
:placeholder="getPlaceholder(n, c)"
v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
clearable
:disabled="isDetail" />
<el-radio v-if="getType(n, c) === 'radio'" v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]" :disabled="isDetail" />
<el-checkbox v-if="getType(n, c) === 'check'" v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]" :disabled="isDetail" />
<!-- 全部selcet下拉框可输入搜索 filterable-->
<el-select
v-if="getType(n, c) === 'select'"
:placeholder="getPlaceholder(n, c)"
v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
clearable
filterable
:disabled="isDetail || configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].isDisabled"
@change="emitSelectChange(configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name, $event)">
<el-option v-for="opt in configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].options" :key="opt.label + Math.random()" :label="opt.label" :value="opt.value" />
</el-select>
<el-switch v-if="getType(n, c) === 'switch'" v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]" :disabled="isDetail" />
<el-cascader
v-if="getType(n, c) === 'cascader'"
v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
:options="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].options"
:props="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].props"
:disabled="isDetail"
clearable />
<el-time-select v-if="getType(n, c) === 'time'" v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]" :disabled="isDetail" />
<el-date-picker
v-if="getType(n, c) === 'date'"
v-bind="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].props"
:placeholder="getPlaceholder(n, c)"
value-format='yyyy-MM-ddTHH:mm:ss'
v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
:disabled="isDetail" />
</el-form-item>
</el-col>
</el-row>
<!-- extra components , like Markdown or RichEdit -->
<template v-if="configs.extraComponents && configs.extraComponents.length > 0">
<el-form-item v-for="(ec, index) in configs.extraComponents" :key="ec.name + index" :label="ec.label" class="extra-components">
<component
style="margin-top: 40px"
v-if="ec.hasModel"
:is="ec.component"
v-bind="ec.props"
v-model="dataForm[ec.name]"
@ready="handleEditorReady"
:read-only="isDetail" />
<!-- <component v-if="ec.hasModel" :is="ec.component" v-bind="ec.props" v-model="dataForm[ec.name]" /> -->
<component
v-else
:is="ec.component"
v-bind="ec.props"
@uploader-update-filelist="handleUploadListUpdate($event, ec.props.extraParams.typeCode)"
:uploader-inject-file-list="/*用于设备分流的*/ fileList[ec.props.extraParams.typeCode]"
:read-only="isDetail" />
</el-form-item>
</template>
</el-form>
<template v-if="dataForm.id && configs.subtable">
<attr-form :related-id="dataForm.id" v-bind="configs.subtable" :is-detail="isDetail" />
</template>
</div>
<span slot="footer" class="dialog-footer">
<template v-for="(operate, index) in configs.operations">
<!-- {{ operate.name | btnNameFilter }} -->
<el-button
v-if="
!isDetail &&
(operate.showAlways ||
(((dataForm.id && operate.showOnEdit) || (!dataForm.id && !operate.showOnEdit)) && (operate.permission ? $hasPermission(operate.permission) : true)))
"
:key="`operate-${index}`"
:style="{
backgroundColor: btnType[operate.name],
color: btnColor[operate.name]
}"
@click="handleClick(operate)"
:disabled='isDisabled'
>{{ btnName[operate.name] }}</el-button
>
</template>
<el-button v-if="isDetail" @click="handleClick({ name: 'cancel' })">{{ $t('cancel') }}</el-button>
</span>
</el-dialog>
</template>
<script>
import CKEditor from 'ckeditor4-vue'
import AttrForm from '../AttrForm'
import { pick } from 'lodash/object'
import { pick as __pick } from '@/utils/filters'
import i18n from '@/i18n'
// for i18n
const title = {
detail: i18n.t('detail'),
add: i18n.t('add'),
edit: i18n.t('edit')
}
//
const btnType = {
add: '#0b58ff',
save: '#0b58ff',
update: '#0b58ff',
reset: ''
// cancel: 'text'
// add more...
}
const btnColor = {
save: '#fff',
update: '#fff',
reset: ''
// cancel: 'text'
// add more...
}
const btnName = {
// for i18n
save: i18n.t('save'),
update: i18n.t('update'),
reset: i18n.t('reset'),
cancel: i18n.t('cancel')
// add more...
}
//
const COLUMN_PER_ROW = 2
export default {
name: 'AddOrUpdateDialog',
components: { AttrForm },
props: {
configs: {
type: Object,
default: () => ({}) // 使
}
},
filters: {
nameFilter: function (name) {
if (!name) return null
// for i18n
const defaultNames = {
name: i18n.t('name'),
code: i18n.t('code'),
remark: i18n.t('remark'),
description: i18n.t('desc'),
specifications: i18n.t('prod.spec')
// add more...
}
return defaultNames[name]
}
},
// provide() {
// return {
// _df: this.dataForm
// }
// },
data() {
return {
//
isDisabled: false,
COLUMN_PER_ROW,
title,
/** 按钮相关属性 */
btnName,
btnType,
btnColor,
defaultNames: {
name: i18n.t('name'),
code: i18n.t('code'),
remark: i18n.t('remark'),
description: i18n.t('desc'),
specifications: i18n.t('prod.spec')
// add more...
},
defaultPlaceholders: {}, // defaultNames
/** 表单相关属性 */
visible: false,
isEdit: false,
isDetail: false,
dataForm: {},
dataFormRules: {},
tempForm: [], // code
shouldWait: null,
fileForm: {}, // typeCode
fileList: {} // typeCode
}
},
computed: {
rows() {
// ''
return Math.ceil(this.configs.fields.length / COLUMN_PER_ROW)
}
},
created() {
/** load lang */
// CKEditor.load()
// console.log('lang', CKEditor.component.props.config.defaultLanguage = 'en' )
},
mounted() {
/** 计算 defaultPlaceholders */
const prefix = i18n.t('hints.input')
Object.entries(this.defaultNames).map(([key, value]) => {
this.defaultPlaceholders[key] = prefix + value
})
/** 转换 configs.fields 的结构,把纯字符串转为对象 */
this.$nextTick(() => {
this.configs.fields = this.configs.fields.map((item) => {
if (typeof item === 'string') {
return { name: item }
}
return item
})
/** 动态设置dataForm字段 */
this.configs.fields.forEach((item) => {
this.$set(this.dataForm, [item.name], '')
/** select 的默认值设置 */
if (item.type === 'select') {
const opts = item.options || []
const dft = opts.find((item) => item.default || false)
if (dft) {
this.$set(this.dataForm, [item.name], dft.value)
}
}
if (item.api) {
/** 自动请求并填充 */
// or this.shouldWaitPool = []
this.shouldWait = this.$http({
url: this.$http.adornUrl(item.api),
method: 'POST' //
}).then(({ data: res }) => {
if (res && res.code === 0) {
// this.dataForm[item.name] = res.data // <===
this.tempForm.push({ name: item.name, data: res.data })
}
})
} // end if (item.api)
// relatedFielditem relatedField
if (item.relatedField) {
this.$watch(
function () {
return this.dataForm[item.name]
},
function (val, old) {
if (val && val !== old) {
this.$emit('select-change', { name: item.name, id: val })
}
},
{ deep: true, immediate: true }
)
}
if (item.required) {
const requiredRule = {
required: true,
message: i18n.t('validate.required'),
// trigger: 'change'
trigger: 'blur'
}
/** 检查是否已经存在该字段的规则 */
const exists = this.dataFormRules[item.name] || null
/** 设置验证规则 */
if (exists) {
const unset = true
for (const rule of exists) {
if (rule.required) unset = false
}
if (unset) {
exists.push(requiredRule)
}
} else {
/** 不存在已有规则 */
this.$set(this.dataFormRules, [item.name], [requiredRule])
}
} // end if (item.required)
if (item.rules) {
const exists = this.dataFormRules[item.name] || null
if (exists) {
//
exists.push(...item.rules)
} else {
this.$set(this.dataFormRules, [item.name], [...item.rules])
}
} // end if (item.rules)
})
/** 计算默认值 */
function calDefault(type) {
switch (type) {
case 'array':
return []
// more case...
default:
return ''
}
}
/** 检查是否需要额外的组件 */
this.configs.extraComponents &&
this.configs.extraComponents.forEach((item) => {
// if (Object.hasOwn(this.dataForm, [item.name])) {
if (this.dataForm.hasOwnProperty(item.name)) {
return
} else {
this.$set(this.dataForm, [item.name], calDefault(item.fieldType))
}
})
/** 单独设置 id */
this.$set(this.dataForm, 'id', null)
})
},
methods: {
getSpan(n, c) {
const opt = this.configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)]
return opt && opt.span ? opt.span : 24 / COLUMN_PER_ROW
},
getLabel(n, c) {
const opt = this.configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)]
if (opt) {
// if opt is valid
return opt.label ? opt.label : this.defaultNames[opt.name]
}
},
getPlaceholder(n, c) {
if (this.isDetail) {
/** 如果是详情,就不展示 提示文本 */
return ''
}
const opt = this.configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)]
if (opt) {
// if opt is valid
return opt.placeholder
? opt.placeholder
: this.defaultPlaceholders[opt.name]
? this.defaultPlaceholders[opt.name]
: opt.label
? (opt.type === 'select' ? i18n.t('choose') : i18n.t('hints.input')) + opt.label
: null
// : opt.type === 'select'
// ? i18n.t('choose')
// : ''
}
},
getType(n, c) {
const opt = this.configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)]
if (opt) {
if (!opt.type || ['input', 'number' /** add more.. */].includes(opt.type)) {
return 'input'
} else if (['select' /** add more.. */].includes(opt.type)) {
return 'select'
} else if (['cascader'].includes(opt.type)) {
return 'cascader'
} else if (['date'].includes(opt.type)) {
return 'date'
}
// add more...
} else {
return 'input'
}
},
init(id, isdetail = false) {
this.isDetail = isdetail
this.visible = true
this.$nextTick(() => {
this.$refs['dataForm'].resetFields()
this.dataForm.id = id || null
if (this.dataForm.id) {
this.$http({
url: this.$http.adornUrl(`${this.configs.infoUrl}/${this.dataForm.id}`),
method: 'get'
}).then(({ data: res }) => {
if (res && res.code === 0) {
const dataFormKeys = Object.keys(this.dataForm)
console.log('keys ===> ', dataFormKeys)
// console.log('data form keys: ', dataFormKeys, pick(res.data, dataFormKeys))
this.dataForm = __pick(res.data, dataFormKeys)
console.log('pick(res.data, dataFormKeys) ===> ', __pick(res.data, dataFormKeys))
// LABEL: FILE_RELATED
/** 对文件下载进行分流 */
this.fileList = {}
if (this.dataForm.files) {
// console.log('files: ', this.dataForm.files)
this.dataForm.files.forEach((file) => {
// const fileName = file.fileUrl.split('/').pop()
/** [1] 处理 fileList */
// if (Object.hasOwn(this.fileList, file.typeCode)) {
if (this.fileList.hasOwnProperty(file.typeCode)) {
/** 已存在 */
// this.fileList[file.typeCode].push({ id: file.id, name: fileName, typeCode: file.typeCode })
this.fileList[file.typeCode].push(file)
} else {
// this.fileList[file.typeCode] = [{ id: file.id, name: fileName, typeCode: file.typeCode }]
this.fileList[file.typeCode] = [file]
}
/** [2] 处理 fileForm */
// if (Object.hasOwn(this.fileForm, file.typeCode)) {
if (this.fileForm.hasOwnProperty(file.typeCode)) {
this.fileForm[file.typeCode].push(file.id)
} else {
this.fileForm[file.typeCode] = [file.id]
}
})
}
}
})
} else {
/** 如果不是编辑,就填充自动生成的数据 */
if (this.shouldWait)
this.shouldWait.then(() => {
if (this.tempForm.length) {
// console.log('create new, tempform', JSON.stringify(this.tempForm.length))
this.tempForm.forEach((item) => {
// console.log('item data', item.data)
this.dataForm[item.name] = item.data
})
// console.log('create new, dataform', JSON.stringify(this.dataForm))
}
this.shouldWait = null
})
}
})
},
emitSelectChange(name, id) {
// console.log(id)
const currentField = this.configs.fields.find((item) => item.name === name)
if (currentField.relatedField) {
this.dataForm[currentField.relatedField] = null
}
this.$emit('select-change', { name, id })
},
handleEditorReady(val) {},
handleClick(btn) {
/** 提取url */
const urls = {}
this.configs.operations.map((item) => {
urls[item.name] = {}
urls[item.name].url = item.url
urls[item.name].extraFields = item.extraFields || {}
})
/** 操作 */
switch (btn.name) {
case 'save':
this.isDisabled = true
setTimeout(() => {
this.isDisabled = false
}, 3000)
case 'update':
this.isDisabled = true
setTimeout(() => {
this.isDisabled = false
}, 3000)
/** 需要验证表单的操作 */
this.$refs['dataForm'].validate((valid) => {
if (valid) {
/** 对于文件上传的单独处理(合并处理) */
if (Object.keys(this.fileForm).length) {
// LABEL: FILE_RELATED
let fileIds = []
for (const [key, item] of Object.entries(this.fileForm)) {
if (Array.isArray(item)) {
fileIds = fileIds.concat(item)
} else {
console.error('handleClick(): 上传文件数组类型不正确')
}
}
this.$set(this.dataForm, 'fileIds', fileIds)
}
console.log('before send: ', this.dataForm)
this.$http({
url: this.$http.adornUrl(urls[btn.name].url),
method: btn.name === 'save' ? 'POST' : 'PUT',
data: { ...this.dataForm, ...urls[btn.name].extraFields }
})
.then(({ data: res }) => {
if (res && res.code === 0) {
this.$message({
message: i18n.t('prompt.success'),
// message: btn.name === 'save' ? i18n.t('prompt.success') : '!',
type: 'success',
duration: 1500,
onClose: () => {
this.$emit('refreshDataList')
this.visible = false
}
})
} else {
this.$message.error(res.msg)
}
})
.catch((err) => {
this.$message({
message: err,
type: 'error',
duration: 2000
})
})
}
})
return
case 'reset':
for (const key of Object.keys(this.dataForm)) {
if (typeof this.dataForm[key] === 'string') {
this.dataForm[key] = ''
} else if (this.dataForm[key] instanceof Array) {
this.dataForm[key].splice(0)
} else {
this.dataForm[key] = null
}
}
break
case 'cancel':
this.handleClose()
// add more..
}
},
// LABEL: FILE_RELATED
handleUploadListUpdate(filelist, typeCode = 'DefaultTypeCode') {
// console.log('before handleUploadListUpdate(): ', JSON.parse(JSON.stringify(this.fileForm)))
// typeCode: EquipmentTypeFile
// typeCode: EquipmentInfoFile | EquipmentInfoImage
// dataForm
// this.$set(
// this.dataForm,
// 'fileIds',
// filelist.map(item => item.id)
// )
// console.log('handleUploadListUpdate(): ', this.dataForm)
//
this.$set(
this.fileForm,
typeCode,
filelist.map((item) => item.id)
)
// console.log('after handleUploadListUpdate(): ', this.fileForm)
},
handleClose() {
this.$emit('destory-dialog')
this.visible = false
}
}
}
</script>
<style scoped>
.super-flexible-dialog >>> .el-select,
.super-flexible-dialog >>> .el-cascader {
width: 100%;
}
.super-flexible-dialog >>> ::-webkit-scrollbar {
width: 4px;
border-radius: 4px;
background: #fff;
}
.super-flexible-dialog >>> ::-webkit-scrollbar-thumb {
width: 4px;
border-radius: 4px;
background: #ccc;
}
.super-flexible-dialog >>> .hidden-input {
display: none;
}
</style>

View File

@ -0,0 +1,11 @@
<template>
<div class="cell-container">
</div>
</template>
<script>
export default {}
</script>
<style></style>

View File

@ -0,0 +1,30 @@
import i18n from '@/i18n'
export default {
name: 'TableTextComponent',
props: {
injectData: {
type: Object,
default: () => ({})
}
},
data() {
return {
// for i18n inject:
defaultText: i18n.t('viewdetail')
}
},
methods: {
emitClick() {
// console.log('inject data:' ,this.injectData)
this.$emit('emit-data', {
type: this.injectData.head?.actionName || 'view-detail-action',
data: this.injectData.head?.emitFullData ? this.injectData : this.injectData.id
})
}
},
render: function (h) {
// console.log('button content:', this.injectData)
return h('span', null, [h('el-button', { props: { type: 'text' }, style: { paddingLeft: 0 }, on: { click: this.emitClick } }, this.injectData.head?.buttonContent || this.defaultText)])
}
}

View File

@ -0,0 +1,74 @@
/*
* @Descripttion:
* @version:
* @Author: fzq
* @Date: 2023-01-06 15:49:50
* @LastEditors: fzq
* @LastEditTime: 2023-01-16 10:18:25
*/
import i18n from '@/i18n'
export default {
name: 'TableOperations',
props: {
injectData: {
type: Object,
default: () => ({})
}
},
data() {
return {
btnTypes: {
add: 'primary',
delete: 'danger',
detail: 'info'
// add more...
},
colors: {
delete: '#FF5454',
preview: '#f09843',
design: '#0b58ff',
edit: '#0b58ff'
// 'view-trend': 'red'
// add more...
},
text: {
// TODO: i18n
edit: i18n.t('edit'),
detail: i18n.t('detail'),
delete: i18n.t('delete'),
viewAttr: i18n.t('viewattr'),
preview: i18n.t('preview'),
design: i18n.t('design'),
'view-trend': '查看趋势'
// add more...
}
}
},
methods: {
// 发射事件
emit(opt) {
let emitFull = false
let eventType = 'default'
let customField
if (typeof opt === 'object') {
eventType = opt.name
customField = opt.emitField || 'id'
emitFull = opt.emitFull || false
} else {
eventType = opt
}
this.$emit('emit-data', { type: eventType, data: emitFull ? this.injectData : customField ? this.injectData[customField] : this.injectData.id })
}
},
render: function (h) {
let btns = []
for (const optionStr of this.injectData.head?.options) {
const optObj = typeof optionStr === 'object'
// btns.push(h('el-button', { props: { type: this.btnTypes[optionStr] } }, optionStr))
// 原色 #409EFF
btns.push(h('el-button', { props: { type: 'text' }, style: { color: optObj ? this.colors[optionStr.name] : this.colors[optionStr] || '#0b58ff' }, on: { click: this.emit.bind(null, optionStr) } }, typeof optionStr === 'object' ? this.text[optionStr.name] : this.text[optionStr]))
}
return h('span', null, btns)
}
}

View File

@ -0,0 +1,79 @@
<!--
* @Descripttion:
* @version:
* @Author: fzq
* @Date: 2022-11-25 09:51:46
* @LastEditors: fzq
* @LastEditTime: 2023-02-09 10:17:22
-->
<template>
<!-- 数字代表多级表头最小列宽 -->
<!-- :width="opt.width || null" -->
<!-- :width="flexColumnWidth(opt.prop || null)" -->
<!-- header-align="center" align="center" -->
<!-- :min-width="opt.minWidth || null" -->
<el-table-column
:label="opt.label ? opt.label : opt.name"
:prop="opt.prop || null"
:min-width="[$route.fullPath == '/monitoring-realtimeQualityInspection' ? 170 : (opt.minWidth || null)]"
:fixed="opt.fixed || null"
:show-overflow-tooltip="opt.showOverflowTooltip || false"
filter-placement="top"
:align="opt.align || 'center'"
v-bind="opt.more"
>
<template v-if="opt.prop" slot-scope="scope">
<component v-if="opt.subcomponent" :is="opt.subcomponent" :key="idx + 'sub'" :inject-data="{ ...scope.row, head: opt }" @emit-data="handleSubEmitData" />
<!-- 直接展示数据或应用过滤器 -->
<span v-else>{{ scope.row[opt.prop] | commonFilter(opt.filter) }}</span>
</template>
<!-- 递归 -->
<template v-if="!opt.prop && opt.children">
<TableHead v-for="(subhead, index) in opt.children" :key="'subhead' + index" :opt="subhead" />
</template>
</el-table-column>
</template>
<script>
export default {
name: 'TableHead',
filters: {
commonFilter: (source, filterType = a => a) => {
return filterType(source)
}
},
props: {
opt: {
type: Object,
default: () => ({})
}
},
methods: {
//
flexColumnWidth(str) {
let flexWidth = 0
for (const char of str) {
if ((char >= 'A' && char <= 'Z') || (char >= 'a' && char <= 'z')) {
// 8
flexWidth += 8
} else if (char >= '\u4e00' && char <= '\u9fa5') {
// 20
flexWidth += 20
} else {
// 5
flexWidth += 5
}
}
// if (flexWidth < 50) {
// //
// flexWidth = 50
// }
if (flexWidth > 250) {
//
flexWidth = 250
}
return flexWidth + 'px'
},
}
}
</script>

View File

@ -0,0 +1,220 @@
<template>
<div class="base-table">
<!-- 花式新增按钮 -->
<div class="setting">
<template v-if="topBtnConfig.length > 0">
<!-- table顶部操作按钮区 -->
<div class="action_btn">
<template v-for="(btn, index) in topBtnConfig">
<span v-if="btn.type === 'add'" :key="index" style="display: inline-block" @click="clickTopButton(btn.type)">
<svg-icon style="width: 14px; height: 14px" class="iconPlus" icon-class="addPage" />
<span class="add">{{ $t('add') }}</span>
</span>
</template>
</div>
</template>
<!-- 设置小齿轮table列的图标 -->
<el-popover placement="bottom-start" width="200" trigger="click">
<div class="setting-box">
<!-- :label="item.name ? item.name : item.label" 三元判别就可以让厂务的实时数据可以显示 -->
<el-checkbox v-for="(item, index) in tableHeadConfigs" :key="'cb' + index" v-model="selectedBox[index]" :label="item.name ? item.name : item.label" />
</div>
<i slot="reference" class="el-icon-s-tools" style="color: #0b58ff" />
</el-popover>
</div>
<!-- border 属性增加边框:header-cell-style="{background:'#FAFAFA',color:'#606266',height: '40px'}" -->
<!-- <el-table :data="data" -->
<el-table
:data="renderData"
style="width: 100%"
fit
highlight-current-row
:header-cell-style="{ background: '#FAFAFA', color: '#000', height: '40px' }"
:max-height="maxHeight"
:span-method="spanMethod || null"
:row-style="{ height: '40px' }"
:cell-style="{ padding: '0px' }">
<!-- 表格头定义 -->
<!-- in tableHeadConfigs -->
<template v-for="(head, idx) in renderTableHeadList">
<!-- 带type的表头 -->
<el-table-column
:key="idx"
v-if="head.type"
:type="head.type"
:label="head.label || head.name || ''"
:header-align="head.align || 'center'"
:align="head.align || 'center'"
:width="head.width || 50"
:index="
head.type === 'index'
? (val) => {
return val + 1 + (page - 1) * size
}
: null
"
v-bind="head.more"></el-table-column>
<!-- 普通的表头 -->
<!-- :align="head.align || null" 表头居中 -->
<!-- :min-width="head.minWidth || null" -->
<el-table-column
v-else
:key="idx + 'else'"
:label="head.label ? head.label : head.name"
:prop="head.prop || null"
:width="head.width || null"
:min-width="head.minWidth || null"
:fixed="head.fixed || null"
:show-overflow-tooltip="head.showOverflowTooltip || true"
:tooltip-effect="head.tooltipEffect || 'light'"
filter-placement="top"
:align="head.align || 'center'"
v-bind="head.more">
<!-- 子组件 编辑/删除 -->
<template v-if="head.prop" slot-scope="scope">
<component v-if="head.subcomponent" :is="head.subcomponent" :key="idx + 'sub'" :inject-data="{ ...scope.row, head }" @emit-data="handleSubEmitData" />
<!-- 直接展示数据或应用过滤器 -->
<span v-else>{{ scope.row[head.prop] | commonFilter(head.filter) }}</span>
</template>
<!-- 多级表头 -->
<template v-if="!head.prop && head.children">
<TableHead v-for="(subhead, subindex) in head.children" :key="'subhead-' + idx + '-subindex-' + subindex" :opt="subhead"/>
</template>
</el-table-column>
</template>
</el-table>
</div>
</template>
<script>
import { isObject, isString } from 'lodash'
import TableHead from './components/table-head.vue'
export default {
name: 'BaseTable',
filters: {
commonFilter: (source, filterType = (a) => a) => {
return filterType(source)
}
},
props: {
tableHeadConfigs: {
type: Array,
default: () => []
// required: true,
// validator: val => val.filter(item => !isString(item.prop) || !isString(item.name)).length === 0
},
data: {
type: Array,
default: () => []
},
maxHeight: {
type: Number,
// default: window.innerHeight - 325
// el-table
default: window.innerHeight - 100
// default: 500
},
spanMethod: {
type: Function,
default: () => {
;() => [0, 0]
},
required: false
},
page: {
type: Number,
default: 1
},
size: {
type: Number,
default: 10
},
// props
// tableConfig: {
// type: Array,
// required: true,
// validator: (val) => val.filter((item) => !isString(item.prop) || !isString(item.label)).length === 0
// },
topBtnConfig: {
type: Array,
default: () => {
return []
}
}
},
filters: {
commonFilter: (source, filterType = (a) => a) => {
return filterType(source)
}
},
data() {
return {
selectedBox: new Array(100).fill(true)
}
},
computed: {
renderData() {
return this.data.map((item, index) => {
return {
...item,
_pageIndex: (this.page - 1) * this.limit + index + 1
}
})
},
renderTableHeadList() {
return this.tableHeadConfigs.filter((item, index) => {
return this.selectedBox[index]
})
}
},
beforeMount() {
this.selectedBox = new Array(100).fill(true)
if (this.highIndex) {
this.tableRowIndex = 0
}
},
created() {
// console.log(this.selectedBox)
// console.log(this.tableHeadConfigs)
},
methods: {
handleSubEmitData(payload) {
this.$emit('operate-event', payload)
},
clickTopButton(val) {
this.$emit('clickTopBtn', val)
}
},
components: { TableHead }
}
</script>
<style lang="scss">
.setting {
text-align: right;
padding: 0px 15px 7px;
.action_btn {
display: inline-block;
margin-right: 15px;
font-size: 14px;
.add {
color: #0b58ff;
}
}
.setting-box {
width: 100px;
}
i {
color: #aaa;
}
}
.el-table .success-row {
background: #eaf1fc;
}
.iconPlus {
color: #0b58ff;
margin-right: 2px;
}
</style>

View File

@ -0,0 +1,213 @@
<template>
<div class="base-upload" style="border-radius: 8px; margin-top: 48px; padding: 0; max-height: 500px;">
<el-upload
class="yd-upload"
action="#"
:http-request="handleUpload"
multiple
:file-list="fileList"
:on-preview="handleDownload"
:on-remove="handleRemove"
:before-upload="/.*?image.*?/i.test(extraParams.typeCode) ? validateImage : validateFile"
>
<!-- :before-remove="beforeRemove" -->
<!-- accept="image/*" -->
<!-- <el-upload class="yd-upload" :action="$http.adornUrl(url)" multiple name="files" :data="extraParams" :file-list="fileList" :on-remove="handleRemove" :before-remove="beforeRemove"> -->
<el-button :disabled="readOnly" type="primary">{{ buttonContent }}</el-button>
<div v-if="tip" slot="tip" class="el-upload__tip">{{ tip }}</div>
</el-upload>
</div>
</template>
<script>
import { pick } from 'lodash/object'
export default {
name: 'BaseUpload',
props: {
url: String,
buttonContent: String,
tip: {
type: String,
default: null
},
extraParams: {
type: Object,
default: () => ({})
},
uploaderInjectFileList: {
// fileList
type: Array,
default: () => []
},
readOnly: {
type: Boolean,
default: false
}
},
// inject: {
// parentDataForm: "_df"
// },
data() {
return {
fileList: []
}
},
mounted() {
this.fileList.splice(0)
this.$watch('uploaderInjectFileList', function(val) {
if (val && val.length) {
// console.log('this.uploaderInjectFileList', this.uploaderInjectFileList)
/** uploaderInjectFileList 里关于文件的信息比较全,需要手动过滤一下 */
this.fileList = val.map(item => {
const name = item.fileUrl.split('/').pop()
return { ...pick(item, ['id', 'fileName', 'typeCode']), name }
})
}
// console.log('fillist: ', this.fileList)
})
// if (this.parentDataForm) {
// console.log('parent dataform: ', this.parentDataForm)
// }
},
methods: {
/** 自定义上传行为 */
handleUpload(file) {
const formData = new FormData()
let files = file.file
formData.append('files', files)
this.$http({
url: this.$http.adornUrl(this.url),
method: 'POST',
data: formData,
params: {
typeCode: this.extraParams.typeCode
}
}).then(({ data: res }) => {
if (res && res.code === 0) {
res.data.forEach(item => {
const ext = item.fileUrl.split('.').reverse()[0]
const name = `${item.fileName}.${ext}`
this.fileList.push({ ...pick(item, ['id', 'fileName', 'typeCode']), name })
})
// TODO: fileIds[]
this.$emit('uploader-update-filelist', this.fileList)
}
})
},
/** 大小验证,由配置文件开启 */
validateFile(file) {
const isRightSize = file.size / 1024 / 1024 < 2
if (!isRightSize) {
// this.$message.error(this.$t('upload.picSizeAlarm'))
this.$message.error('文件不应超过 2MB')
}
return isRightSize
},
/** 图片验证,由配置文件开启 */
validateImage(file) {
// console.log('[*] ')
const isRightSize = file.size / 1024 / 1024 < 2
if (!isRightSize) {
this.$message.error('文件不应超过 2MB')
// this.$message.error(this.$t('upload.picSizeAlarm'))
}
const isAccept = new RegExp('image/*').test(file.type)
if (!isAccept) {
// this.$message.error(this.$t('upload.picAlarm'))
this.$message.error('只允许上传图片')
}
return isRightSize && isAccept
},
/** 点击下载 */
handleDownload({ id: fileId, name: fileName }) {
const type = {
download: 1,
preview: 0
}
this.$http({
url: this.$http.adornUrl('/monitoring/attachment/downloadFile'),
method: 'get',
params: this.$http.adornParams({
attachmentId: fileId,
type: type.download
// fileName,
// outputQuality,
// scale
}),
responseType: 'blob'
}).then(({ data: res }) => {
const blob = new Blob([res])
// console.log('blob', blob)
if ('download' in document.createElement('a')) {
const alink = document.createElement('a')
// console.log('filename: ', fileName)
alink.download = fileName
alink.style.display = 'none'
alink.target = '_blank'
alink.href = URL.createObjectURL(blob)
document.body.appendChild(alink)
alink.click()
URL.revokeObjectURL(alink.href)
document.body.removeChild(alink)
} else {
navigator.msSaveBlob(blob, fileName)
}
})
},
// beforeRemove(file, filelist) {
// return this.$confirm(` ${file.name}?`)
// },
handleRemove(file, filelist) {
// fileList
this.$emit('uploader-update-filelist', filelist)
}
}
}
</script>
<style scoped>
.base-upload >>> .yd-upload {
margin-bottom: 20px;
}
/* .base-upload >>> .el-button {
display: block;
width: 200px;
position: relative;
left: -50px;
} */
/* .base-upload >>> .el-upload--text {
width: 100px;
position: relative;
left: -100px;
} */
.base-upload >>> .el-upload__tip {
margin-top: 0;
margin-left: 5px;
}
.base-upload {
display: flex;
}
.yd-upload {
/* background-color: #efefef; */
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: flex-start;
}
</style>

View File

@ -76,7 +76,7 @@ export default {
return data.name.indexOf(value) !== -1
},
getDeptList (id) {
return this.$http.get('/sys/dept/list').then(({ data: res }) => {
return this.$http.get(this.$http.adornUrl('/sys/dept/list')).then(({ data: res }) => {
if (res.code !== 0) {
return this.$message.error(res.msg)
}

View File

@ -90,7 +90,7 @@ export default {
return data.name.indexOf(value) !== -1
},
getDataList (id) {
return this.$http.get('/sys/region/tree').then(({ data: res }) => {
return this.$http.get(this.$http.adornUrl('/sys/region/tree')).then(({ data: res }) => {
if (res.code !== 0) {
return this.$message.error(res.msg)
}

View File

@ -0,0 +1,68 @@
<!--
* @Author: lb
* @Date: 2022-05-18 16:00:00
* @LastEditors: fzq
* @LastEditTime: 2023-01-03 10:00:06
* @Description:
-->
<template>
<div :class="[className, { 'p-0': noPadding }]">
<slot />
</div>
</template>
<script>
export default {
props: {
size: {
// : xl lg md sm
type: String,
default: 'de',
validator: function(val) {
return ['xl', 'lg', 'de', 'md', 'sm'].indexOf(val) !== -1
}
},
noPadding: {
type: Boolean,
default: false
}
},
computed: {
className: function() {
return `${this.size}-title`
}
}
}
</script>
<style lang="scss" scoped>
$pxls: (xl, 28px) (lg, 24px) (de, 22px) (md, 18px) (sm, 16px);
$mgr: 6px;
@each $size, $height in $pxls {
.#{$size}-title {
padding: 8px 0;
font-size: $height;
line-height: $height;
color: #000;
font-weight: 500;
// font-family: '', 'Microsoft YaHei', Arial, Helvetica, sans-serif;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
&::before {
content: '';
display: inline-block;
vertical-align: top;
width: 4px;
height: $height;
border-radius: 1px;
margin-right: $mgr;
// background-color: #0b58ff;#409EFF;
background-color: #0b58ff;
}
}
}
.p-0 {
padding: 0;
}
</style>

View File

@ -16,7 +16,9 @@ $--color-transition-base: color .2s cubic-bezier(.645,.045,.355,1) !default;
/* Color
-------------------------- */
/// color|1|Brand Color|0
$--color-primary: #409EFF !default;
// $--color-primary: #409EFF !default;
// 左上标题背景颜色
$--color-primary: #001529 !default;
/// color|1|Background Color|4
$--color-white: #FFFFFF !default;
/// color|1|Background Color|4
@ -50,6 +52,7 @@ $--color-danger-lighter: mix($--color-white, $--color-danger, 90%) !default;
$--color-info-lighter: mix($--color-white, $--color-info, 90%) !default;
/// color|1|Font Color|2
$--color-text-primary: #303133 !default;
$--color-text-home: #fff !default;
/// color|1|Font Color|2
$--color-text-regular: #606266 !default;
/// color|1|Font Color|2

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

678
src/i18n/en.js Normal file
View File

@ -0,0 +1,678 @@
const t = {}
t.loading = 'Loading...'
t.createTime = 'Create Time'
t.brand = {}
t.brand.lg = 'SCADA Platform'
t.brand.mini = 'SCADA'
t.brand.home = 'Home'
t.routes = {}
t.routes['产品池'] = 'Products Pool'
t.routes['基本资料'] = 'Basic Data'
t.routes['设备数采'] = 'Equipment PLC'
t.routes['厂务管理'] = 'Factory Management'
t.routes['报表管理'] = 'Report Management'
t.routes['质量管理'] = 'Quality Management'
t.routes['权限管理'] = 'Permission Management'
t.routes['系统设置'] = 'System Settings'
t.routes['日志管理'] = 'Log Management'
t.routes['数据分析'] = 'Data Analysis'
// 二级
t.routes['厂务'] = 'Factory Affair'
t.routes['设备'] = 'Equipment'
t.routes['字典管理'] = 'Dict Management'
t.routes['PLC信息'] = 'PLC'
// Relations between
t.routes['设备与PLC关联配置'] = 'PLC & Equipments'
t.routes['近24小时设备生产数据'] = 'Equipment Data'
t.routes['近24小时产线生产数据'] = 'Productline Data'
t.routes['近24小时质量检查数据'] = 'Quality Inspection Data'
t.routes['报表总览'] = 'Report Overview'
t.routes['报表分类'] = 'Report Types'
t.routes['报表详情'] = 'Report Detail'
t.routes['报表设计'] = 'Report Design'
t.routes['报表预览'] = 'Report Preview'
// Quality
t.routes['质量检测基础数据'] = 'Inspection Basic Data'
t.routes['当前检测数据'] = 'Current Inspection Data'
t.routes['检测统计数据'] = 'Statistics Data'
t.routes['质量检查信息记录'] = 'Quality Inspection Records'
t.routes['用户管理'] = 'User Management'
t.routes['部门管理'] = 'Department Management'
t.routes['角色管理'] = 'Role Management'
t.routes['菜单管理'] = 'Menu Management'
t.routes['参数管理'] = 'Params Management'
t.routes['定时任务'] = 'Timed Tasks'
t.routes['文件上传'] = 'File Upload'
t.routes['登录日志'] = 'Login Records'
t.routes['操作日志'] = 'Operations Records'
t.routes['设备效率分析'] = 'EQU Efficiency Analysis'
t.routes['设备异常分析'] = 'EQU Exceptions Analysis'
t.routes['设备状态时序图'] = 'EQU Status Timeseq'
t.routes['产品质量分析'] = 'Product Quality Analysis'
t.routes['产量分析'] = 'Product Analysis'
t.routes['生产节拍时序图'] = 'Product Beat Timeseq'
t.routes['设备产量时序图'] = 'EQU Product Timeseq'
// 三级
t.routes['工厂'] = 'Factory'
t.routes['产线'] = 'Product Lines'
t.routes['工段'] = 'Work Sections'
t.routes['设备类型'] = 'Equipment Types'
t.routes['设备分组'] = 'Equipment Groups'
t.routes['设备信息'] = 'Equipment Details'
t.routes['设备参数状态监控'] = 'Current Equipment State'
t.routes['设备分组报警信息'] = 'Equipment Group Alarm'
t.routes['设备历史参数'] = 'Equipment Historical Parameters'
t.routes['质量检测类型'] = 'Quality Inpection Types'
t.routes['质量检测信息'] = 'Quality Inpection Details'
t.routes['安灯检测盒'] = 'Andeng inspection box'
t.andeng = {}
t.andeng.inspectContent = 'Inspection Content'
t.andeng.btnVal = 'Button Value'
t.andeng.btnBoxModel = 'Button Box Model'
t.copyright = 'VISHAKHA glass pvt Ltd'
t.dictValueList = 'View Details'
t.save = 'Save'
t.add = 'Add'
t.delete = 'Delete'
t.deleteBatch = 'Delete Batch'
t.update = 'Update'
t.query = 'Search'
t.export = 'Export'
t.handle = 'Operations'
t.confirm = 'Confirm'
t.cancel = 'Cancel'
t.clear = 'Clear'
t.logout = 'Logout'
t.manage = 'Handle'
t.createDate = 'Create Date'
t.keyword = 'Keyword(s): '
t.choose = 'Please Choose '
t.remark = 'Remark'
t.delMark = 'Delete Mark '
t.isvalid = 'is valid'
t.available = 'available'
t.unavailable = 'unavailable'
t.alert = 'alert'
t.creator = 'Creator'
t.creatorName = 'Creator\'s name'
t.updator = 'Updator'
t.updatorName = 'Updator\'s name'
t.updateTime = 'Update Time'
t.version = 'Version'
t.search = 'Search'
t.countPerPage = 'Per Page' // ?
t.currentPage = 'Current Page' // ?
t.fetchList = 'Fetch Data List' // ?
t.multi = 'Multiple Selection' // ?
t.do = 'Proceed' // ?
t.submit = 'Submit' // ?
t.desc = 'Description'
t.disable = 'Disable'
t.equipment = 'Equipment'
t.enabled = 'Enabled'
t.cannotempty = 'can\'t be empty'
t.parameter = 'Parameters'
t.enable = 'Enable'
t.index = 'Index'
t.relation = 'Relation'
t.fetchInfo = 'Fetch Info'
t.name = 'Name'
t.code = 'Code'
t.attrName = 'Attribute name'
t.attrValue = 'Attribute value'
t.unit = 'Unit'
t.table = 'Table'
t.table2 = 'Table'
t.downloadurl = 'Download Url'
t.recordTime = 'Record Time'
t.notCollect = 'No'
t.collect = 'Yes'
t.required = 'Required'
t.paramUrl = 'Parameter url'
t.enname = 'English Name'
t.collectOrNot = 'Collect or not'
t.min = 'Min Value'
t.max = 'Max Value'
t.status = 'Status'
t.normal = 'Normal'
t.shutdown = 'Shut Down'
t.malfunction = 'Malfunction' // ?
t.diagram = 'Device Status Sequence Diagram'
t.diagram2 = 'Device Product Sequence Diagram'
t.addr = 'Address'
t.planStop = 'Plan to stop'
t.startTime = 'Start Time'
t.endTime = 'End Time'
t.today = 'Today'
t.time = 'Time'
t.eqId = 'Current Equipment ID:'
t.ti = 'Time'
t.plcCode = 'PLC Code'
t.equName = 'Equipment Name'
t.equCode = 'Equipment Code'
t.yAxisTime = 'Time (h)'
t.yAxisRate = 'Percentage (%)'
t.hourTime = '(h)'
t.graph = 'Graph'
t.category = 'Category'
t.categoryName = 'Category Name'
t.categoryCode = 'Category Code'
t.rate = 'Rate'
t.link = 'Link Url'
t.refresh = 'Refresh'
t.abbr = 'Abbreviation'
t.detail = 'Details'
t.viewdetail = 'Details'
t.viewattr = 'View Attributions'
t.edit = 'Edit'
t.source = 'Source'
t.auto = 'Auto'
t.manual = 'Manually'
t.loaddone = 'Loaded'
t.produceTime = 'Date of manufacture'
t.enterTime = 'Enter Time'
t.manufacturer = 'Manufacturer'
t.success = 'success!'
t.all = 'All'
t.reset = 'Reset'
t.preview = 'Preview'
t.design = 'Design'
t.timetype = 'Time Type'
t.reftimerange = 'By time range'
t.refdate = 'By date'
t.hour = 'Hour(s)'
t.yes = 'yes'
t.no = 'no'
t.LoginRecords = ' Login Records'
t.operationsRecords = ' Operations Records'
t.allIcons= 'All Icons'
t.err= 'Error'
t.errors = {}
t.errors.nosection = 'There is no sections on this product line.'
t.errors.numsection = 'There are {num} sections on this product line.'
t.errors.nodata = 'Error, no data available!'
t.hints = {}
t.hints.input = 'Please input '
t.hints.select = 'Please select '
t.hints.date = 'Please select date'
t.hints.checktime = 'Please select inspection time'
t.hints.number = 'Please input correct number'
t.hints.integer = 'Please input correct integer'
t.hints.addr = 'Please input address'
t.hints.upload2m = 'File size cannot be larger than 2MB (2048KB)'
t.hints.upload2mPic = 'Image files only. File size cannot be larger than 2MB (2048KB)'
t.factory = {}
t.factory.title = 'Factory'
t.factory.name = 'Factory Name'
t.factory.code = 'Factory Code'
t.prod = {}
t.prod.id = 'Product ID'
t.prod.name = 'Product Name'
t.prod.code = 'Product Code'
t.prod.type = 'Product Type'
t.prod.area = 'Area'
t.prod.spec = 'Product Specification'
t.prod.attr = 'Attributes'
t.prod.attrcode = 'Attribute Code'
t.prod.attrcodeHints = 'Please input attribute code'
t.prod.attrname = 'Attribute Node'
t.prod.attrnameHints = 'Please input attribute name'
t.prod.attrvalueHints = 'Please input attribute value'
t.prod.descHints = 'Please input description'
// t.prod.processTime = 'Processing Time (Hours)'
t.prod.processTime = 'Processing Time (s)'
t.prod.processTimeHints = 'Please input processing time'
t.prod.relatedPid = 'Related Product'
t.alarm = {}
t.alarm.name = 'Alarm'
t.alarm.info = 'Alarm Informations'
t.alarm.view = 'View Alarm'
t.alarm.eq = 'Alarm Equipment'
t.alarm.type = 'Alarm Type'
t.alarm.code = 'Alarm Code'
t.alarm.level = 'Alarm Level'
t.alarm.content = 'Alarm Content'
t.alarm.source = 'Alarm Source'
t.alarm.det = 'Alarm Details'
t.alarm.externalCode = 'External Code'
t.alarm.description = 'Description'
t.alarm.remark = 'Remark'
t.report = {}
t.report.name = 'Report Name'
t.report.det = 'Report Content'
t.report.type = 'Report Type'
t.report.code = 'Report Code'
t.report.lnk = 'Report Url'
t.inspect = {}
t.inspect.type = 'Inspection Type'
t.inspect.code = 'Inspection Code'
t.inspect.det = 'Inspection Details'
t.inspect.detcode = 'Inspection Content Code'
t.inspect.people = 'Inspector'
t.inspect.time = 'Inspection Time'
t.inspect.typetotal = 'Total Inspection Types'
t.inspect.typename = 'Inspection Type'
t.inspect.typecode = 'Inspection Code'
t.inspect.ioTotal = 'Data of input/output and total inspections'
t.inspect.plTotal = 'Inspection contents in each line'
t.inspect.inTotal = 'Up Sum'
t.inspect.outTotal = 'Down Sum'
t.inspect.checkTotal = 'Total Inspections'
t.inspect.rate = 'Rate'
t.inspect.typeCount = 'Data of inspection types'
t.realtime = {}
t.realtime.eq = 'Realtime data of equipments(24h)'
t.realtime.pl = 'Realtime data of productlines(24h)'
t.realtime.inspect = 'Realtime data of quality inspections(24h)'
t.realtime.in = 'in'
t.realtime.out = 'out'
t.realtime.data = 'scrap'
t.realtime.num = 'scrap quantity'
t.realtime.rate = 'scrap rate'
t.realtime.total = 'Equipment total production'
t.realtime.goodrate = 'Passed Rate'
t.realtime.runState = 'running state'
t.realtime.state = 'status'
t.realtime.hasFault = 'malfunction'
t.realtime.recentParamValue = 'recent parameters'
t.realtime.view = 'view'
t.realtime.input = 'input' //'投入数'
t.realtime.output = 'output' //'产出数'
t.realtime.eqName = 'Equipment name'
t.realtime.eqCode = 'Equipment cdoe'
t.realtime.productionSnapshotTime = 'production recording time' // '生产量记录时间'
t.realtime.statusSnapshotTime = 'status recording time' // '状态记录时间'
t.realtime.refresh = 'Refresh data...'
t.ws = {}
t.ws.title = 'Work Section'
t.ws.id = 'Work Section ID'
t.ws.name = 'Work Section Name'
t.ws.code = 'Work Section Code'
t.ws.binded = 'Binded Equipments'
t.ws.unbind = 'Equipment Name'
t.ws.eqbindplaceholder = 'Select an equipment'
t.ws.sort = 'sort'
t.ws.setorder = 'Please input order of equipments in the work section.'
t.ws.bind = 'bind'
t.ws.eqbind = 'Binded Equipment(s)'
t.ws.belong = 'Product Line'
t.file = {}
t.file.title = 'File'
t.file.name = 'File Name'
t.file.code = 'File Code'
t.file.typeName = 'File Type'
t.file.typeCode = 'File Type Code'
t.eq = {}
t.eq.title = 'Equipment'
t.eq.id = 'Equipment ID'
t.eq.name = 'Equipment Name'
t.eq.code = 'Equipment Code'
t.eq.type = 'Equipment Type'
t.eq.grade = 'Specification of equipment'
t.eq.group = 'Equipment Group'
t.eq.groupname = 'Group Name'
t.eq.groupcode = 'Group Code'
t.eq.excode = 'External Code'
t.eq.input = 'Input Device'
t.eq.output = 'Output Device'
t.eq.tvalue = 'Device\'s TT Value'
t.eq.processingTime = 'Processing Time (s)'
t.eq.dtype = 'Data source'
t.eq.dtypenone = 'none'
t.eq.dtypeinput = 'Input Data Device'
t.eq.dtypeoutput = 'Output Data Device'
t.eq.upload = 'Upload'
t.eq.image = 'Equipment Pictures'
t.eq.viewattr = 'Equipment Attributions'
t.eq.plcbarcode = 'PLC Bar Code'
t.eq.plccode = 'PLC Code'
t.eq.plcname = 'PLC Name'
t.eq.port = 'Port'
t.eq.type = 'Type'
t.eq.typecode = 'Type Code'
t.eq.parent = 'Parent'
t.eq.mtbf = 'Mean time between failures[MTBF] (h)'
t.eq.mttr = 'Mean time to repair[MTTR] (h)'
t.eq.efficienttimeh = 'Working time(h)'
t.eq.shutdowntimeh = 'Off time(h)'
t.eq.worktimeh = 'Working time(h)'
t.eq.downtimeh = 'Malfunction duration(h)'
t.eq.stoptimeh = 'Halt duration(h)'
t.eq.worktime = 'Functioning duration'
t.eq.stoptime = 'Halt duration'
t.eq.downtime = 'Malfunction duration'
t.eq.downcount = 'Malfunction counts'
t.eq.downrate = 'Malfunction rates'
t.eq.stoplost = 'Lost'
t.eq.ratio = 'percentage'
t.eq.time = 'time'
t.eq.timetrend = 'trend'
t.eq.nogap = 'no interval'
t.eq.monthgap = 'by month'
t.eq.daygap = 'by day'
t.eq.weekgap = 'by week'
t.eq.hourgap = 'by hour'
t.eq.workdurationratio = 'Functioning duration ratio' // '工作时长比率'
t.eq.stopdurationratio = 'Halt duration ratio' // '停机时长比率'
t.eq.stopratio = 'Halt ratio' // '停机比率'
t.eq.downdurationratio = 'Malfunction duration ratio' // '故障时长比率'
t.eq.speedefficiency = 'Speed launch rate' //'速度开动率'
t.eq.speedlost = 'Speed lost'
t.eq.timeefficiency = 'Time launch rate' //'时间开动率'
t.eq.year = 'year'
t.eq.month = 'month'
t.eq.realyield = 'Actual processing speed'
t.eq.designyield = 'Theoretical processing speed'
t.eq.viewtrend = 'View Trends'
t.eq.productQuality = 'Product Quality Analysis'
t.eq.productionAnalysis = 'Production Analysis'
t.eq.productQuantity = 'Product Quantity'
t.eq.line1= 'Line 1'
t.eq.line2= 'Line 2'
t.eq.line3= 'Line 3'
t.eq.line4= 'Line 4'
t.eq.sectionName = 'Section Name'
t.eq.equipmentName = 'Equipment Name'
t.eq.okNum = 'Qualified Quantity'
t.eq.nokNum = 'Unqualified Quantity'
t.eq.passRate = 'Qualified Rate'
t.eq.passRatePercent = 'Qualified Rate(%)'
t.pl = {}
t.pl.title = 'Product Line'
t.pl.id = 'Product Line ID'
t.pl.name = 'Product Line Name'
t.pl.sum = 'Sum'
t.pl.code = 'Product Line Code'
t.pl.status = 'Product Line Status'
t.pl.belong = 'Product Line'
t.pl.tvalue = 'TT Value'
t.pl.factoryHints = 'Please select a factory'
t.pl.process = 'Working procedure'
t.pl.add = 'Add Euipment'
t.pl.add2 = 'Add Comparison Euipment'
t.pl.queryFirst = 'Please Query First'
t.pl.choose = 'Please select equipment'
t.pl.confirm = 'Confirm'
t.pl.cancel = 'Cancel'
t.pl.success = 'The new device data is obtained successfully'
t.prompt = {}
t.prompt.title = 'Prompt'
t.prompt.info = 'Are you sure to {handle}?'
t.prompt.sure = 'Are you sure to delete this record?'
t.prompt.success = 'success'
t.prompt.failed = 'failed'
t.prompt.deleteBatch = 'Please choose items to delete.'
t.prompt.month = 'Please choose month'
t.validate = {}
t.validate.required = 'This is required.'
t.validate.format = '{attr} has a wrong format.'
t.validate.keyValueWarning = 'The value must be an integer between 0 and 100!'
t.validate.requiredRole = 'Choose at least one role'
t.upload = {}
t.upload.title = 'Upload Assets'
t.upload.text = 'Drag the file here, or <em> click Upload </em>'
t.upload.tip = 'Only support files with format: {format}'
t.upload.button = 'upload'
t.datePicker = {}
t.datePicker.range = 'to'
t.datePicker.start = 'Start Time'
t.datePicker.end = 'End Time'
t.datePicker.starttime = 'Start Time'
t.datePicker.endtime = 'End Time'
t.fullscreen = {}
t.fullscreen.prompt = 'This operation is not supported by your browser.'
t.updatePassword = {}
t.updatePassword.title = 'Update Password'
t.updatePassword.username = 'Username'
t.updatePassword.password = 'Current Password'
t.updatePassword.newPassword = 'New Password'
t.updatePassword.confirmPassword = 'Confirm Password'
t.updatePassword.validate = {}
t.updatePassword.validate.confirmPassword = 'The two passwords are different. Please check again.'
t.contentTabs = {}
t.contentTabs.closeCurrent = 'Close current tab'
t.contentTabs.closeOther = 'Close other tabs'
t.contentTabs.closeAll = 'Close all tabs'
/* 页面 */
t.notFound = {}
t.notFound.desc = 'Sorry! The page you\'re looking is missing.'
t.notFound.back = 'Back'
t.notFound.home = 'Home Page'
t.login = {}
t.login.title = 'Login'
t.login.username = 'Username'
t.login.password = 'Password'
t.login.captcha = 'Captcha'
t.login.demo = 'Demo'
// t.login.copyright = 'Copyright @Intelligent Automation Research Institute Co., Ltd Version: 1.0'
t.login.copyright = 'Copyright @VISHAKHA glass pvt Ltd Version: 1.0'
t.login.warning = 'Already Login!'
t.schedule = {}
t.schedule.beanName = 'Bean Name'
t.schedule.beanNameTips = 'spring bean name, eg: testTask'
t.schedule.pauseBatch = 'Pause'
t.schedule.resumeBatch = 'Resume'
t.schedule.runBatch = 'Run'
t.schedule.log = 'Log List'
t.schedule.params = 'Parameters'
t.schedule.cronExpression = 'cron expression'
t.schedule.cronExpressionTips = 'ex: 0 0 12 * * ?'
t.schedule.remark = 'Remark'
t.schedule.status = 'Status'
t.schedule.status0 = 'Pause'
t.schedule.status1 = 'Normal'
t.schedule.statusLog0 = 'Failed'
t.schedule.statusLog1 = 'Success'
t.schedule.pause = 'Pause'
t.schedule.resume = 'Resume'
t.schedule.run = 'Excute'
t.schedule.jobId = 'Job ID'
t.schedule.times = 'Time Cost (ms)'
t.schedule.createDate = 'Executed Tune' // ?
t.oss = {}
t.oss.config = 'Cloud storage configuration'
t.oss.upload = 'upload'
t.oss.url = 'url'
t.oss.createDate = 'Create Time'
t.oss.type = 'type'
t.oss.type1 = 'Qiniu'
t.oss.type2 = 'Aliyun'
t.oss.type3 = 'Tencent Cloud'
t.oss.qiniuDomain = 'Domain name'
t.oss.qiniuDomainTips = 'Bound domain name'
t.oss.qiniuPrefix = 'Prefix'
t.oss.qiniuPrefixTips = 'If no, the default value is null'
t.oss.qiniuAccessKey = 'AccessKey'
t.oss.qiniuAccessKeyTips = 'Qiniu AccessKey'
t.oss.qiniuSecretKey = 'SecretKey'
t.oss.qiniuSecretKeyTips = 'Qiniu SecretKey'
t.oss.qiniuBucketName = 'BucketName'
t.oss.qiniuBucketNameTips = 'Qiniu BucketName'
t.oss.aliyunDomain = 'Domain'
t.oss.aliyunDomainTips = 'Domain name bound to Ali Cloud, such ashttp://cdn.renren.io'
t.oss.aliyunPrefix = 'Prefix'
t.oss.aliyunPrefixTips = 'If no, the default value is null'
t.oss.aliyunEndPoint = 'EndPoint'
t.oss.aliyunEndPointTips = 'Aliyun EndPoint'
t.oss.aliyunAccessKeyId = 'AccessKeyId'
t.oss.aliyunAccessKeyIdTips = 'Aliyun AccessKeyId'
t.oss.aliyunAccessKeySecret = 'AccessKeySecret'
t.oss.aliyunAccessKeySecretTips = 'Aliyun AccessKeySecret'
t.oss.aliyunBucketName = 'BucketName'
t.oss.aliyunBucketNameTips = 'Aliyun BucketName'
t.oss.qcloudDomain = 'Domain'
t.oss.qcloudDomainTips = 'Tencent Cloud Domains'
t.oss.qcloudPrefix = 'Prefix'
t.oss.qcloudPrefixTips = 'If no, the default value is null'
t.oss.qcloudAppId = 'AppId'
t.oss.qcloudAppIdTips = 'Tencent Cloud AppId'
t.oss.qcloudSecretId = 'SecretId'
t.oss.qcloudSecretIdTips = 'Tencent Cloud SecretId'
t.oss.qcloudSecretKey = 'SecretKey'
t.oss.qcloudSecretKeyTips = 'Tencent Cloud SecretKey'
t.oss.qcloudBucketName = 'BucketName'
t.oss.qcloudBucketNameTips = 'Tencent Cloud BucketName'
t.oss.qcloudRegion = 'Region'
t.oss.qcloudRegionTips = 'Select'
t.oss.qcloudRegionBeijing1 = 'Beijing District 1 (North China)'
t.oss.qcloudRegionBeijing = 'Beijing'
t.oss.qcloudRegionShanghai = 'Shanghai (East China)'
t.oss.qcloudRegionGuangzhou = 'Guangzhou (South China)'
t.oss.qcloudRegionChengdu = 'Chengdu (Southwest)'
t.oss.qcloudRegionChongqing = 'Chongqing'
t.oss.qcloudRegionSingapore = 'Singapore'
t.oss.qcloudRegionHongkong = 'Hong Kong'
t.oss.qcloudRegionToronto = 'Toronto'
t.oss.qcloudRegionFrankfurt = 'Frankfurt'
t.dept = {}
t.dept.name = 'Department Name'
t.dept.parentName = 'Superior Department'
t.dept.sort = 'Sort'
t.dept.parentNameDefault = 'First tier department'
t.dept.chooseerror = 'Please select a department'
t.dept.title = 'Department Selection'
t.dict = {}
t.dict.dictName = 'Dictionary Name'
t.dict.dictType = 'Dictionary Type'
t.dict.dictLabel = 'Dictionary Label'
t.dict.dictValue = 'Dictionary Value'
t.dict.sort = 'Sort'
t.dict.remark = 'Remark'
t.dict.createDate = 'Create Time'
t.logError = {}
t.logError.requestUri = 'Request URL'
t.logError.requestMethod = 'Request Method'
t.logError.requestParams = 'Request Parameters'
t.logError.ip = 'IP'
t.logError.userAgent = 'User Agent'
t.logError.createDate = 'Create Time'
t.logError.errorInfo = 'Exceptions'
t.logLogin = {}
t.logLogin.creatorName = 'User Name'
t.logLogin.status = 'Status'
t.logLogin.status0 = 'Failed'
t.logLogin.status1 = 'Success'
t.logLogin.status2 = 'Account has been locked'
t.logLogin.operation = 'Operation Type'
t.logLogin.operation0 = 'Login'
t.logLogin.operation1 = 'Logout'
t.logLogin.ip = 'IP'
t.logLogin.userAgent = 'User-Agent'
t.logLogin.createDate = 'Create Time'
t.logOperation = {}
t.logOperation.status = 'Status'
t.logOperation.status0 = 'Failed'
t.logOperation.status1 = 'Success'
t.logOperation.creatorName = 'User Name'
t.logOperation.operation = 'User Operations'
t.logOperation.requestUri = 'Request URL'
t.logOperation.requestMethod = 'Request Method'
t.logOperation.requestParams = 'Request Parameters'
t.logOperation.requestTime = 'Request Duration'
t.logOperation.ip = 'IP'
t.logOperation.userAgent = 'User-Agent'
t.logOperation.createDate = 'Create Time'
t.menu = {}
t.menu.name = 'Chinese Name'
t.menu.nameEn = 'Name'
t.menu.icon = 'Icons'
t.menu.type = 'Type'
t.menu.type0 = 'Menu'
t.menu.type1 = 'Button'
t.menu.sort = 'Sort'
t.menu.url = 'Route'
t.menu.permissions = 'Authorization Identifier'
t.menu.permissionsTips = 'Multiple are separated by commas, such as:sys:menu:save,sys:menu:update'
t.menu.parentName = 'Superior menu'
t.menu.parentNameDefault = 'First tier menu'
t.menu.resource = 'Authorized Resource'
t.menu.resourceUrl = 'Resource URL'
t.menu.resourceMethod = 'Request methods'
t.menu.resourceAddItem = 'Add Item'
t.params = {}
t.params.name = 'Parameter Name'
t.params.code = 'Parameter Code'
t.params.paramCode = 'Parameter Code'
t.params.paramValue = 'Parameter Value'
t.params.paramStdValue = 'Standard Parameter Code'
t.params.plctitle = 'PLC Collection Parameters'
t.params.plcid = 'PLC ID'
t.params.remark = 'Remark'
t.role = {}
t.role.name = 'Role Name'
t.role.remark = 'Remark'
t.role.createDate = 'Create Time'
t.role.menuList = 'Menu authorization' // ?
t.role.deptList = 'Data authorization' // ?
t.user = {}
t.user.username = 'User Name'
t.user.deptName = 'Department'
t.user.email = 'Email'
t.user.mobile = 'Phone'
t.user.status = 'Status'
t.user.status0 = 'Pause' // ?
t.user.status1 = 'Normal'
t.user.createDate = 'Create Time'
t.user.password = 'Password'
t.user.confirmPassword = 'Confirm Password'
t.user.realName = 'Actual Name'
t.user.gender = 'Gender'
t.user.gender0 = 'male'
t.user.gender1 = 'female'
t.user.gender2 = 'secret'
t.user.roleIdList = 'Role Configurations'
t.user.validate = {}
t.user.validate.confirmPassword = 'The two passwords are different. Please check again.'
t.user.select = 'Select an user'
t.user.selecterror = 'Pick up a record'
t.user.userTable = ' User Table'
export default t

View File

@ -1,9 +1,18 @@
/*
* @Descripttion:
* @version:
* @Author: fzq
* @Date: 2022-11-25 09:51:46
* @LastEditors: fzq
* @LastEditTime: 2023-01-12 11:19:00
*/
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import Cookies from 'js-cookie'
import zhCNLocale from 'element-ui/lib/locale/lang/zh-CN'
import enLocale from 'element-ui/lib/locale/lang/en'
import zhCN from './zh-CN'
import en from './en'
Vue.use(VueI18n)
export const messages = {
@ -11,10 +20,39 @@ export const messages = {
'_lang': '简体中文',
...zhCN,
...zhCNLocale
},
'en': {
'_lang': 'English',
...en,
...enLocale
}
}
export function getLanguage() {
if (Cookies.get('language')) {
return Cookies.get('language')
}
// if has not choose language
const language = (navigator.language || navigator.browserLanguage)
const locales = Object.keys(messages)
for (const locale of locales) {
if (language.indexOf(locale) > -1) {
Cookies.set('language', locale)
return locale
}
}
Cookies.set('language', 'en')
return 'en'
}
export default new VueI18n({
locale: Cookies.get('language') || 'zh-CN',
messages
// 默认语言
locale: Cookies.get('language') || 'en',
locale: getLanguage(), // 先默认中文
messages,
//抑制警告
silentFallbackWarn: true,
})

View File

@ -1,39 +1,448 @@
const t = {}
t.loading = '加载中...'
t.createTime = '添加时间'
t.brand = {}
t.brand.lg = '人人权限系统'
t.brand.mini = '人人'
t.brand.lg = '深加工SCADA平台'
t.brand.mini = 'SCADA'
t.brand.home = '首页'
t.routes = {}
// 一级
t.routes['产品池'] = '产品池'
t.routes['基本资料'] = '基本资料'
t.routes['设备数采'] = '设备数采'
t.routes['厂务管理'] = '厂务管理'
t.routes['报表管理'] = '报表管理'
t.routes['质量管理'] = '质量管理'
t.routes['权限管理'] = '权限管理'
t.routes['系统设置'] = '系统设置'
t.routes['日志管理'] = '日志管理'
t.routes['数据分析'] = '数据分析'
// 二级
t.routes['厂务'] = '厂务'
t.routes['设备'] = '设备'
t.routes['字典管理'] = '字典管理'
t.routes['PLC信息'] = 'PLC信息'
t.routes['设备与PLC关联配置'] = '设备与PLC关联配置' // ?
t.routes['近24小时设备生产数据'] = '近24小时设备生产数据'
t.routes['近24小时产线生产数据'] = '近24小时产线生产数据'
t.routes['近24小时质量检查数据'] = '近24小时质量检查数据'
t.routes['报表总览'] = '报表总览'
t.routes['报表分类'] = '报表分类'
t.routes['报表详情'] = '报表详情'
t.routes['报表设计'] = '报表设计'
t.routes['报表预览'] = '报表预览'
t.routes['质量检测基础数据'] = '质量检测基础数据'
t.routes['当前检测数据'] = '当前检测数据'
t.routes['检测统计数据'] = '检测统计数据'
t.routes['质量检查信息记录'] = '质量检查信息记录'
t.routes['用户管理'] = '用户管理'
t.routes['部门管理'] = '部门管理'
t.routes['角色管理'] = '角色管理'
t.routes['菜单管理'] = '菜单管理'
t.routes['参数管理'] = '参数管理'
t.routes['定时任务'] = '定时任务'
t.routes['文件上传'] = '文件上传'
t.routes['登录日志'] = '登录日志'
t.routes['操作日志'] = '操作日志'
t.routes['设备效率分析'] = '设备效率分析'
t.routes['设备异常分析'] = '设备异常分析'
t.routes['设备状态时序图'] = '设备状态时序图'
t.routes['产品质量分析'] = '产品质量分析'
t.routes['产量分析'] = '产量分析'
t.routes['生产节拍时序图'] = '生产节拍时序图'
t.routes['设备产量时序图'] = '设备产量时序图'
// 三级
t.routes['工厂'] = '工厂'
t.routes['产线'] = '产线'
t.routes['工段'] = '工段'
t.routes['设备类型'] = '设备类型'
t.routes['设备分组'] = '设备分组'
t.routes['设备信息'] = '设备信息'
t.routes['设备参数状态监控'] = '设备参数状态监控'
t.routes['设备分组报警信息'] = '设备分组报警信息'
t.routes['设备历史参数'] = '设备历史参数'
t.routes['质量检测类型'] = '质量检测类型'
t.routes['质量检测信息'] = '质量检测信息'
t.routes['安灯检测盒'] = '安灯检测盒'
t.andeng = {}
t.andeng.inspectContent = '检测内容'
t.andeng.btnVal = '按钮值'
t.andeng.btnBoxModel = '按钮盒模式'
t.copyright = 'VISHAKHA glass pvt Ltd'
t.dictValueList = '查看值列表'
t.save = '保存'
t.add = '新增' // 1
t.delete = '删除' // 1
t.deleteBatch = '批量删除' // 1
t.update = '修改' // 1
t.query = '查询' // 1
t.export = '导出' // 1
t.handle = '操作' // 1
t.confirm = '确定' // 1
t.cancel = '取消' // 1
t.clear = '清除' // 1
t.logout = '退出' // 1
t.manage = '处理' // 1
t.createDate = '创建时间' // 1
t.keyword = '关键字:' // 1
t.choose = '请选择' // 1
t.remark = '备注' // 1
t.delMark = '删除标志' // 0
t.isvalid = '是否有效' // 0
t.available = '可用' // 0
t.unavailable = '不可用' // 0
t.alert = '弹窗' // 0
t.creator = '创建人' // 1
t.creatorName = '创建人姓名' // 1
t.updator = '更新人' // 1
t.updatorName = '更新人姓名' // 1
t.updateTime = '更新时间'
t.version = '版本号' // 1
t.search = '查询' // 1
t.countPerPage = '每页数' // ?
t.currentPage = '当前页' // ?
t.fetchList = '获取数据列表' // ?
t.multi = '多选' // ?
t.do = '进行' // ?
t.submit = '表单提交' // ?
t.desc = '描述' // 1
t.disable = '停用' // 1
t.equipment = '设备' // 1
t.enabled = '启用状态' // ?
t.cannotempty = '不能为空' // ?
t.parameter = '参数名' // 1
t.enable = '启用' // 1
t.index = '序号' // 1
t.relation = '关联' // ?
t.fetchInfo = '获取信息' // ?
t.name = '名称' // 1
t.code = '编码' // 1
t.attrName = '属性名称' // 1
t.attrValue = '属性值' // 1
t.unit = '单位' // 1
t.table = '表' // 1
t.table2 = '表格' // 1
t.downloadurl = '下载地址' // 1
t.recordTime = '记录时间' // 1
t.notCollect = '不采集' // 1
t.collect = '采集' // 1
t.required = '必填' // 1
t.paramUrl = '参数地址' // 1
t.enname = '英文名称' // 1
t.collectOrNot = '是否采集' // 1
t.min = '最小值' // 1
t.max = '最大值' // 1
t.status = '状态' // 1
t.normal = '正常' // ?
t.shutdown = '停机' // ?
t.malfunction = '故障' // ?
t.diagram = '设备状态时序图'
t.diagram2 = '设备产量时序图'
t.addr = '地址' // 1
t.planStop = '计划停机' // ?
t.startTime = '开始时间' // 1
t.endTime = '结束时间' // 1
t.to = '至' // 1
t.today = '今天' // 1
t.time = '选择时间'
t.eqId = '当前设备ID:'
t.ti = '时间'
t.plcCode = 'PLC 编码'
t.equName = '设备名称'
t.equCode = '设备编码'
t.yAxisTime = '时间 (h)'
t.yAxisRate = '百分比 (%)'
t.hourTime = '(时)'
t.graph = '图形'
t.category = '分类'
t.categoryName = '分类名称'
t.categoryCode = '分类编码'
t.rate = '比例'
t.link = '链接地址'
t.refresh = '刷新'
t.abbr = '缩写'
t.detail = '详情'
t.viewdetail = '查看详情'
t.viewattr = '查看属性'
t.edit = '编辑'
t.source = '来源'
t.auto = '自动'
t.manual = '手动'
t.loaddone = '加载完成'
t.produceTime = '生产日期'
t.enterTime = '进厂日期'
t.manufacturer = '制造商'
t.success = '修改成功!'
t.all = '全部'
t.reset = '重置'
t.preview = '预览'
t.design = '设计'
t.timetype = '时间类型'
t.reftimerange = '按时间段'
t.refdate = '按日期'
t.hour = '小时'
t.yes = '是'
t.no = '否'
t.LoginRecords = ' 登录日志'
t.operationsRecords = ' 操作日志'
t.allIcons= '所有图标'
t.err= '错误'
t.errors = {}
t.errors.nosection = '该产线没有工段'
t.errors.numsection = '该产线有{num}条工段'
t.errors.nodata = '没有查询到相关数据!'
t.hints = {}
t.hints.input = '请输入'
t.hints.select = '请选择'
t.hints.date = '请选择日期'
t.hints.checktime = '请选择检测时间'
t.hints.number = '请输入正确的数值'
t.hints.integer = '请输入正确的整数'
t.hints.addr = '请输入地址'
t.hints.upload2m = '上传文件大小不要超过 2MB (2048KB)'
t.hints.upload2mPic = '上传图片文件,且大小不要超过 2MB (2048KB)'
t.factory = {}
t.factory.title = '工厂'
t.factory.name = '工厂名称'
t.factory.code = '工厂编码'
t.prod = {}
t.prod.id = '产品ID'
t.prod.name = '产品名称'
t.prod.code = '产品编码'
t.prod.type = '产品类型'
t.prod.area = '单位平方数'
t.prod.spec = '规格'
t.prod.attr = '属性'
t.prod.attrcode = '属性编码'
t.prod.attrcodeHints = '请输入属性编码'
t.prod.attrname = '属性名称'
t.prod.attrnameHints = '请输入属性名称'
t.prod.attrvalueHints = '请输入属性值'
t.prod.descHints = '请输入描述'
// t.prod.processTime = '加工时间 (h)'
t.prod.processTime = '产线完成单位产品用时 (s)'
t.prod.processTimeHints = '请输入完成单位产品用时'
// t.prod.processTimeHints = '请输入加工时间'
t.prod.relatedPid = '关联产品'
t.alarm = {}
t.alarm.name = '报警'
t.alarm.info = '报警信息'
t.alarm.view = '查看报警'
t.alarm.eq = '报警设备'
t.alarm.type = '报警类型'
t.alarm.code = '报警编码'
t.alarm.level = '报警级别'
t.alarm.content = '报警内容'
t.alarm.source = '报警来源'
t.alarm.det = '报警详细内容'
t.alarm.externalCode = '外部编码'
t.alarm.description = '描述'
t.alarm.remark = '备注'
t.report = {}
t.report.name = '报表名称'
t.report.det = '报表内容'
t.report.type = '报表分类'
t.report.code = '报表编码'
t.report.lnk = '链接地址'
t.inspect = {}
t.inspect.type = '检测类型'
t.inspect.code = '检测编码'
t.inspect.det = '检测内容'
t.inspect.detcode = '内容编码'
t.inspect.people = '检测人员'
t.inspect.time = '检测时间'
t.inspect.typetotal = '检测类型总数'
t.inspect.typename = '检测类型名称'
t.inspect.typecode = '检测类型编码'
t.inspect.ioTotal = '上下片及检测总数统计'
t.inspect.plTotal = '各产线检测内容统计'
t.inspect.inTotal = '上片总数'
t.inspect.outTotal = '下片总数'
t.inspect.checkTotal = '检测总数'
t.inspect.rate = '比例'
t.inspect.typeCount = '检测类型统计数据'
t.realtime = {}
t.realtime.eq = '近24小时产线生产数据'
t.realtime.pl = '近24小时产线生产数据'
t.realtime.inspect = '近24小时质量检查数据'
t.realtime.in = '进数据'
t.realtime.out = '出数据'
t.realtime.data = '报废数据'
t.realtime.num = '报废数量'
t.realtime.rate = '报废比例'
t.realtime.total = '设备总产量'
t.realtime.goodrate = '良品率'
t.realtime.runState = '是否运行'
t.realtime.state = '状态'
t.realtime.hasFault = '是否故障'
t.realtime.recentParamValue = '参数近期值'
t.realtime.view = '查看'
t.realtime.input = '投入数'
t.realtime.output = '产出数'
t.realtime.eqName = '设备名称'
t.realtime.eqCode = '设备编码'
t.realtime.productionSnapshotTime = '生产量记录时间'
t.realtime.statusSnapshotTime = '状态记录时间'
t.realtime.refresh = '刷新数据'
t.ws = {}
t.ws.title = '工段'
t.ws.id = '工段ID'
t.ws.name = '工段名称'
t.ws.code = '工段编码'
t.ws.binded = '已绑定的设备'
t.ws.unbind = '设备名称'
t.ws.eqbindplaceholder = '选择一个设备进行绑定'
t.ws.sort = '工段排序'
t.ws.setorder = '请输入工段中设备的顺序'
t.ws.bind = '绑定'
t.ws.eqbind = '设备绑定'
t.ws.belong = '所属产线'
t.file = {}
t.file.title = '文件'
t.file.name = '文件名称'
t.file.code = '文件编号'
t.file.typeName = '文件类型名称'
t.file.typeCode = '文件类型编号'
t.eq = {}
t.eq.title = '设备'
t.eq.id = '设备ID'
t.eq.name = '设备名称'
t.eq.code = '设备编码'
t.eq.type = '设备类型'
t.eq.grade = '设备规格'
t.eq.group = '设备分组'
t.eq.groupname = '分组名称'
t.eq.groupcode = '分组编码'
t.eq.excode = '设备外部代码'
t.eq.input = '上片数据设备'
t.eq.output = '下片数据设备'
t.eq.tvalue = '设备TT值'
t.eq.processingTime = '单件产品加工时间(秒)'
t.eq.dtype = '数据类别'
t.eq.dtypenone = '无类别'
t.eq.dtypeinput = '上片数据设备'
t.eq.dtypeoutput = '下片数据设备'
t.eq.upload = '上传资料'
t.eq.image = '设备图片'
t.eq.viewattr = '查看设备属性'
t.eq.plcbarcode = 'plc条码'
t.eq.plccode = 'PLC编码'
t.eq.plcname = 'PLC名称'
t.eq.port = '端口'
t.eq.type = '类型名称'
t.eq.typecode = '类型编码'
t.eq.parent = '父类'
t.eq.mtbf = '平均故障间隔时间[MTBF] (h)'
t.eq.mttr = '平均维修时间[MTTR] (h)'
t.eq.efficienttimeh = '有效时间(h)'
t.eq.shutdowntimeh = '关机时间(h)'
t.eq.worktimeh = '工作时长(h)'
t.eq.downtimeh = '故障时长(h)'
t.eq.stoptimeh = '停机时长(h)'
t.eq.worktime = '工作时长'
t.eq.stoptime = '停机时长'
t.eq.downtime = '故障时长'
t.eq.downcount = '故障次数'
t.eq.downrate = '故障比率'
t.eq.stoplost = '中断损失'
t.eq.ratio = '百分比'
t.eq.time = '时间'
t.eq.timetrend = '时间区间走势'
t.eq.nogap = '无间隔'
t.eq.monthgap = '按月'
t.eq.daygap = '按天'
t.eq.weekgap = '按周'
t.eq.hourgap = '按小时'
t.eq.workdurationratio = '工作时长比率'
t.eq.stopdurationratio = '停机时长比率'
t.eq.stopratio = '停机比率'
t.eq.downdurationratio = '故障时长比率'
t.eq.speedefficiency = '速度开动率'
t.eq.speedlost = '速度损失'
t.eq.timeefficiency = '时间开动率'
t.eq.year='年'
t.eq.month='月'
t.eq.realyield = '实际加工速度'
t.eq.designyield = '理论加工速度'
t.eq.viewtrend = '查看趋势'
t.eq.productQuality = '产品质量分析'
t.eq.productionAnalysis = '产量分析'
t.eq.productQuantity = '产品数量'
t.eq.line1= '产线1'
t.eq.line2= '产线2'
t.eq.line3= '产线3'
t.eq.line4= '产线4'
t.eq.sectionName = '工序'
t.eq.equipmentName = '设备名称'
t.eq.okNum = '合格数量'
t.eq.nokNum = '不合格数量'
t.eq.passRate = '合格率'
t.eq.passRatePercent = '合格率(%)'
t.pl = {}
t.pl.title = '产线'
t.pl.id = '产线ID'
t.pl.name = '产线名称'
t.pl.sum = '合计'
t.pl.code = '产线编码'
t.pl.status = '产线状态'
t.pl.belong = '所属产线'
t.pl.tvalue = '产线TT值(每小时下片数量)'
t.pl.factoryHints = '请选择所属工厂'
t.pl.process = '工序'
t.pl.add = '添加设备'
t.pl.add2 = '添加对比设备'
t.pl.queryFirst = '请先查询数据'
t.pl.success = '新设备数据获取成功'
t.pl.choose = '请选择设备'
t.pl.confirm = '确定'
t.pl.cancel = '取消'
t.add = '新增'
t.delete = '删除'
t.deleteBatch = '删除'
t.update = '修改'
t.query = '查询'
t.export = '导出'
t.handle = '操作'
t.confirm = '确定'
t.cancel = '取消'
t.clear = '清除'
t.logout = '退出'
t.manage = '处理'
t.createDate = '创建时间'
t.keyword = '关键字:'
t.choose = '请选择'
t.prompt = {}
t.prompt.title = '提示'
t.prompt.info = '确定进行[{handle}]操作?'
t.prompt.sure = '确定删除这条记录吗?'
t.prompt.success = '操作成功'
t.prompt.failed = '操作失败'
t.prompt.deleteBatch = '请选择删除项'
t.prompt.month = '请选择月份'
t.validate = {}
t.validate.required = '必填项不能为空'
t.validate.format = '{attr}格式错误'
t.validate.keyValueWarning = '该数值必须是100以内的正整数'
t.validate.requiredRole = '至少选择一个角色'
t.upload = {}
t.upload.title = '上传资料'
t.upload.text = '将文件拖到此处,或<em>点击上传</em>'
t.upload.tip = '只支持{format}格式文件!'
t.upload.button = '点击上传'
@ -42,6 +451,8 @@ t.datePicker = {}
t.datePicker.range = '至'
t.datePicker.start = '开始日期'
t.datePicker.end = '结束日期'
t.datePicker.starttime = '开始时间'
t.datePicker.endtime = '结束时间'
t.fullscreen = {}
t.fullscreen.prompt = '您的浏览器不支持此操作'
@ -72,7 +483,9 @@ t.login.username = '用户名'
t.login.password = '密码'
t.login.captcha = '验证码'
t.login.demo = '在线演示'
t.login.copyright = '人人开源'
// t.login.copyright = '版权所有:中建材智能自动化研究院有限公司 版本: 1.0'
t.login.copyright = '版权所有VISHAKHA glass pvt Ltd 版本: 1.0'
t.login.warning = '已经登录过了'
t.schedule = {}
t.schedule.beanName = 'bean名称'
@ -171,7 +584,7 @@ t.dict.remark = '备注'
t.dict.createDate = '创建时间'
t.logError = {}
t.logError.requestUri = '请求URI'
t.logError.requestUri = '请求URL'
t.logError.requestMethod = '请求方式'
t.logError.requestParams = '请求参数'
t.logError.ip = '操作IP'
@ -198,7 +611,7 @@ t.logOperation.status0 = '失败'
t.logOperation.status1 = '成功'
t.logOperation.creatorName = '用户名'
t.logOperation.operation = '用户操作'
t.logOperation.requestUri = '请求URI'
t.logOperation.requestUri = '请求URL'
t.logOperation.requestMethod = '请求方式'
t.logOperation.requestParams = '请求参数'
t.logOperation.requestTime = '请求时长'
@ -207,7 +620,8 @@ t.logOperation.userAgent = 'User-Agent'
t.logOperation.createDate = '创建时间'
t.menu = {}
t.menu.name = '名称'
t.menu.name = '中文名'
t.menu.nameEn = '英文名'
t.menu.icon = '图标'
t.menu.type = '类型'
t.menu.type0 = '菜单'
@ -224,8 +638,13 @@ t.menu.resourceMethod = '请求方式'
t.menu.resourceAddItem = '添加一项'
t.params = {}
t.params.name = '参数名称'
t.params.code = '参数编码'
t.params.paramCode = '编码'
t.params.paramValue = '值'
t.params.paramStdValue = '参数设定标准值'
t.params.plctitle = 'PLC采集参数'
t.params.plcid = 'PLC连接表ID'
t.params.remark = '备注'
t.role = {}
@ -256,6 +675,7 @@ t.user.validate = {}
t.user.validate.confirmPassword = '确认密码与密码输入不一致'
t.user.select = '选择用户'
t.user.selecterror = '请选择一条记录'
t.user.userTable = ' 用户表'
export default t

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,30 @@
/*
* @Descripttion:
* @version:
* @Author: fzq
* @Date: 2022-12-13 21:01:02
* @LastEditors: fzq
* @LastEditTime: 2023-01-11 10:47:26
*/
import './iconfont'
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg component
// register globally
Vue.component('svg-icon', SvgIcon)
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)
// 这里注释掉了
// const svgFiles = require.context('./svg', true, /\.svg$/)
// svgFiles.keys().map(item => svgFiles(item))
export default {
// 获取图标icon-(*).svg名称列表, 例如[shouye, xitong, zhedie, ...]
getNameList() {
return requireAll(req).map(item => item.default.id.replace('icon-', ''))
}
}
const svgFiles = require.context('./svg', true, /\.svg$/)
svgFiles.keys().map(item => svgFiles(item))

2
src/icons/svg/chrome.svg Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1660620397071" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="964" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); }
</style></defs><path d="M87.788 227.913c17.049 29.189 34.039 58.291 51.043 87.383 51.784 88.596 103.585 177.181 155.325 265.804 2.62 4.485 5.062 9.143 7 13.955C349.786 715.89 484.618 771.244 604.34 719.47c2.398-1.037 4.887-1.861 9.302-3.526-2.588 4.897-4.038 7.89-5.7 10.755-54.798 94.487-109.707 188.908-164.246 283.545-4.133 7.171-8.493 8.259-15.899 6.935-206.01-36.867-364.332-183.492-412.98-387.026-33.681-140.916-9.465-273.513 67.799-396.221a55.282 55.282 0 0 1 2.993-4.263c0.41-0.532 1.065-0.875 2.179-1.756zM637.574 322.251c4.879-0.232 7.832-0.494 10.785-0.495 109.636-0.021 219.273 0.08 328.908-0.221 8.034-0.021 11.143 2.592 13.896 9.949 77.165 206.263 15.492 437.682-155.167 576.728-99.718 81.243-214.648 119.245-343.254 115.541-4.101-0.116-8.19-0.579-13.782-0.991 2.282-4.327 3.863-7.594 5.678-10.723 73.799-127.297 147.568-254.609 221.459-381.853 61.326-105.603 35.165-231.359-63.311-303.663-1.275-0.936-2.452-2.003-5.212-4.272zM970.66 284.978h-15.17c-145.492 0-290.984-0.444-436.474 0.156-97.432 0.401-169.373 44.268-212.233 132.11-11.095 22.739-15.798 48.603-23.28 72.528-0.437-0.663-2.509-3.517-4.279-6.546-54.593-93.406-109.079-186.878-163.896-280.152-3.852-6.555-3.331-10.476 1.434-16.115C205.093 82.393 316.58 20.463 452.687 3.72c207.799-25.561 413.84 82.445 511.367 267.993 1.915 3.643 3.675 7.368 6.606 13.265zM702.425 512.551c-0.178 106.027-85.601 189.996-193.057 189.771-103.007-0.212-187.656-86.695-187.287-191.343 0.373-106.007 85.766-189.459 193.555-189.154 102.551 0.287 186.962 86.481 186.789 190.726z" p-id="965"></path></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,2 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1660620397071" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="964" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); }
</style></defs><path d="M87.788 227.913c17.049 29.189 34.039 58.291 51.043 87.383 51.784 88.596 103.585 177.181 155.325 265.804 2.62 4.485 5.062 9.143 7 13.955C349.786 715.89 484.618 771.244 604.34 719.47c2.398-1.037 4.887-1.861 9.302-3.526-2.588 4.897-4.038 7.89-5.7 10.755-54.798 94.487-109.707 188.908-164.246 283.545-4.133 7.171-8.493 8.259-15.899 6.935-206.01-36.867-364.332-183.492-412.98-387.026-33.681-140.916-9.465-273.513 67.799-396.221a55.282 55.282 0 0 1 2.993-4.263c0.41-0.532 1.065-0.875 2.179-1.756zM637.574 322.251c4.879-0.232 7.832-0.494 10.785-0.495 109.636-0.021 219.273 0.08 328.908-0.221 8.034-0.021 11.143 2.592 13.896 9.949 77.165 206.263 15.492 437.682-155.167 576.728-99.718 81.243-214.648 119.245-343.254 115.541-4.101-0.116-8.19-0.579-13.782-0.991 2.282-4.327 3.863-7.594 5.678-10.723 73.799-127.297 147.568-254.609 221.459-381.853 61.326-105.603 35.165-231.359-63.311-303.663-1.275-0.936-2.452-2.003-5.212-4.272zM970.66 284.978h-15.17c-145.492 0-290.984-0.444-436.474 0.156-97.432 0.401-169.373 44.268-212.233 132.11-11.095 22.739-15.798 48.603-23.28 72.528-0.437-0.663-2.509-3.517-4.279-6.546-54.593-93.406-109.079-186.878-163.896-280.152-3.852-6.555-3.331-10.476 1.434-16.115C205.093 82.393 316.58 20.463 452.687 3.72c207.799-25.561 413.84 82.445 511.367 267.993 1.915 3.643 3.675 7.368 6.606 13.265zM702.425 512.551c-0.178 106.027-85.601 189.996-193.057 189.771-103.007-0.212-187.656-86.695-187.287-191.343 0.373-106.007 85.766-189.459 193.555-189.154 102.551 0.287 186.962 86.481 186.789 190.726z" p-id="965" fill="#fff"></path></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="选择" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="首页选择" transform="translate(-1492.000000, -20.000000)" fill-rule="nonzero">
<g id="banner/top" transform="translate(1.000000, -0.000000)">
<g id="倒计时" transform="translate(1491.000000, 20.000000)">
<rect id="矩形" fill="#000000" opacity="0" x="0" y="0" width="24" height="24"></rect>
<path d="M18.6251339,2.5 L18.7173046,2.506884 C19.0181775,2.55223577 19.25,2.81622235 19.25,3.13636364 C19.25,3.48849651 18.9695089,3.77267387 18.6250952,3.77272728 L18.6250952,3.77272728 L17.500134,3.77272728 L17.500134,6.68181819 L17.4950738,6.93194703 C17.4134263,8.92636566 16.3486624,10.7533909 14.6512846,11.7864428 L14.6512846,11.7864428 L14.3002984,12.0000588 L14.6513368,12.2135889 L14.8602283,12.3467668 C16.5045868,13.4445685 17.5015027,15.3107448 17.500134,17.3180114 L17.500134,17.3180114 L17.500134,20.2272727 L18.6251339,20.2272727 L18.7173078,20.2341693 C19.0181892,20.2795564 19.25,20.5435156 19.25,20.8636364 C19.25,21.2157918 18.9694948,21.5 18.6251339,21.5 L18.6251339,21.5 L4.62513396,21.5 L4.53296333,21.493116 C4.23209038,21.4477642 4.00026791,21.1837777 4.00026791,20.8636364 C4.00026791,20.5115035 4.28075902,20.2273261 4.62517273,20.2272727 L4.62517273,20.2272727 L5.75013395,20.2272727 L5.75013395,17.3181818 L5.75519413,17.068053 C5.8368416,15.0736343 6.90160547,13.2466092 8.59898334,12.2135572 L8.59898334,12.2135572 L8.94996946,11.9999412 L8.59893115,11.7864111 L8.39003962,11.6532332 C6.74568111,10.5554315 5.74876521,8.68925518 5.75013389,6.68198865 L5.75013389,6.68198865 L5.75013395,3.77272728 L4.62513396,3.77272728 L4.53097506,3.76549115 C4.34557884,3.73677723 4.18042961,3.62417437 4.08444297,3.45578133 C3.97185234,3.2582593 3.97185234,3.01446799 4.08444297,2.81694595 C4.196414,2.6205109 4.40253386,2.5 4.62513396,2.5 L4.62513396,2.5 L18.6251339,2.5 Z M11.6309675,12.6364317 L11.4133705,12.641183 C8.9566894,12.7532313 7.00013396,14.805007 7.00013396,17.3181818 L7.00013396,17.3181818 L7.00013396,20.2272727 L16.2501339,20.2272727 L16.2501339,17.3181818 L16.2450986,17.0982663 C16.1348575,14.6926999 14.227663,12.7467226 11.8259996,12.6410372 L11.8259996,12.6410372 L11.6309675,12.6364317 Z M16.2501339,3.77272728 L7.00013396,3.77272728 L7.00013396,6.68181819 L7.00489156,6.89606874 C7.1155058,9.38167112 9.1410632,11.3636364 11.625134,11.3636364 L11.625134,11.3636364 L11.8208425,11.3591365 L12.0382189,11.3444826 C14.4134338,11.1283734 16.2499952,9.11397106 16.2501339,6.68183244 L16.2501339,6.68183244 L16.2501339,3.77272728 Z" id="形状结合" fill="#FFFFFF"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="1_基础资料" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="1-1工厂信息" transform="translate(-1446.000000, -20.000000)" fill="#000000" fill-rule="nonzero">
<g id="banner/top/栏" transform="translate(336.000000, 0.000000)">
<g id="编组-5" transform="translate(944.000000, 15.000000)">
<g id="倒计时" transform="translate(166.000000, 5.000000)">
<rect id="矩形" opacity="0" x="0" y="0" width="24" height="24"></rect>
<path d="M18.6251339,2.5 L18.7173046,2.506884 C19.0181775,2.55223577 19.25,2.81622235 19.25,3.13636364 C19.25,3.48849651 18.9695089,3.77267387 18.6250952,3.77272728 L18.6250952,3.77272728 L17.500134,3.77272728 L17.500134,6.68181819 L17.4950738,6.93194703 C17.4134263,8.92636566 16.3486624,10.7533909 14.6512846,11.7864428 L14.6512846,11.7864428 L14.3002984,12.0000588 L14.6513368,12.2135889 L14.8602283,12.3467668 C16.5045868,13.4445685 17.5015027,15.3107448 17.500134,17.3180114 L17.500134,17.3180114 L17.500134,20.2272727 L18.6251339,20.2272727 L18.7173078,20.2341693 C19.0181892,20.2795564 19.25,20.5435156 19.25,20.8636364 C19.25,21.2157918 18.9694948,21.5 18.6251339,21.5 L18.6251339,21.5 L4.62513396,21.5 L4.53296333,21.493116 C4.23209038,21.4477642 4.00026791,21.1837777 4.00026791,20.8636364 C4.00026791,20.5115035 4.28075902,20.2273261 4.62517273,20.2272727 L4.62517273,20.2272727 L5.75013395,20.2272727 L5.75013395,17.3181818 L5.75519413,17.068053 C5.8368416,15.0736343 6.90160547,13.2466092 8.59898334,12.2135572 L8.59898334,12.2135572 L8.94996946,11.9999412 L8.59893115,11.7864111 L8.39003962,11.6532332 C6.74568111,10.5554315 5.74876521,8.68925518 5.75013389,6.68198865 L5.75013389,6.68198865 L5.75013395,3.77272728 L4.62513396,3.77272728 L4.53097506,3.76549115 C4.34557884,3.73677723 4.18042961,3.62417437 4.08444297,3.45578133 C3.97185234,3.2582593 3.97185234,3.01446799 4.08444297,2.81694595 C4.196414,2.6205109 4.40253386,2.5 4.62513396,2.5 L4.62513396,2.5 L18.6251339,2.5 Z M11.6309675,12.6364317 L11.4133705,12.641183 C8.9566894,12.7532313 7.00013396,14.805007 7.00013396,17.3181818 L7.00013396,17.3181818 L7.00013396,20.2272727 L16.2501339,20.2272727 L16.2501339,17.3181818 L16.2450986,17.0982663 C16.1348575,14.6926999 14.227663,12.7467226 11.8259996,12.6410372 L11.8259996,12.6410372 L11.6309675,12.6364317 Z M16.2501339,3.77272728 L7.00013396,3.77272728 L7.00013396,6.68181819 L7.00489156,6.89606874 C7.1155058,9.38167112 9.1410632,11.3636364 11.625134,11.3636364 L11.625134,11.3636364 L11.8208425,11.3591365 L12.0382189,11.3444826 C14.4134338,11.1283734 16.2499952,9.11397106 16.2501339,6.68183244 L16.2501339,6.68183244 L16.2501339,3.77272728 Z" id="形状结合"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="1_基础资料">
<g id="1-1工厂信息" transform="translate(-1580.000000, -20.000000)">
<g id="banner/top/栏" transform="translate(336.000000, 0.000000)">
<g id="编组-5" transform="translate(944.000000, 15.000000)">
<g id="下载" transform="translate(300.000000, 5.000000)">
<rect id="矩形" opacity="0" x="0" y="0" width="24" height="24"></rect>
<path d="M7.6875,13.5 L11.25,13.5 L11.25,3.75 C11.25,3.33578644 11.5857864,3 12,3 C12.4142136,3 12.75,3.33578644 12.75,3.75 L12.75,13.5 L12.75,13.5 L16.3125,13.5 L12,18 L7.6875,13.5 Z M20.25,12 C19.8357864,12 19.5,12.3357864 19.5,12.75 L19.5,18.5 C19.5,19.0522847 19.0522847,19.5 18.5,19.5 L5.5,19.5 C4.94771525,19.5 4.5,19.0522847 4.5,18.5 L4.5,12.75 C4.5,12.3357864 4.16421356,12 3.75,12 C3.33578644,12 3,12.3357864 3,12.75 L3,19 C3,20.1045695 3.8954305,21 5,21 L19,21 C20.1045695,21 21,20.1045695 21,19 L21,12.75 C21,12.3357864 20.6642136,12 20.25,12 Z" id="形状"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="1_基础资料">
<g id="1-1工厂信息" transform="translate(-1580.000000, -20.000000)">
<g id="banner/top/栏" transform="translate(336.000000, 0.000000)">
<g id="编组-5" transform="translate(944.000000, 15.000000)">
<g id="下载" transform="translate(300.000000, 5.000000)">
<rect id="矩形" opacity="0" x="0" y="0" width="24" height="24"></rect>
<path d="M7.6875,13.5 L11.25,13.5 L11.25,3.75 C11.25,3.33578644 11.5857864,3 12,3 C12.4142136,3 12.75,3.33578644 12.75,3.75 L12.75,13.5 L12.75,13.5 L16.3125,13.5 L12,18 L7.6875,13.5 Z M20.25,12 C19.8357864,12 19.5,12.3357864 19.5,12.75 L19.5,18.5 C19.5,19.0522847 19.0522847,19.5 18.5,19.5 L5.5,19.5 C4.94771525,19.5 4.5,19.0522847 4.5,18.5 L4.5,12.75 C4.5,12.3357864 4.16421356,12 3.75,12 C3.33578644,12 3,12.3357864 3,12.75 L3,19 C3,20.1045695 3.8954305,21 5,21 L19,21 C20.1045695,21 21,20.1045695 21,19 L21,12.75 C21,12.3357864 20.6642136,12 20.25,12 Z" id="形状" fill="#fff"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<svg class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="128" height="128"><defs><style/></defs><path d="M512 128q69.675 0 135.51 21.163t115.498 54.997 93.483 74.837 73.685 82.006 51.67 74.837 32.17 54.827L1024 512q-2.347 4.992-6.315 13.483T998.87 560.17t-31.658 51.669-44.331 59.99-56.832 64.34-69.504 60.16-82.347 51.5-94.848 34.687T512 896q-69.675 0-135.51-21.163t-115.498-54.826-93.483-74.326-73.685-81.493-51.67-74.496-32.17-54.997L0 513.707q2.347-4.992 6.315-13.483t18.816-34.816 31.658-51.84 44.331-60.33 56.832-64.683 69.504-60.331 82.347-51.84 94.848-34.816T512 128.085zm0 85.333q-46.677 0-91.648 12.331t-81.152 31.83-70.656 47.146-59.648 54.485-48.853 57.686-37.675 52.821-26.325 43.99q12.33 21.674 26.325 43.52t37.675 52.351 48.853 57.003 59.648 53.845T339.2 767.02t81.152 31.488T512 810.667t91.648-12.331 81.152-31.659 70.656-46.848 59.648-54.186 48.853-57.344 37.675-52.651T927.957 512q-12.33-21.675-26.325-43.648t-37.675-52.65-48.853-57.345-59.648-54.186-70.656-46.848-81.152-31.659T512 213.334zm0 128q70.656 0 120.661 50.006T682.667 512 632.66 632.661 512 682.667 391.339 632.66 341.333 512t50.006-120.661T512 341.333zm0 85.334q-35.328 0-60.33 25.002T426.666 512t25.002 60.33T512 597.334t60.33-25.002T597.334 512t-25.002-60.33T512 426.666z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

1
src/icons/svg/eye.svg Normal file
View File

@ -0,0 +1 @@
<svg width="128" height="64" xmlns="http://www.w3.org/2000/svg"><path d="M127.072 7.994c1.37-2.208.914-5.152-.914-6.87-2.056-1.717-4.797-1.226-6.396.982-.229.245-25.586 32.382-55.74 32.382-29.24 0-55.74-32.382-55.968-32.627-1.6-1.963-4.57-2.208-6.397-.49C-.17 3.086-.399 6.275 1.2 8.238c.457.736 5.94 7.36 14.62 14.72L4.17 35.96c-1.828 1.963-1.6 5.152.228 6.87.457.98 1.6 1.471 2.742 1.471s2.284-.49 3.198-1.472l12.564-13.983c5.94 4.416 13.021 8.587 20.788 11.53l-4.797 17.418c-.685 2.699.686 5.397 3.198 6.133h1.37c2.057 0 3.884-1.472 4.341-3.68L52.6 42.83c3.655.736 7.538 1.227 11.422 1.227 3.883 0 7.767-.49 11.422-1.227l4.797 17.173c.457 2.208 2.513 3.68 4.34 3.68.457 0 .914 0 1.143-.246 2.513-.736 3.883-3.434 3.198-6.133l-4.797-17.172c7.767-2.944 14.848-7.114 20.788-11.53l12.336 13.738c.913.981 2.056 1.472 3.198 1.472s2.284-.49 3.198-1.472c1.828-1.963 1.828-4.906.228-6.87l-11.65-13.001c9.366-7.36 14.849-14.474 14.849-14.474z"/></svg>

After

Width:  |  Height:  |  Size: 944 B

1
src/icons/svg/home.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1615188284589" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2221" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M998.428444 381.112889l-469.333333-353.180445c-0.469333-0.355556-0.981333-0.568889-1.479111-0.896a28.017778 28.017778 0 0 0-2.417778-1.464888 29.909333 29.909333 0 0 0-10.453333-3.128889 30.705778 30.705778 0 0 0-5.475556-0.014223 28.771556 28.771556 0 0 0-13.112889 4.707556c-0.412444 0.284444-0.867556 0.469333-1.28 0.782222l-469.333333 353.180445a28.458667 28.458667 0 0 0 34.204445 45.468444l73.656888-55.424V854.186667c0 111.701333 29.141333 147.555556 136.803556 147.555555h483.555556c107.662222 0 147.640889-35.854222 147.640888-147.555555V379.320889l62.805334 47.260444c5.12 3.854222 11.121778 5.717333 17.080889 5.717334a28.444444 28.444444 0 0 0 17.137777-51.185778zM443.747556 674.673778H580.266667c31.288889 0 36.707556 0.554667 36.707555 28.8v241.422222H417.877333V703.473778c0-28.245333-5.418667-28.8 25.870223-28.8z m400.782222-327.111111v506.666666c0 81.365333-14.193778 90.666667-90.752 90.666667h-108.359111V703.473778c0-48.967111-23.850667-57.244444-65.152-57.244445h-136.519111c-41.301333 0-54.314667 8.277333-54.314667 57.244445v241.422222H270.222222c-76.572444 0-79.914667-9.301333-79.914666-90.666667V347.562667c0-5.788444-1.749333-11.150222-4.721778-15.644445L512 86.272l334.336 251.591111a28.231111 28.231111 0 0 0-1.806222 9.699556z" fill="" p-id="2222"></path><path d="M435.370667 230.499556L250.055111 373.617778c-3.512889 2.688-2.858667 6.855111-2.858667 11.278222v161.777778a14.222222 14.222222 0 1 0 28.444445 0V391.907556l178.730667-138.837334c6.243556-4.778667 5.034667-13.710222 0.256-19.939555a13.425778 13.425778 0 0 0-19.256889-2.631111zM261.418667 589.340444a14.222222 14.222222 0 0 0-14.222223 14.222223v14.222222a14.222222 14.222222 0 1 0 28.444445 0v-14.222222a14.222222 14.222222 0 0 0-14.222222-14.222223z" fill="#000" p-id="2223"></path></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.0 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="10px" height="10px" viewBox="0 0 10 10" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 60 (88103) - https://sketch.com -->
<desc>Created with Sketch.</desc>
<g id="11_系统管理" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="11-1用户管理" transform="translate(-1764.000000, -160.000000)">
<g id="编组-15" transform="translate(1763.000000, 158.000000)">
<g id="编组-18">
<g id="icon/界面内/新增" transform="translate(0.000000, 1.000000)">
<g id="编组">
<rect id="矩形" stroke="#979797" fill="#D8D8D8" opacity="0" x="0.5" y="0.5" width="11" height="11"></rect>
<path d="M10.0813953,6.42885117 L6.37790698,6.42885117 L6.37790698,10.0770235 C6.37790698,10.3108355 6.19069767,10.5 5.95930233,10.5 L5.95930233,10.5 C5.72790698,10.5 5.54069767,10.3108355 5.54069767,10.0770235 L5.54069767,6.42885117 L1.91860465,6.42885117 C1.6872093,6.42885117 1.5,6.23968668 1.5,6.00587467 L1.5,6.00587467 C1.5,5.77206266 1.6872093,5.58289817 1.91860465,5.58289817 L5.54069767,5.58289817 L5.54069767,1.9229765 C5.54069767,1.68916449 5.72790698,1.5 5.95930233,1.5 L5.95930233,1.5 C6.19069767,1.5 6.37790698,1.68916449 6.37790698,1.9229765 L6.37790698,5.58289817 L10.0813953,5.58289817 C10.3127907,5.58289817 10.5,5.77206266 10.5,6.00587467 L10.5,6.00587467 C10.5,6.23968668 10.3127907,6.42885117 10.0813953,6.42885117 L10.0813953,6.42885117 Z" id="Shape" fill="#0B58FF" transform="translate(6.000000, 6.000000) scale(1, -1) translate(-6.000000, -6.000000) "></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -31,6 +31,10 @@ Vue.use(renRegionTree)
Vue.prototype.$http = http
Vue.prototype.$hasPermission = hasPermission
Vue.prototype.$getDictLabel = getDictLabel
// is auth
Vue.prototype.isAuth = permission => {
return "正在检查的权限是:" + permission
}
// 保存整站vuex本地储存初始状态
window.SITE_CONFIG['storeState'] = cloneDeep(store.state)

View File

@ -0,0 +1,24 @@
export default {
data() {
return {
dictList: {}
}
},
methods: {
initDictList(dictTypeIdList) {
const allDictList = JSON.parse(localStorage.getItem('dictList'))
if (!Object.keys(allDictList).length) {
return this.$message({
// TODO: i18n
message: '未能获取数据字典',
type: 'error',
duration: 2000
})
}
dictTypeIdList.forEach(id => {
this.dictList[id] = allDictList[id].map(item => ({ label: item.dictLabel, value: item.dictValue }))
})
}
}
}

View File

@ -1,7 +1,7 @@
import Cookies from 'js-cookie'
import qs from 'qs'
export default {
data () {
data() {
/* eslint-disable */
return {
// 设置属性
@ -29,22 +29,24 @@ export default {
}
/* eslint-enable */
},
created () {
created() {
if (this.mixinViewModuleOptions.createdIsNeed) {
this.query()
}
},
activated () {
activated() {
if (this.mixinViewModuleOptions.activatedIsNeed) {
this.query()
}
},
methods: {
// 获取数据列表
query () {
query() {
this.dataListLoading = true
this.$http.get(
this.mixinViewModuleOptions.getDataListURL,
this.$http.adornUrl(
this.mixinViewModuleOptions.getDataListURL
),
{
params: {
order: this.order,
@ -68,11 +70,11 @@ export default {
})
},
// 多选
dataListSelectionChangeHandle (val) {
dataListSelectionChangeHandle(val) {
this.dataListSelections = val
},
// 排序
dataListSortChangeHandle (data) {
dataListSortChangeHandle(data) {
if (!data.order || !data.prop) {
this.order = ''
this.orderField = ''
@ -83,13 +85,13 @@ export default {
this.query()
},
// 分页, 每页条数
pageSizeChangeHandle (val) {
pageSizeChangeHandle(val) {
this.page = 1
this.limit = val
this.query()
},
// 分页, 当前页
pageCurrentChangeHandle (val) {
pageCurrentChangeHandle(val) {
this.page = val
this.query()
},
@ -98,7 +100,7 @@ export default {
this.query()
},
// 新增 / 修改
addOrUpdateHandle (id) {
addOrUpdateHandle(id) {
this.addOrUpdateVisible = true
this.$nextTick(() => {
this.$refs.addOrUpdate.dataForm.id = id
@ -106,19 +108,20 @@ export default {
})
},
// 关闭当前窗口
closeCurrentTab (data) {
closeCurrentTab(data) {
var tabName = this.$store.state.contentTabsActiveName
this.$store.state.contentTabs = this.$store.state.contentTabs.filter(item => item.name !== tabName)
if (this.$store.state.contentTabs.length <= 0) {
this.$store.state.sidebarMenuActiveName = this.$store.state.contentTabsActiveName = 'home'
return false
// this.$store.state.sidebarMenuActiveName = this.$store.state.contentTabsActiveName = 'home'
// return false
this.$router.push({ name: 'home' })
}
if (tabName === this.$store.state.contentTabsActiveName) {
this.$router.push({ name: this.$store.state.contentTabs[this.$store.state.contentTabs.length - 1].name })
}
},
// 删除
deleteHandle (id) {
deleteHandle(id) {
if (this.mixinViewModuleOptions.deleteIsBatch && !id && this.dataListSelections.length <= 0) {
return this.$message({
message: this.$t('prompt.deleteBatch'),
@ -132,7 +135,7 @@ export default {
type: 'warning'
}).then(() => {
this.$http.delete(
`${this.mixinViewModuleOptions.deleteURL}${this.mixinViewModuleOptions.deleteIsBatch ? '' : '/' + id}`,
this.$http.adornUrl(`${this.mixinViewModuleOptions.deleteURL}${this.mixinViewModuleOptions.deleteIsBatch ? '' : '/' + id}`),
this.mixinViewModuleOptions.deleteIsBatch ? {
'data': id ? [id] : this.dataListSelections.map(item => item[this.mixinViewModuleOptions.deleteIsBatchKey])
} : {}
@ -148,11 +151,11 @@ export default {
this.query()
}
})
}).catch(() => {})
}).catch(() => {})
}).catch(() => { })
}).catch(() => { })
},
// 导出
exportHandle () {
exportHandle() {
var params = qs.stringify({
'token': Cookies.get('token'),
...this.dataForm

View File

@ -2,6 +2,8 @@ import Vue from 'vue'
import Router from 'vue-router'
import http from '@/utils/request'
import { isURL } from '@/utils/validate'
import Cookies from 'js-cookie'
import i18n from '@/i18n'
Vue.use(Router)
@ -12,7 +14,7 @@ export const pageRoutes = [
component: () => import('@/views/pages/404'),
name: '404',
meta: { title: '404未找到' },
beforeEnter (to, from, next) {
beforeEnter(to, from, next) {
// 拦截处理特殊业务场景
// 如果, 重定向路由包含__双下划线, 为临时添加路由
if (/__.*/.test(to.redirectedFrom)) {
@ -21,7 +23,20 @@ export const pageRoutes = [
next()
}
},
{ path: '/login', component: () => import('@/views/pages/login'), name: 'login', meta: { title: '登录' } }
{
path: '/login',
component: () => import('@/views/pages/login'),
name: 'login',
meta: { title: '登录' },
beforeEnter(to, from, next) {
if (Cookies.get('token')) {
Vue.prototype.$message({ message: $t('login.warning'), type: 'error' })
next(false)
} else {
next()
}
}
}
]
// 模块路由(基于主入口布局页面)
@ -30,13 +45,15 @@ export const moduleRoutes = {
component: () => import('@/views/main'),
name: 'main',
redirect: { name: 'home' },
// redirect: { name: 'sys-log-login' },
meta: { title: '主入口布局' },
children: [
{ path: '/home', component: () => import('@/views/modules/home'), name: 'home', meta: { title: '首页', isTab: true } }
// { path: '/sys-log-login', component: () => import('@/views/modules/sys/log-login'), name: 'sys-log-login', meta: { title: '首页', isTab: true } }
{ path: '/home', component: () => import('@/views/modules/home'), name: 'home', meta: { title: '首页', isTab: false, hiddenSiderbar: true } }
]
}
export function addDynamicRoute (routeParams, router) {
export function addDynamicRoute(routeParams, router) {
// 组装路由名称, 并判断是否已添加, 如是: 则直接跳转
var routeName = routeParams.routeName
var dynamicRoute = window.SITE_CONFIG['dynamicRoutes'].filter(item => item.name === routeName)[0]
@ -77,24 +94,30 @@ router.beforeEach((to, from, next) => {
if (window.SITE_CONFIG['dynamicMenuRoutesHasAdded'] || fnCurrentRouteIsPageRoute(to, pageRoutes)) {
return next()
}
// 获取字典列表, 添加并全局变量保存
http.get('/sys/dict/type/all').then(({ data: res }) => {
http.get(http.adornUrl('/sys/dict/type/all')).then(({ data: res }) => {
if (res.code !== 0) {
return
}
window.SITE_CONFIG['dictList'] = res.data
}).catch(() => {})
}).catch((err) => {
})
// 获取菜单列表, 添加并全局变量保存
http.get('/sys/menu/nav').then(({ data: res }) => {
if (res.code !== 0) {
Vue.prototype.$message.error(res.msg)
return next({ name: 'login' })
}
http.get(http.adornUrl('/sys/menu/nav')).then(({ data: res }) => {
/** axios 的拦截器已经拦截出错情况,此处只考虑正确情况即可 */
window.SITE_CONFIG['menuList'] = res.data
// .map(item => {
// if (item.name === '产品池') {
// console.log('Got you')
// item.name =
// }
// return item
// })
fnAddDynamicMenuRoutes(window.SITE_CONFIG['menuList'])
next({ ...to, replace: true })
}).catch(() => {
next({ name: 'login' })
}).catch((err) => {
// Vue.prototype.$message.error(err)
})
})
@ -103,7 +126,7 @@ router.beforeEach((to, from, next) => {
* @param {*} route 当前路由
* @param {*} pageRoutes 页面路由
*/
function fnCurrentRouteIsPageRoute (route, pageRoutes = []) {
function fnCurrentRouteIsPageRoute(route, pageRoutes = []) {
var temp = []
for (var i = 0; i < pageRoutes.length; i++) {
if (route.path === pageRoutes[i].path) {
@ -121,10 +144,13 @@ function fnCurrentRouteIsPageRoute (route, pageRoutes = []) {
* @param {*} menuList 菜单列表
* @param {*} routes 递归创建的动态(菜单)路由
*/
function fnAddDynamicMenuRoutes (menuList = [], routes = []) {
function fnAddDynamicMenuRoutes(menuList = [], routes = []) {
var temp = []
for (var i = 0; i < menuList.length; i++) {
if (menuList[i].children && menuList[i].children.length >= 1) {
// 菜单的国际化
menuList[i].name = i18n.t(`routes["${menuList[i].name}"]`)
temp = temp.concat(menuList[i].children)
continue
}
@ -136,9 +162,15 @@ function fnAddDynamicMenuRoutes (menuList = [], routes = []) {
meta: {
...window.SITE_CONFIG['contentTabDefault'],
menuId: menuList[i].id,
title: menuList[i].name
// 菜单的国际化
title: i18n.t(`routes["${menuList[i].name}"]`)
}
}
// 菜单的国际化
menuList[i].name = i18n.t(`routes["${menuList[i].name}"]`)
// console.log('route ===', route.meta.title)
// eslint-disable-next-line
let URL = (menuList[i].url || '').replace(/{{([^}}]+)?}}/g, (s1, s2) => eval(s2)) // URL支持{{ window.xxx }}占位符变量
if (isURL(URL)) {
@ -151,9 +183,11 @@ function fnAddDynamicMenuRoutes (menuList = [], routes = []) {
}
routes.push(route)
}
if (temp.length >= 1) {
return fnAddDynamicMenuRoutes(temp, routes)
}
// 添加路由
router.addRoutes([
{

View File

@ -1,3 +1,11 @@
/*
* @Descripttion:
* @version:
* @Author: fzq
* @Date: 2022-12-11 20:33:35
* @LastEditors: fzq
* @LastEditTime: 2023-01-12 09:50:26
*/
import Vue from 'vue'
import Vuex from 'vuex'
import cloneDeep from 'lodash/cloneDeep'
@ -9,7 +17,7 @@ export default new Vuex.Store({
namespaced: true,
state: {
// 导航条, 布局风格, default(白色) / colorful(鲜艳)
navbarLayoutType: 'colorful',
navbarLayoutType: '',
// 侧边栏, 布局皮肤, default(白色) / dark(黑色)
sidebarLayoutSkin: 'dark',
// 侧边栏, 折叠状态
@ -23,11 +31,12 @@ export default new Vuex.Store({
contentTabs: [
{
...window.SITE_CONFIG['contentTabDefault'],
'name': 'home',
'title': 'home'
// 这里显示/隐藏 main-content的home标签
// 'name': 'home',
// 'title': 'home'
}
],
contentTabsActiveName: 'home'
// contentTabsActiveName: 'home'
},
modules: {
user

40
src/utils/filters.js Normal file
View File

@ -0,0 +1,40 @@
/*
* @Descripttion:
* @version:
* @Author: fzq
* @Date: 2022-11-25 09:51:46
* @LastEditors: fzq
* @LastEditTime: 2023-02-01 09:39:37
*/
/** filters */
import moment from 'moment'
export const dictFilter = dictTypeId => {
return val => {
return JSON.parse(localStorage.getItem('dictList'))[dictTypeId].find(item => item.dictValue === val)?.dictLabel || '-'
}
}
export const timeFilter = (val) => {
return val ? moment(val).format('YYYY-MM-DD HH:mm:ss') : '-'
}
export const pick = (obj, paths) => {
let result = {}
paths.forEach(key => {
if (obj.hasOwnProperty(key)) {
result[key] = obj[key];
} else {
result[key] = null
}
})
return result
}
// export function timeFormatter(timeObj) {
// if (timeObj) {
// return moment(timeObj).format('YYYY-MM-DD HH:mm:ss')
// } else {
// return '-'
// }
// }

View File

@ -5,7 +5,7 @@ import store from '@/store'
* 权限
* @param {*} key
*/
export function hasPermission (key) {
export function hasPermission(key) {
return window.SITE_CONFIG['permissions'].indexOf(key) !== -1 || false
}
@ -13,7 +13,7 @@ export function hasPermission (key) {
* 获取字典数据列表
* @param dictType 字典类型
*/
export function getDictDataList (dictType) {
export function getDictDataList(dictType) {
const type = window.SITE_CONFIG['dictList'].find((element) => (element.dictType === dictType))
if (type) {
return type.dataList
@ -27,7 +27,7 @@ export function getDictDataList (dictType) {
* @param dictType 字典类型
* @param dictValue 字典值
*/
export function getDictLabel (dictType, dictValue) {
export function getDictLabel(dictType, dictValue) {
const type = window.SITE_CONFIG['dictList'].find((element) => (element.dictType === dictType))
if (type) {
const val = type.dataList.find((element) => (element.dictValue === dictValue + ''))
@ -44,16 +44,17 @@ export function getDictLabel (dictType, dictValue) {
/**
* 清除登录信息
*/
export function clearLoginInfo () {
export function clearLoginInfo() {
store.commit('resetStore')
Cookies.remove('token')
window.SITE_CONFIG['dynamicMenuRoutesHasAdded'] = false
window.SITE_CONFIG['dynamicMenuRoutes'] = []
}
/**
* 获取uuid
*/
export function getUUID () {
export function getUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
return (c === 'x' ? (Math.random() * 16 | 0) : ('r&0x3' | '0x8')).toString(16)
})
@ -62,7 +63,7 @@ export function getUUID () {
/**
* 获取svg图标(id)列表
*/
export function getIconList () {
export function getIconList() {
var res = []
var list = document.querySelectorAll('svg symbol')
for (var i = 0; i < list.length; i++) {
@ -73,12 +74,12 @@ export function getIconList () {
}
/**
* 树形数据转换
* 树形数据转换把扁平的数据转换为树形结构的数据
* @param {*} data
* @param {*} id
* @param {*} pid
*/
export function treeDataTranslate (data, id = 'id', pid = 'pid') {
export function treeDataTranslate(data, id = 'id', pid = 'pid') {
var res = []
var temp = {}
for (var i = 0; i < data.length; i++) {
@ -97,3 +98,24 @@ export function treeDataTranslate (data, id = 'id', pid = 'pid') {
}
return res
}
/** 计算表格的最大高 */
export function calcMaxHeight(num) {
const FIXED_HEIGHT = 220
let clientHeight = 0
const bodyHeight = document.body.clientHeight || null
const documentHeight = document.documentElement.clientHeight || null
if (bodyHeight && documentHeight) {
clientHeight = Math.max(bodyHeight, documentHeight)
} else {
clientHeight = documentHeight ? documentHeight : bodyHeight
}
const finalHeight = clientHeight - num - FIXED_HEIGHT
return finalHeight > 0 ? finalHeight : -finalHeight
}
// tableHeight
export function tableHeight(n) {
return window.innerHeight - n
}

View File

@ -4,9 +4,13 @@ import router from '@/router'
import qs from 'qs'
import { clearLoginInfo } from '@/utils'
import isPlainObject from 'lodash/isPlainObject'
import merge from 'lodash/merge'
const http = axios.create({
baseURL: window.SITE_CONFIG['apiURL'],
// baseURL: window.SITE_CONFIG['apiURL'],
baseURL: '/api',
// baseURL: '/yd-monitor',
// baseURL: process.env.NODE_ENV === 'production' ? '/api' : '/yd-monitor',
timeout: 1000 * 180,
withCredentials: true
})
@ -15,7 +19,8 @@ const http = axios.create({
* 请求拦截
*/
http.interceptors.request.use(config => {
config.headers['Accept-Language'] = Cookies.get('language') || 'zh-CN'
// config.headers['Accept-Language'] = Cookies.get('language') || 'zh-CN'
config.headers['Accept-Language'] = Cookies.get('language') || 'en'
config.headers['token'] = Cookies.get('token') || ''
// 默认参数
var defaults = {}
@ -55,10 +60,55 @@ http.interceptors.response.use(response => {
router.replace({ name: 'login' })
return Promise.reject(response.data.msg)
}
// 下三行注释掉
// else if (response.data.code === 500) {
// return Promise.reject(response.data.msg)
// }
return response
}, error => {
console.error(error)
return Promise.reject(error)
})
/**
* 请求地址处理
* @param {*} actionName action方法名称
*/
http.adornUrl = (actionName) => {
// 非生产环境 && 开启代理, 接口前缀统一使用[/proxyApi/]前缀做代理拦截!
// return (process.env.NODE_ENV !== 'production' && process.env.OPEN_PROXY ? window.SITE_CONFIG.projURL : '') + actionName
// return (process.env.NODE_ENV !== 'production' ? '/yd-monitor' : '/api') + actionName
return actionName
}
/**
* get请求参数处理
* @param {*} params 参数对象
* @param {*} openDefultParams 是否开启默认参数?
*/
http.adornParams = (params = {}, openDefaultParams = true) => {
var defaults = {
't': new Date().getTime()
}
return openDefaultParams ? merge(defaults, params) : params
}
/**
* post请求数据处理
* @param {*} data 数据对象
* @param {*} openDefultdata 是否开启默认数据?
* @param {*} contentType 数据格式
* json: 'application/json; charset=utf-8'
* form: 'application/x-www-form-urlencoded; charset=utf-8'
*/
http.adornData = (data = {}, openDefaultdata = true, contentType = 'json') => {
var defaults = {
't': new Date().getTime()
}
data = openDefaultdata ? merge(defaults, data) : data
return contentType === 'raw' ? data : contentType === 'json' ? JSON.stringify(data) : qs.stringify(data)
// return contentType === 'json' ? JSON.stringify(data, (_, v) => typeof v === 'bigint' ? v.toString() : v) : qs.stringify(data)
}
export default http

View File

@ -1,3 +1,11 @@
/*
* @Descripttion:
* @version:
* @Author: fzq
* @Date: 2022-11-25 09:51:46
* @LastEditors: fzq
* @LastEditTime: 2022-11-30 15:09:05
*/
/**
* 邮箱
* @param {*} s
@ -29,3 +37,11 @@ export function isPhone (s) {
export function isURL (s) {
return /^http[s]?:\/\/.*/.test(s)
}
/**
* @param {string} path
* @returns {Boolean}
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path)
}

56
src/views/Footerbar.vue Normal file
View File

@ -0,0 +1,56 @@
<!--
* @Author: your name
* @Date: 2021-01-27 10:07:42
* @LastEditTime: 2023-01-13 16:22:01
* @LastEditors: fzq
* @Description: In User Settings Edit
* @FilePath: \mt-bus-fe\src\layout\components\FooterBar.vue
-->
<template>
<div v-if="this.$route.meta.hiddenSiderbar !== true" :class="[$store.state.sidebarFold == true ? 'footerbar' : 'footerbar2']">
© {{ $t('copyright') }}
</div>
</template>
<script>
export default {
components: {},
computed: {},
watch: {},
methods: {}
}
</script>
<style lang="scss">
.footerbar{
position: fixed;
bottom: 0;
width: 100%;
height: 20px;
// line-height: 50px;
// text-indent: 2em;
// background: #fff;
// z-index: 999;
// box-shadow: 2px -2px 2px rgba($color: #000000, $alpha: .1);
text-align: center;
font-size: 12px;
color: #C7C7C7;
margin: 5px 0;
}
.footerbar2{
position: fixed;
bottom: 0;
width: 100%;
height: 20px;
// line-height: 50px;
// text-indent: 2em;
// background: #fff;
// z-index: 999;
// box-shadow: 2px -2px 2px rgba($color: #000000, $alpha: .1);
left: 50vw;
font-size: 12px;
color: #C7C7C7;
margin: 5px 0;
}
</style>

View File

@ -1,96 +1,121 @@
<template>
<main :class="['aui-content', { 'aui-content--tabs': $route.meta.isTab }]">
<!-- tab展示内容 -->
<template v-if="$route.meta.isTab">
<el-dropdown class="aui-content--tabs-tools">
<i class="el-icon-arrow-down"></i>
<el-dropdown-menu slot="dropdown" :show-timeout="0">
<el-dropdown-item @click.native="tabRemoveHandle($store.state.contentTabsActiveName)">{{ $t('contentTabs.closeCurrent') }}</el-dropdown-item>
<el-dropdown-item @click.native="tabsCloseOtherHandle()">{{ $t('contentTabs.closeOther') }}</el-dropdown-item>
<el-dropdown-item @click.native="tabsCloseAllHandle()">{{ $t('contentTabs.closeAll') }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-tabs v-model="$store.state.contentTabsActiveName" @tab-click="tabSelectedHandle" @tab-remove="tabRemoveHandle">
<el-tab-pane
v-for="item in $store.state.contentTabs"
:key="item.name"
:name="item.name"
:label="item.title"
:closable="item.name !== 'home'"
:class="{ 'is-iframe': tabIsIframe(item.iframeURL) }">
<template v-if="item.name === 'home'">
<svg slot="label" class="icon-svg aui-content--tabs-icon-nav" aria-hidden="true"><use xlink:href="#icon-home"></use></svg>
</template>
<iframe v-if="tabIsIframe(item.iframeURL)" :src="item.iframeURL" width="100%" height="100%" frameborder="0" scrolling="yes"></iframe>
<keep-alive v-else>
<router-view v-if="item.name === $store.state.contentTabsActiveName" />
</keep-alive>
</el-tab-pane>
</el-tabs>
</template>
<!-- 其他方式, 展示内容 -->
<template v-else>
<keep-alive>
<router-view />
</keep-alive>
</template>
</main>
<!-- <main :class="['aui-content', { 'aui-content--tabs': $route.meta.isTab }]"> -->
<main :class="[this.$route.meta.hiddenSiderbar !== true ? ['aui-content', { 'aui-content--tabs': $route.meta.isTab }] : 'aui-sidebar.close']">
<!-- tab展示内容 -->
<template v-if="$route.meta.isTab">
<el-dropdown class="aui-content--tabs-tools">
<i class="el-icon-arrow-down"></i>
<el-dropdown-menu slot="dropdown" :show-timeout="0">
<el-dropdown-item @click.native="tabRemoveHandle($store.state.contentTabsActiveName)">{{ $t('contentTabs.closeCurrent') }}</el-dropdown-item>
<el-dropdown-item @click.native="tabsCloseOtherHandle()">{{ $t('contentTabs.closeOther') }}</el-dropdown-item>
<el-dropdown-item @click.native="tabsCloseAllHandle()">{{ $t('contentTabs.closeAll') }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-tabs v-model="$store.state.contentTabsActiveName" @tab-click="tabSelectedHandle" @tab-remove="tabRemoveHandle" ref="tabs">
<el-tab-pane
v-for="item in $store.state.contentTabs"
:key="item.name"
:name="item.name"
:label="item.title"
:closable="item.name !== ''"
:class="{ 'is-iframe': tabIsIframe(item.iframeURL) }">
<!-- <template v-if="item.name === 'home'">
<svg slot="label" class="icon-svg aui-content--tabs-icon-nav" aria-hidden="true"><use xlink:href="#icon-home"></use></svg>
</template> -->
<iframe v-if="tabIsIframe(item.iframeURL)" :src="item.iframeURL" width="100%" height="100%" frameborder="0" scrolling="yes"></iframe>
<keep-alive v-else>
<router-view v-if="item.name === $store.state.contentTabsActiveName" />
</keep-alive>
</el-tab-pane>
</el-tabs>
</template>
<!-- 其他方式, 展示内容 -->
<template v-else>
<keep-alive>
<router-view />
</keep-alive>
</template>
</main>
</template>
<script>
import { isURL } from '@/utils/validate'
export default {
data () {
return {
}
},
methods: {
// tabs, iframe
tabIsIframe (url) {
return isURL(url)
},
// tabs, tab
tabSelectedHandle (tab) {
tab = this.$store.state.contentTabs.filter(item => item.name === tab.name)[0]
if (tab) {
this.$router.push({
'name': tab.name,
'params': { ...tab.params },
'query': { ...tab.query }
})
}
},
// tabs, tab
tabRemoveHandle (tabName) {
if (tabName === 'home') {
return false
}
this.$store.state.contentTabs = this.$store.state.contentTabs.filter(item => item.name !== tabName)
if (this.$store.state.contentTabs.length <= 0) {
this.$store.state.sidebarMenuActiveName = this.$store.state.contentTabsActiveName = 'home'
return false
}
// tab
if (tabName === this.$store.state.contentTabsActiveName) {
let tab = this.$store.state.contentTabs[this.$store.state.contentTabs.length - 1]
this.$router.push({
name: tab.name,
params: { ...tab.params },
query: { ...tab.query }
})
}
},
// tabs,
tabsCloseOtherHandle () {
this.$store.state.contentTabs = this.$store.state.contentTabs.filter(item => {
return item.name === 'home' || item.name === this.$store.state.contentTabsActiveName
})
},
// tabs,
tabsCloseAllHandle () {
this.$store.state.contentTabs = this.$store.state.contentTabs.filter(item => item.name === 'home')
this.$router.push({ name: 'home' })
}
}
data() {
return {}
},
mounted() {
this.$nextTick(() => {
// ref
this.$store.state.contentTabs.splice(0, 1)
// home$children
if (this.$route.meta.hiddenSiderbar !== true) {
this.$refs.tabs.$children[0].$refs.tabs[0].style.display = 'none'
}
// console.log(this.$refs.tabs.$children[0].$refs)
// console.log('11',this.$refs.tabs.$children[0].$refs.tabs[0])
// console.log('22',this.$store.state.contentTabs)
})
// setTimeout(function() {
// //
// // .bind(this) 使function() thisthisundefined
// this.$store.state.contentTabs.splice(0, 1)
// // home$children
// if (this.$route.meta.hiddenSiderbar !== true) {
// this.$refs.tabs.$children[0].$refs.tabs[0].style.display = 'none'
// }
// }.bind(this),0)
},
methods: {
// tabs, iframe
tabIsIframe(url) {
return isURL(url)
},
// tabs, tab
tabSelectedHandle(tab) {
tab = this.$store.state.contentTabs.filter((item) => item.name === tab.name)[0]
if (tab) {
this.$router.push({
name: tab.name,
params: { ...tab.params },
query: { ...tab.query }
})
}
},
// tabs, tab
tabRemoveHandle(tabName) {
if (tabName === 'home') {
return false
}
this.$store.state.contentTabs = this.$store.state.contentTabs.filter((item) => item.name !== tabName)
if (this.$store.state.contentTabs.length <= 0) {
this.$store.state.sidebarMenuActiveName = this.$store.state.contentTabsActiveName = 'home'
// return false
this.$router.push({ name: 'home' })
}
// tab
if (tabName === this.$store.state.contentTabsActiveName) {
let tab = this.$store.state.contentTabs[this.$store.state.contentTabs.length - 1]
this.$router.push({
name: tab.name,
params: { ...tab.params },
query: { ...tab.query }
})
}
},
// tabs,
tabsCloseOtherHandle() {
this.$store.state.contentTabs = this.$store.state.contentTabs.filter((item) => {
return item.name === 'home' || item.name === this.$store.state.contentTabsActiveName
})
},
// tabs,
tabsCloseAllHandle() {
this.$store.state.contentTabs = this.$store.state.contentTabs.filter((item) => item.name === 'home')
// this.$router.push({ name: 'sys-log-login' })
this.$router.push({ name: 'home' })
}
}
}
</script>

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