Compare commits

...

181 Commits

Author SHA1 Message Date
fxxian 9571f4744f 定时更新detail数据 2024-04-08 17:07:11 +08:00
fxxian 64b03f9a67 定时更新detail数据 2024-04-08 17:03:08 +08:00
fxxian 2d46369bf7 chore: 加大清零等待时间 2024-04-08 14:38:18 +08:00
fxxian 70d9e547f3 chore: 加大清零等待时间 2024-04-08 14:34:26 +08:00
fxxian 60f0deaa55 fix: 修复screen清零不同步更新计数问题 2024-04-08 13:40:41 +08:00
fxxian 111cbdc0fb fix: 清零同步更新screen数据 2024-04-08 00:11:02 +08:00
fxxian 9221e203d0 fix: 清零同步更新screen数据 2024-04-08 00:03:47 +08:00
Jay Huang a12e229d41 优化二代蚊灯电量显示和隐藏自动清理按钮 2024-03-27 18:32:46 +08:00
Jay Huang 48a44aa864 更新二代蚊灯控制指令路由 2024-03-27 18:01:59 +08:00
Jay Huang 30d5372b30 新增灭蚊灯自动清扫功能 2023-12-02 16:26:09 +08:00
Jay Huang d423df4ad6 fix 2023-12-01 22:26:21 +08:00
Jay Huang 3a2a504520 优化部分页面显示 2023-12-01 22:11:35 +08:00
Jay Huang 41f8bcffd7 #增加了繁体中文支持,更新了二代灭蚊灯标签和远程控制功能 2023-11-27 17:47:27 +08:00
黄伟杰 3f731a8a7e 隐藏温湿度 2023-09-04 12:12:43 +08:00
VIJAY\vijay 73e7bdf682 电量小于10%时显示 2023-02-13 12:24:30 +08:00
VIJAY\vijay 191fa0586d 电量显示从电压转化为百分比 2022-08-23 15:07:06 +08:00
VIJAY\vijay 784165ae78 新增气象台数据查询页面 2022-08-23 12:00:51 +08:00
VIJAY\vijay 6059735df0 更新timeout时间50秒 2022-08-09 15:56:15 +08:00
vijay-huang c6bee1cb7e 去掉ssl 2021-12-14 14:21:04 +08:00
vijay-huang 17c29088c3 域名转让香港公司后,修改API调用地址 2021-12-14 14:10:22 +08:00
xianfuxing bb99c3b765 # 更新marker显示逻辑 2021-08-06 15:07:07 +08:00
xianfuxing 4b931fe6cd # update domain 2021-08-05 10:46:44 +08:00
xianfuxing 44558bc751 # 优化用户名验证 2021-05-11 15:52:30 +08:00
vijay-huang ce22ad34ab #增加几个icon 2020-09-16 10:38:50 +08:00
vijay-huang 1cbd2a6af6 #优化Detail数据查看和地图查看的图标按钮 2020-09-11 16:50:18 +08:00
vijay-huang e4f1ac3310 #改善了status页面的显示UI 2020-09-10 17:38:15 +08:00
xianfuxing 11e9e5fec0 # 更新日期筛选 2020-06-24 11:48:18 +08:00
xianfuxing 39e670743c # 趋势表格添加时间选择 2020-06-23 17:23:41 +08:00
xianfuxing dd6032672e # 优化下载业务逻辑 2020-06-08 17:44:59 +08:00
xianfuxing b2ac5951f2 # 调整下载超时 2020-06-08 13:54:28 +08:00
xianfuxing 392ad2a2b0 # 修改当月数据字段名称 2020-06-05 14:50:25 +08:00
vijay-huang 26a9311bb2 #撤销screen电量百分比,还原成具体数据,由接口统一处理 2020-06-05 10:39:04 +08:00
xianfuxing 53c83abfbf # 更新api名称 2020-06-04 14:54:33 +08:00
xianfuxing 6121f74334 # 优化查询 2020-06-03 18:01:41 +08:00
xianfuxing 2e55a1729d # 修正filename 2020-06-02 17:40:24 +08:00
xianfuxing 685df8f73b Merge branch 'master' of gitee.com:xianfuxing/Mosqkiller 2020-06-02 17:34:13 +08:00
xianfuxing d632a64828 # up export log 2020-06-02 17:33:46 +08:00
vijay-huang 021edcebdb #优化detail页面手机显示 2020-06-02 17:33:33 +08:00
xianfuxing cfa05ce41a # 清理旧代码 2020-06-01 17:34:47 +08:00
vijay-huang ff998824a0 #修改显示方式 2020-06-01 16:36:11 +08:00
xianfuxing 61405cf324 # 添加时间选择 2020-05-29 17:04:37 +08:00
xianfuxing ddec16ea60 # 优化分页、搜索 2020-05-28 17:48:24 +08:00
vijay-huang 5a8b4fa683 Merge branch 'master' of https://gitee.com/xianfuxing/Mosqkiller 2020-05-28 12:00:42 +08:00
vijay-huang de4c2a9700 #增加温度和湿度的数据显示 2020-05-28 12:00:01 +08:00
xianfuxing 0bdd25b915 # 完善面板数据 2020-05-28 11:20:50 +08:00
xianfuxing 30e825833e # 改为本月数据 2020-05-27 17:59:29 +08:00
xianfuxing 6fb2612469 # 优化表格数据 2020-05-27 16:50:43 +08:00
xianfuxing 669cd3dedc # 修正格式 2020-05-27 11:25:23 +08:00
xianfuxing 30a9bdee69 # 调整role 2020-05-27 11:17:55 +08:00
xianfuxing 6a913ec57f # 清理冗余代码 2020-05-27 10:24:04 +08:00
vijay-huang 9edf4919eb #更新贝沙湾2期位置 2020-05-25 17:40:28 +08:00
vijay-huang c83db88952 #更换HK LOGO 2020-05-25 17:21:10 +08:00
xianfuxing f29cdc6cd9 Merge branch 'master' of gitee.com:xianfuxing/Mosqkiller 2020-05-25 17:15:18 +08:00
xianfuxing 3a04d1a910 # 添加device name 2020-05-25 17:14:54 +08:00
vijay-huang da249d54c4 #更改地图default列表 2020-05-25 17:09:59 +08:00
xianfuxing bd58b80bc4 # 调整device base 样式 2020-05-25 15:27:31 +08:00
vijay-huang 5bad80e5cf Merge branch 'master' of https://gitee.com/xianfuxing/Mosqkiller 2020-05-25 14:38:12 +08:00
vijay-huang 7e1bf467ae # 隐藏地图弹窗的区域和驾车规划 2020-05-25 14:37:58 +08:00
xianfuxing e20af0e91e # title 使用设备名称显示 2020-05-25 14:32:15 +08:00
xianfuxing cc95c8d0ce # up humidity 2019-09-01 13:53:36 +08:00
xianfuxing a56751b0b6 # up 温度 2019-09-01 13:30:56 +08:00
xianfuxing c9d28e4cc8 # add humiture 2019-08-30 23:35:40 +08:00
xianfuxing d49f578930 # 设备详情页面国际化更新 2019-02-14 18:12:32 +08:00
xianfuxing 66ccc93f30 # 日志页面国际化更新 2019-02-14 18:00:02 +08:00
xianfuxing b3c8215689 # 设备列表页,国际化更新 2019-02-13 18:33:43 +08:00
xianfuxing bd2eb6675c # counter 部分国际化 2018-12-02 10:47:30 +08:00
xianfuxing d73ca0f46d # disable statistic/settings nav menu 2018-12-02 10:23:16 +08:00
xianfuxing 86a6ccaf63 # bugfixed - detail chart reverse 2018-11-16 14:16:43 +08:00
xianfuxing 99d5eea018 # bugfixed 2018-10-11 14:14:54 +08:00
xianfuxing 84070498c6 # reset devcieID if logout 2018-10-10 18:30:47 +08:00
xianfuxing 23ea18dcca # add username in navarbar 2018-10-10 14:40:41 +08:00
xianfuxing f5568205f9 # 调整权限名称 2018-10-08 19:22:55 +08:00
xianfuxing 5b2f7d7c9d # 优化权限逻辑 2018-09-30 17:36:57 +08:00
xianfuxing 2cc2c2aa6a # 优化x-axis 显示 2018-09-28 16:27:07 +08:00
xianfuxing 08ca34945d # 添加count的类型判断 2018-09-24 22:22:41 +08:00
xianfuxing be79586a4d # bug fixed, 添加device logs hisory api 2018-09-24 21:45:46 +08:00
xianfuxing 781960bf17 # 详情页表格数据改为统计total 2018-09-24 21:39:47 +08:00
xianfuxing 08c55cf959 # css bug fxied 2018-09-10 14:51:09 +08:00
xianfuxing 3b15c1f807 # css socped limited 2018-09-10 14:46:12 +08:00
xianfuxing 068b191207 # 优化地图显示 2018-09-10 14:38:20 +08:00
xianfuxing 9a9fbd01c5 # flag 设置优化 2018-09-08 16:38:25 +08:00
xianfuxing 3dbeb5ae8b # up base style 2018-09-07 17:25:28 +08:00
xianfuxing f584b7e435 # 窗体,按钮跳转 2018-09-06 17:02:04 +08:00
xianfuxing 40965e0f2a # remove useless time sleep 2018-09-05 21:04:22 +08:00
xianfuxing a971db8738 # 优化手机messageBox宽度 2018-09-05 21:02:27 +08:00
xianfuxing c025234884 # up geo map 2018-09-05 20:50:42 +08:00
xianfuxing cac58caadc # up prod api 2018-09-05 10:46:42 +08:00
xianfuxing f041d52be2 # 更新定位坐标 2018-09-04 20:22:31 +08:00
xianfuxing 14a2a86635 # 定位后显示路径 2018-09-04 20:19:58 +08:00
xianfuxing 2773ea5856 # up geo-tip 2018-09-04 20:07:40 +08:00
xianfuxing 636e0877b7 # up geo 2018-09-04 19:58:24 +08:00
xianfuxing 434d9bd012 # add geo 2018-09-04 19:54:47 +08:00
xianfuxing 89d570fb57 # remove useless code 2018-09-04 18:27:51 +08:00
xianfuxing cd67e8a495 # bug fixed sleep until map initial then exec driving search 2018-09-04 11:16:30 +08:00
xianfuxing 51e4259fd8 # up 2018-09-03 20:44:07 +08:00
xianfuxing 699e39492d # up zoom 2018-09-03 20:35:51 +08:00
xianfuxing 5419a8f7d9 # 优化 2018-09-03 20:15:12 +08:00
xianfuxing dd4da1e6f4 # up async plugin 2018-09-03 20:08:42 +08:00
xianfuxing b21d0af572 # up driving 2018-09-03 19:33:52 +08:00
xianfuxing 97af9a4e6a # add transfer plan 2018-09-02 23:37:02 +08:00
xianfuxing a75bcabf86 # seems no need to use flag 2018-09-02 14:54:10 +08:00
xianfuxing ec4e49f5da # 初步完成跳转标记地图 2018-09-02 14:48:53 +08:00
xianfuxing 720b6a3b63 # 初始化地图跳转 2018-09-02 14:33:59 +08:00
xianfuxing 5d68f72890 # up item 2018-09-02 14:02:33 +08:00
xianfuxing f452de76cd # 优化样式 2018-09-02 11:01:49 +08:00
xianfuxing 3fbc0b95c3 # 优化信息窗体逻辑 2018-09-01 11:41:23 +08:00
xianfuxing 6060fcd0d6 # up map2 2018-08-31 18:38:59 +08:00
xianfuxing 328f5289d8 # 更新高德原生api 2018-08-30 18:02:13 +08:00
xianfuxing 7d10a9398a # up 2018-08-29 21:35:21 +08:00
xianfuxing 68db231f8e # disabled tinycme plugin 2018-08-29 09:36:40 +08:00
xianfuxing 71db09ce38 # up map search 2018-08-29 00:07:55 +08:00
xianfuxing 46e801346b # up events 2018-08-28 18:12:36 +08:00
xianfuxing 14541130f3 # up 2018-08-28 12:21:37 +08:00
xianfuxing ded0611df8 # up 2018-08-28 11:56:29 +08:00
xianfuxing 755e24b9a0 # add marker 2018-08-28 11:34:23 +08:00
xianfuxing b50ef0fb6d # bug fixed. 2018-08-28 11:14:28 +08:00
xianfuxing fc24c86728 # 调整宽度 2018-08-28 10:57:18 +08:00
xianfuxing 15dced5e76 # add test positions 2018-08-28 10:49:20 +08:00
xianfuxing db00d3e054 # up map 判断跳转来源 2018-08-27 22:25:17 +08:00
xianfuxing 08d1712ad0 # up map 2018-08-27 21:48:47 +08:00
xianfuxing 6d69ca3948 # up height 100% 2018-08-27 16:02:16 +08:00
xianfuxing d779e9b324 # 初始化地图 2018-08-27 14:49:28 +08:00
xianfuxing 5c0a2e12e4 # bug fixed, empty screen 2018-08-26 21:07:37 +08:00
xianfuxing 8416b0e17c # lineChart bug fixed 2018-08-24 15:55:57 +08:00
xianfuxing 14d83dd19d # add screen animation 2018-08-23 23:31:17 +08:00
xianfuxing 9eca742161 # bug fixed resize 2018-08-23 20:47:43 +08:00
xianfuxing 50614aa654 # up chart 2018-08-23 18:58:58 +08:00
xianfuxing ebf2ff9b96 # up avatar 2018-08-23 14:19:10 +08:00
xianfuxing 43ece7e820 # add cur time with moment.js 2018-08-22 23:08:12 +08:00
xianfuxing 8538e02f0c # 完善screen 2018-08-22 20:35:26 +08:00
xianfuxing 9c483e8699 # 更新样式 2018-08-22 19:40:16 +08:00
xianfuxing 0c2f582b84 # up screen 2018-08-22 19:17:21 +08:00
xianfuxing 0f18df3e03 # screen 初稿 2018-08-22 00:08:25 +08:00
xianfuxing 080e696f26 # 初始化显示屏 2018-08-21 18:55:18 +08:00
xianfuxing 3e04a825a2 # 调整坐标宽带 2018-08-21 14:09:18 +08:00
xianfuxing 1bb45287ab # 修改翻译 2018-08-21 11:27:44 +08:00
xianfuxing bf5959e40d # add localStorage 2018-08-21 10:24:16 +08:00
xianfuxing 14919161eb # rename detail view name, because will be chached if named 'detail' 2018-08-20 21:29:03 +08:00
xianfuxing 920b1da28d # detail page 2018-08-20 21:06:20 +08:00
xianfuxing ccafbe6e21 # 优化logs列表 2018-08-20 15:44:37 +08:00
xianfuxing 456d96f4f8 # 修正名称错误 2018-08-20 15:23:21 +08:00
xianfuxing c8e195793a # 调整名称 2018-08-20 15:20:12 +08:00
xianfuxing 767373ec18 # disabled useless nav tool 2018-08-20 11:53:10 +08:00
xianfuxing 0766551376 Merge branch 'master' of gitee.com:xianfuxing/Mosqkiller 2018-08-20 11:12:59 +08:00
xianfuxing 1d9cd07614 # up submit button 2018-08-20 11:12:51 +08:00
xianfuxing 6dce0c39e4 # device_id模糊查询 2018-08-19 22:51:35 +08:00
xianfuxing 306e477364 # add status select 2018-08-19 22:34:26 +08:00
xianfuxing b7fa1fea17 # add pagination in device page 2018-08-19 21:54:19 +08:00
xianfuxing d7fc6a8585 # up device_id search 2018-08-19 15:22:33 +08:00
xianfuxing d737117b25 # compatible with mobile style 2018-08-18 17:40:29 +08:00
xianfuxing b6fc576b26 # up device 2018-08-18 17:34:16 +08:00
xianfuxing 781bc88e47 # up device list 2018-08-18 15:45:01 +08:00
xianfuxing a08b33d6d8 # 优化序号显示 2018-08-18 12:59:07 +08:00
xianfuxing 8f03176d42 # up increment, total chart 2018-08-15 20:50:35 +08:00
xianfuxing d89fb84047 # add settings view 2018-08-15 16:24:06 +08:00
xianfuxing faa2a140e4 # add settings 2018-08-15 15:52:59 +08:00
xianfuxing 61c69ef508 # up handleSetLineChartData 2018-08-14 18:17:44 +08:00
xianfuxing 1ee4c938c6 # print chartData 2018-08-14 17:15:15 +08:00
xianfuxing ae878dbca2 # up history linechart x-axis 2018-08-14 16:57:39 +08:00
xianfuxing 076c486cf4 # up total-history linechart 2018-08-14 16:39:36 +08:00
xianfuxing 13cfaeba7b # up history table 2018-08-14 11:24:14 +08:00
xianfuxing 27db1ba5d4 # add log history table 2018-08-13 21:18:05 +08:00
xianfuxing 24f1b02e20 # disabled useless components 2018-08-13 21:01:53 +08:00
xianfuxing ada63a4525 # 样式兼容mobile 2018-08-12 14:07:03 +08:00
xianfuxing 204b6bcfe5 # up dashboard icon 2018-08-10 10:26:03 +08:00
xianfuxing e6383df92a # add panel statistic 2018-08-09 23:49:38 +08:00
xianfuxing 21796fb5fe # 添加设备、日志统计api 2018-08-09 18:16:44 +08:00
xianfuxing 87d04a0568 # add counter detail page 2018-08-05 15:00:38 +08:00
xianfuxing 984adf721e # update lang 2018-08-04 13:08:26 +08:00
xianfuxing 364c0f9a61 # renane from count to logs 2018-08-04 13:01:34 +08:00
xianfuxing f1e6a20a0c # rename count-view to logs-view 2018-08-04 11:49:29 +08:00
xianfuxing 386836d940 # 调整分页背景色 2018-08-04 10:55:46 +08:00
xianfuxing 4613c32c93 # up pagination style 2018-08-03 12:38:09 +08:00
xianfuxing 67ab8dc8f9 # up pagination style 2018-08-02 19:14:01 +08:00
xianfuxing e2af5b3fa6 # 优化登录过期提示 2018-08-02 19:13:16 +08:00
xianfuxing a0fc07809a # 优化401提醒 2018-08-01 23:44:19 +08:00
xianfuxing 3d033a55f7 # up 401 message box 2018-08-01 21:43:24 +08:00
xianfuxing 5835498ab3 # up logout 2018-08-01 20:52:52 +08:00
xianfuxing 48127c3f57 # up pagination style 2018-08-01 20:30:23 +08:00
xianfuxing e9c09ac836 # up count view 2018-08-01 15:46:44 +08:00
xianfuxing 83344da3d5 # 更新错误 2018-08-01 13:57:04 +08:00
110 changed files with 4824 additions and 4169 deletions

View File

@ -96,5 +96,8 @@ module.exports = {
net: 'empty',
tls: 'empty',
child_process: 'empty'
},
externals: {
'AMap': 'AMap'
}
}

View File

@ -1,5 +1,6 @@
module.exports = {
NODE_ENV: '"production"',
ENV_CONFIG: '"prod"',
BASE_API: '"http://127.0.0.1:8000/"'
BASE_API: '"http://47.106.73.20:8000/"'
//BASE_API: '"https://mosq.celex-iot.com:8000/"'
}

View File

@ -8,8 +8,9 @@
<title>celex-iot</title>
</head>
<body>
<script src=<%= htmlWebpackPlugin.options.path %>/tinymce4.7.5/tinymce.min.js></script>
<!-- <script src=<%= htmlWebpackPlugin.options.path %>/tinymce4.7.5/tinymce.min.js></script> -->
<div id="app"></div>
<!-- built files will be auto injected -->
<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.8&key=250fde87c69f9f46d0a2bdbc561a82a8"></script>
</body>
</html>

View File

@ -41,12 +41,15 @@
"dropzone": "5.2.0",
"echarts": "3.8.5",
"element-ui": "2.3.2",
"eslint-plugin-vue": "^6.2.2",
"file-saver": "1.3.3",
"font-awesome": "4.7.0",
"js-cookie": "2.2.0",
"jsonlint": "1.6.3",
"jszip": "3.1.5",
"mockjs": "1.0.1-beta3",
"moment": "^2.27.0",
"node-sass": "^7.0.1",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"screenfull": "3.3.2",
@ -55,12 +58,13 @@
"simplemde": "1.11.2",
"sortablejs": "1.7.0",
"vue": "2.5.10",
"vue-amap": "^0.5.8",
"vue-count-to": "1.0.13",
"vue-i18n": "7.3.2",
"vue-multiselect": "2.0.8",
"vue-router": "3.0.1",
"vue-splitpane": "1.0.2",
"vuedraggable": "^2.16.0",
"vuedraggable": "^2.24.1",
"vuex": "3.0.1",
"xlsx": "^0.11.16"
},
@ -91,7 +95,6 @@
"husky": "0.14.3",
"lint-staged": "7.2.0",
"node-notifier": "5.1.2",
"node-sass": "^4.7.2",
"optimize-css-assets-webpack-plugin": "3.2.0",
"ora": "1.3.0",
"portfinder": "1.0.13",
@ -99,6 +102,7 @@
"postcss-loader": "2.0.9",
"postcss-url": "7.3.0",
"rimraf": "2.6.2",
"sass": "^1.54.4",
"sass-loader": "6.0.6",
"script-loader": "0.7.2",
"semver": "5.4.1",

View File

@ -1,5 +1,6 @@
import request from '@/utils/request'
// device list api
export function fetchDeviceList(query) {
return request({
url: '/api/counter/device/',
@ -7,3 +8,82 @@ export function fetchDeviceList(query) {
params: query
})
}
// device log list api
export function fetchDeviceLogs(query) {
request.defaults.timeout = 50000 * 6
return request({
url: '/api/counter/logs/',
method: 'get',
params: query
})
}
// reset timeout
request.defaults.timeout = 50000
// device logs history api
export function fetchDeviceLogsHistory(query) {
return request({
url: '/api/counter/device/daily/',
method: 'get',
params: query
})
}
// device info statistic api
export function fetchDeviceInfoStatistic(query) {
return request({
url: '/api/counter/device/status/',
method: 'get',
params: query
})
}
// device log statistic api
export function fetchDeviceLogStatistic(query) {
return request({
url: '/api/counter/latest/statistic/',
method: 'get',
params: query
})
}
// log statistic history api
export function fetchLogStatisticHistory(query) {
return request({
url: '/api/counter/latest/daily/',
method: 'get',
params: query
})
}
// device temp log statistic api
export function fetchDeviceTempLog(query) {
return request({
url: '/api/mosq/temp/',
method: 'get',
params: query
})
}
// weather device log api
export function fetchWeatherLog(query) {
return request({
url: '/api/mosq/weather/',
method: 'get',
params: query
})
}
// device v2 remote control
export function fetchRemoteControl(deviceID, data) {
return request({
url: `/api/mosq/device/${deviceID}/mqtt/pub/`,
method: 'post',
data
})
}

View File

@ -14,7 +14,7 @@ export function loginByUsername(username, password) {
export function logout() {
return request({
url: '/api/users/logout',
url: '/api/users/logout/',
method: 'get'
})
}

539
src/assets/icon/demo.css Normal file
View File

@ -0,0 +1,539 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

View File

@ -0,0 +1,630 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>IconFont Demo</title>
<link rel="shortcut icon" href="https://img.alicdn.com/tps/i4/TB1_oz6GVXXXXaFXpXXJDFnIXXX-64-64.ico" type="image/x-icon"/>
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
<link rel="stylesheet" href="demo.css">
<link rel="stylesheet" href="iconfont.css">
<script src="iconfont.js"></script>
<!-- jQuery -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
<!-- 代码高亮 -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
</head>
<body>
<div class="main">
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">&#xe86b;</a></h1>
<div class="nav-tabs">
<ul id="tabs" class="dib-box">
<li class="dib active"><span>Unicode</span></li>
<li class="dib"><span>Font class</span></li>
<li class="dib"><span>Symbol</span></li>
</ul>
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=2058344" target="_blank" class="nav-more">查看项目</a>
</div>
<div class="tab-container">
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe632;</span>
<div class="name">abb_temperature-cels</div>
<div class="code-name">&amp;#xe632;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe82f;</span>
<div class="name">humidity</div>
<div class="code-name">&amp;#xe82f;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe683;</span>
<div class="name">map</div>
<div class="code-name">&amp;#xe683;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe620;</span>
<div class="name">detail</div>
<div class="code-name">&amp;#xe620;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe857;</span>
<div class="name">signal-2</div>
<div class="code-name">&amp;#xe857;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe818;</span>
<div class="name">signal-1</div>
<div class="code-name">&amp;#xe818;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe81a;</span>
<div class="name">signal-3</div>
<div class="code-name">&amp;#xe81a;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xf60e;</span>
<div class="name">signal-4</div>
<div class="code-name">&amp;#xf60e;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xebf6;</span>
<div class="name">mosquito.1</div>
<div class="code-name">&amp;#xebf6;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xebf5;</span>
<div class="name">mosquito</div>
<div class="code-name">&amp;#xebf5;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe617;</span>
<div class="name">power_0</div>
<div class="code-name">&amp;#xe617;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe618;</span>
<div class="name">power_1</div>
<div class="code-name">&amp;#xe618;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe619;</span>
<div class="name">power_2</div>
<div class="code-name">&amp;#xe619;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe61a;</span>
<div class="name">power_3</div>
<div class="code-name">&amp;#xe61a;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe61b;</span>
<div class="name">power_4</div>
<div class="code-name">&amp;#xe61b;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe61c;</span>
<div class="name">power_5</div>
<div class="code-name">&amp;#xe61c;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe61d;</span>
<div class="name">power_6</div>
<div class="code-name">&amp;#xe61d;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe61e;</span>
<div class="name">power_8</div>
<div class="code-name">&amp;#xe61e;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe61f;</span>
<div class="name">power_7</div>
<div class="code-name">&amp;#xe61f;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe625;</span>
<div class="name">power_9</div>
<div class="code-name">&amp;#xe625;</div>
</li>
</ul>
<div class="article markdown">
<h2 id="unicode-">Unicode 引用</h2>
<hr>
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
<ul>
<li>兼容性最好,支持 IE6+,及所有现代浏览器。</li>
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
<li>但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。</li>
</ul>
<blockquote>
<p>注意:新版 iconfont 支持多色图标,这些多色图标在 Unicode 模式下将不能使用如果有需求建议使用symbol 的引用方式</p>
</blockquote>
<p>Unicode 使用步骤如下:</p>
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
<pre><code class="language-css"
>@font-face {
font-family: 'iconfont';
src: url('iconfont.eot');
src: url('iconfont.eot?#iefix') format('embedded-opentype'),
url('iconfont.woff2') format('woff2'),
url('iconfont.woff') format('woff'),
url('iconfont.ttf') format('truetype'),
url('iconfont.svg#iconfont') format('svg');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
>.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre>
<code class="language-html"
>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont el-icon-aliabb_temperature-cels"></span>
<div class="name">
abb_temperature-cels
</div>
<div class="code-name">.el-icon-aliabb_temperature-cels
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alihumidity"></span>
<div class="name">
humidity
</div>
<div class="code-name">.el-icon-alihumidity
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alimap"></span>
<div class="name">
map
</div>
<div class="code-name">.el-icon-alimap
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alixiangqing"></span>
<div class="name">
detail
</div>
<div class="code-name">.el-icon-alixiangqing
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alisignal-2"></span>
<div class="name">
signal-2
</div>
<div class="code-name">.el-icon-alisignal-2
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alisignal-1"></span>
<div class="name">
signal-1
</div>
<div class="code-name">.el-icon-alisignal-1
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alisignal-3"></span>
<div class="name">
signal-3
</div>
<div class="code-name">.el-icon-alisignal-3
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alisignal-4"></span>
<div class="name">
signal-4
</div>
<div class="code-name">.el-icon-alisignal-4
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alimosquito1"></span>
<div class="name">
mosquito.1
</div>
<div class="code-name">.el-icon-alimosquito1
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alimosquito"></span>
<div class="name">
mosquito
</div>
<div class="code-name">.el-icon-alimosquito
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alipower_"></span>
<div class="name">
power_0
</div>
<div class="code-name">.el-icon-alipower_
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alipower_1"></span>
<div class="name">
power_1
</div>
<div class="code-name">.el-icon-alipower_1
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alipower_2"></span>
<div class="name">
power_2
</div>
<div class="code-name">.el-icon-alipower_2
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alipower_3"></span>
<div class="name">
power_3
</div>
<div class="code-name">.el-icon-alipower_3
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alipower_4"></span>
<div class="name">
power_4
</div>
<div class="code-name">.el-icon-alipower_4
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alipower_5"></span>
<div class="name">
power_5
</div>
<div class="code-name">.el-icon-alipower_5
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alipower_6"></span>
<div class="name">
power_6
</div>
<div class="code-name">.el-icon-alipower_6
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alipower_8"></span>
<div class="name">
power_8
</div>
<div class="code-name">.el-icon-alipower_8
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alipower_7"></span>
<div class="name">
power_7
</div>
<div class="code-name">.el-icon-alipower_7
</div>
</li>
<li class="dib">
<span class="icon iconfont el-icon-alipower_9"></span>
<div class="name">
power_9
</div>
<div class="code-name">.el-icon-alipower_9
</div>
</li>
</ul>
<div class="article markdown">
<h2 id="font-class-">font-class 引用</h2>
<hr>
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
<p>与 Unicode 使用方式相比,具有如下特点:</p>
<ul>
<li>兼容性良好,支持 IE8+,及所有现代浏览器。</li>
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
<li>不过因为本质上还是使用的字体,所以多色图标还是不支持的。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
</code></pre>
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;span class="iconfont el-icon-alixxx"&gt;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"
iconfont" 是你项目下的 font-family。可以通过编辑项目查看默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content symbol">
<ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-aliabb_temperature-cels"></use>
</svg>
<div class="name">abb_temperature-cels</div>
<div class="code-name">#el-icon-aliabb_temperature-cels</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alihumidity"></use>
</svg>
<div class="name">humidity</div>
<div class="code-name">#el-icon-alihumidity</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alimap"></use>
</svg>
<div class="name">map</div>
<div class="code-name">#el-icon-alimap</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alixiangqing"></use>
</svg>
<div class="name">detail</div>
<div class="code-name">#el-icon-alixiangqing</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alisignal-2"></use>
</svg>
<div class="name">signal-2</div>
<div class="code-name">#el-icon-alisignal-2</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alisignal-1"></use>
</svg>
<div class="name">signal-1</div>
<div class="code-name">#el-icon-alisignal-1</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alisignal-3"></use>
</svg>
<div class="name">signal-3</div>
<div class="code-name">#el-icon-alisignal-3</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alisignal-4"></use>
</svg>
<div class="name">signal-4</div>
<div class="code-name">#el-icon-alisignal-4</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alimosquito1"></use>
</svg>
<div class="name">mosquito.1</div>
<div class="code-name">#el-icon-alimosquito1</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alimosquito"></use>
</svg>
<div class="name">mosquito</div>
<div class="code-name">#el-icon-alimosquito</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alipower_"></use>
</svg>
<div class="name">power_0</div>
<div class="code-name">#el-icon-alipower_</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alipower_1"></use>
</svg>
<div class="name">power_1</div>
<div class="code-name">#el-icon-alipower_1</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alipower_2"></use>
</svg>
<div class="name">power_2</div>
<div class="code-name">#el-icon-alipower_2</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alipower_3"></use>
</svg>
<div class="name">power_3</div>
<div class="code-name">#el-icon-alipower_3</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alipower_4"></use>
</svg>
<div class="name">power_4</div>
<div class="code-name">#el-icon-alipower_4</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alipower_5"></use>
</svg>
<div class="name">power_5</div>
<div class="code-name">#el-icon-alipower_5</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alipower_6"></use>
</svg>
<div class="name">power_6</div>
<div class="code-name">#el-icon-alipower_6</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alipower_8"></use>
</svg>
<div class="name">power_8</div>
<div class="code-name">#el-icon-alipower_8</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alipower_7"></use>
</svg>
<div class="name">power_7</div>
<div class="code-name">#el-icon-alipower_7</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#el-icon-alipower_9"></use>
</svg>
<div class="name">power_9</div>
<div class="code-name">#el-icon-alipower_9</div>
</li>
</ul>
<div class="article markdown">
<h2 id="symbol-">Symbol 引用</h2>
<hr>
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
<ul>
<li>支持多色图标了,不再受单色限制。</li>
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
</code></pre>
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
<pre><code class="language-html">&lt;style&gt;
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
&lt;/style&gt;
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
&lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
&lt;/svg&gt;
</code></pre>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.tab-container .content:first').show()
$('#tabs li').click(function (e) {
var tabContent = $('.tab-container .content')
var index = $(this).index()
if ($(this).hasClass('active')) {
return
} else {
$('#tabs li').removeClass('active')
$(this).addClass('active')
tabContent.hide().eq(index).fadeIn()
}
})
})
</script>
</body>
</html>

View File

@ -0,0 +1,107 @@
@font-face {font-family: "iconfont";
src: url('iconfont.eot?t=1600056086767'); /* IE9 */
src: url('iconfont.eot?t=1600056086767#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAqMAAsAAAAAGIwAAAo8AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCFQgqgAJojATYCJANUCywABCAFhG0HggEbuBQRVax7JfuiwHZ0swRH1LDmfOLN8X+pLdU8D+KBfr/25751aeAJNtJ9Og0ymSHT2NBgOlE1ksiEpl/vVxkeN/PfI0mFYFoJUjun9VNK1QM5h94KJ2Jhc9gcqRr0xIVekc3Z9v9EjP9d0zLrqI5LZEce7eFPmqNw4fk5PSE3YSbkhBwDOJjcN0AAQdj55l5tktcrga0juLJw7CobZT/QBYrIsq9CAgpFBIp9eRN6alZ+OSXnPSusNoZVxEXHU12bgKJB08CF0moSxEhjVECO1ZXLm0GMy1M6RiPIu2RD5szcha8DTD55ifEAAJv624cvIDPEAIlMCrB1LVpKWoDuM+lvHISO0GAx8hKgy/PHeT5S6AHShLvQwFuAmKin08Ww/KgtAHTxDt9SNio/S/ks87NnvpB9EfeF5gvq699+u5EIUQqZXytjnQVdk/i2pgBKyiqqaur4BIRQbVCNv+bJSWQUFeQJWUDblZnILNpAlEpIiSiDlIlySIUYB6kS4yE1YoK7+ptJBKQBRALSBKIC0gKiEpImpvDrZzLhLoB5BpAUH2XusjoTB3c5MBq4S8BQgGT48qu7IpjfACnwn8PfL4F01DkmALMAZJoAZJ8BY3d0lOV0euVkDlLSAq2Ybromk02KZcnFQhxnsWMJvowHZSwW5LHudjlRGV/8XCiEyRi8ktA1nnN6QtF9zQi7n+QG/enoBX8gMMsTwO1pt0OhoBZ0+vzB2d4gtB6fGo/1hHKGLspRuSewnHnqEgF7LufhJx8m4tZjl+4xmbY7F44A0D968S6O2+9fPg6ZnQ8sJ3z0uH3C+oS0udo73CNDTkCPUterkIFQ2c2AinG34Cqg/ZC3BbcPQwtCIao/WClBui/ZLiQwRHf8ykBgEeIes3sAY/dqQ9aRfeoJ0XN9aXtQ4vDL2jz2sflWgYv2y2tvh5L6b8Mp+wK7/X4yENDjhS0xGJx/6pL1sv0ifYHqSqRQ0uBi2kTqFJjeidulaQMacllUM8WPNXqHPhgkHSdSLwUNwaCIyWjefXKe8yBAt+c6zjA5p7SuQxDrye84j6/nlIzQE86dDgsGDRtsEleHlHIPifWKBU+riHQMSwzPX8uyea1jUrbTQ4+Sdn7mcqZtFDD6nkHKMAYRq9fkBgCDNlHVSsuPA2gLY+DXBaKw6KvYHfSXU24ple+2umyieoeIJKG7I856LRe222TgxBXQJQcGg9UlMbhcDodYr3fKYe4FyTMq+uDkoZtDvsw0MekAvf7iQTolFEqi5Bf8yk5/crK0TifulI6F2BQacWegwGOfet1KSA8GyE5S7GKx3Q3dLslwkOgPauP1fQH9iDX1VlBdx1dIhwJ6++2p59X9ux/5yYYRc+M7+o/lQtewDgBujvTKDQaXREsCaPG8RlkKBqsdBxLoeeluh/JIh+iY4HDQTvxCiLEr/bUOSUdCST1XIpQhsS+Q4nRfiWuEFNnrRJIX9zjtyUCJ/XbaZdh9iMIx5k64Dthd6wLfjeC+4l7/L5KMzivZu05dI7Ce63m7T15NpNgYK6E0cjEOkUY+xiPSKMQExHl2Y7uG/O/SZd3lr5ZBvO3IETxxuMxYzrz/7f0C5tp8Iwsq9ejSSQ3atyviJomy7i2qT9kev/XixZ3GhsQGTvwpQpeSdMA1EusvSN3qKtrJHPknvjYsFBZE0DfRiE6YzkV1hKXdTAgJc7uFeFNhtocxK3Qod9o/tL6Rb6HBkraP+dXGzA8EksNMNh/8+E9eegwtKdGlyyWIjtWKqsozkxeWli5INi9IKS2xtpgJyn6XUnDrVkjhc0xVQ/cZ35V+x7g/WDWnGYdU0FYyZzk42coinuOvF5I5H4R933KQbS8oRMlFSUI6ZDLYnrS9aak215ydTZakjc3KybpSoiouEuxedWPVrpU3djPsXYPkty1V0GyG1TE1L/0vdoUmZsVLX8aWw2qzuRqC+yK+5LPDn0pbMs+4qz5rDvL4v18znam90FX4Gfee5/vSCyZN1HqTcAuvl5KPjQsl3jKFjfgp26YKbJx98XW1uTymqvA1VlFqd9R6kDWmCSsjctkWDiPSJ225Le+HXulTJS21cMUKWLsF1qxYWQtbai4YgyM42ndfAzdN8A7Yp5z58uQZa9urb4VOjh5Niff8cG/k9dbXXb7+EdbgYW4WkRk+HM4ksjh9jvxccJ5v4vA5tBTqHuzLJ/aKh0s7Bof3P6qXgf7xCHSOoKN/jAWAqx8xmLtSVJbyfrZnQxGJZp6OlLDbOMXqekxzYlcl0rkPylVRuUApN6+UIX8i/tuvGWBAQVZR8TXPtGKNLnMYI9cUtb2bU5r0kK3a37xvTFUG9ykssywqRyyRd/oOUDLgWl/qfCJ5ojqkTtGWdhXOlSZvQeqRcE0jtkx35PNZeviejcwmD7zfNOtz3RFyd2vI7xA+L2oLJppb0qUtTVFXhyaS5xOpWp8BB8Pu5J0msDKdRTVrxb7EMqj6pvkhex6Y87v454yySF46o0miPWcx8O/z9Z4sdN6ZZl0bDMcWxp4XnFfjwrCtWfcIR7M8+tgTMFi05yRNpTOK5GeUV/70oPm+9d+qTWZhrF59IhHTjL1I5zgSA3PO9aj5SZK75DtJ8N+XnbLqoYi2TjCl6Og/U0lwe2fp3NKdmh859R+P2xRB4Moim395rW7Ly//CpKZ33pHMV0fPuW5gVn289IuaMSzxhF4tNwvr1R/s9+WjHjA2xew1m+u9XlhuNJbBhUdAGTQZYblb1kQYh00HyBEC1kkv8kN6SLv0n4jJLYFsuVdO9mPvY7LrvHVkj3vHyc735pN933uf7N+9v5NNeSmugbyydkuZZiPyB4j8F+kj/yIvAaBrfITs13Ij3yAr8VeorWER0Ad10AQ+QGsyfAyAIfgVrZeRX5CNCW8iXyOr8WNEUwgNwQ+FsawtWPqxkTv31xj8v0PMw3MsCeW1n5uOi0h5SVRQ4GdBqej5kf8AyC1dRAx13u7SfefrVM4W/EsoJ0HaCXLL/Bp0OrpAdHyCIm/DD4TQpg/b4dr58vUP8i7BWS+RM6CXkjeOp0FPL6NkSi8rb1qvaBLvef6qLikrvRFSqWufRC+t5Usvo+EbZcPAL8oB/OnlDfxLClApq1fxUXeJVcNo5V6Co8FH7hlRjyVY+OiKkfMFiIkcSUXHiT5AKsoSNB1NPinPkIAsYxp1IDOtMcKSxeiJTAFRxBCXLABPj/ZI5rvxGF+nHXksTlXck4BDq0Z9iOtsnfIwCdyxVvG9/gtAGBGHjKnwaf0DkBQ6eGRqZJICf6aTVBW2Jb9yQMxo6o8hWVxiYsgT9QcRT2QQHj5aAHi0kX2OeG5nTBvCaelR/Wy8DejU4quU3Uy/jCQrqqYbpmU7rudr6+jq6RuE3l3X0hDzadmakXDnQaRKexNTn+pzNnZ4+USdhAgqS5YUJYkT3c0M2ansfMJFOWZKGKrZtHQqUuDsCNIqauz0BGZgDhZgCVZgA9YB21QKAAAA') format('woff2'),
url('iconfont.woff?t=1600056086767') format('woff'),
url('iconfont.ttf?t=1600056086767') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('iconfont.svg?t=1600056086767#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
[class^="el-icon-ali"],
[class*=" el-icon-ali"]/*这里有空格*/
{
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.el-icon-aliabb_temperature-cels:before {
content: "\e632";
}
.el-icon-alihumidity:before {
content: "\e82f";
}
.el-icon-alimap:before {
content: "\e683";
}
.el-icon-alixiangqing:before {
content: "\e620";
}
.el-icon-alisignal-2:before {
content: "\e857";
}
.el-icon-alisignal-1:before {
content: "\e818";
}
.el-icon-alisignal-3:before {
content: "\e81a";
}
.el-icon-alisignal-4:before {
content: "\f60e";
}
.el-icon-alimosquito1:before {
content: "\ebf6";
}
.el-icon-alimosquito:before {
content: "\ebf5";
}
.el-icon-alipower_:before {
content: "\e617";
}
.el-icon-alipower_1:before {
content: "\e618";
}
.el-icon-alipower_2:before {
content: "\e619";
}
.el-icon-alipower_3:before {
content: "\e61a";
}
.el-icon-alipower_4:before {
content: "\e61b";
}
.el-icon-alipower_5:before {
content: "\e61c";
}
.el-icon-alipower_6:before {
content: "\e61d";
}
.el-icon-alipower_8:before {
content: "\e61e";
}
.el-icon-alipower_7:before {
content: "\e61f";
}
.el-icon-alipower_9:before {
content: "\e625";
}

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,149 @@
{
"id": "2058344",
"name": "eleThirdIcon",
"font_family": "iconfont",
"css_prefix_text": "el-icon-ali",
"description": "",
"glyphs": [
{
"icon_id": "7658801",
"name": "abb_temperature-cels",
"font_class": "abb_temperature-cels",
"unicode": "e632",
"unicode_decimal": 58930
},
{
"icon_id": "17013987",
"name": "humidity",
"font_class": "humidity",
"unicode": "e82f",
"unicode_decimal": 59439
},
{
"icon_id": "691221",
"name": "map",
"font_class": "map",
"unicode": "e683",
"unicode_decimal": 59011
},
{
"icon_id": "13738103",
"name": "detail",
"font_class": "xiangqing",
"unicode": "e620",
"unicode_decimal": 58912
},
{
"icon_id": "10023646",
"name": "signal-2",
"font_class": "signal-2",
"unicode": "e857",
"unicode_decimal": 59479
},
{
"icon_id": "10248563",
"name": "signal-1",
"font_class": "signal-1",
"unicode": "e818",
"unicode_decimal": 59416
},
{
"icon_id": "10248566",
"name": "signal-3",
"font_class": "signal-3",
"unicode": "e81a",
"unicode_decimal": 59418
},
{
"icon_id": "14536693",
"name": "signal-4",
"font_class": "signal-4",
"unicode": "f60e",
"unicode_decimal": 62990
},
{
"icon_id": "7757423",
"name": "mosquito.1",
"font_class": "mosquito1",
"unicode": "ebf6",
"unicode_decimal": 60406
},
{
"icon_id": "7757432",
"name": "mosquito",
"font_class": "mosquito",
"unicode": "ebf5",
"unicode_decimal": 60405
},
{
"icon_id": "6697986",
"name": "power_0",
"font_class": "power_",
"unicode": "e617",
"unicode_decimal": 58903
},
{
"icon_id": "6697988",
"name": "power_1",
"font_class": "power_1",
"unicode": "e618",
"unicode_decimal": 58904
},
{
"icon_id": "6697989",
"name": "power_2",
"font_class": "power_2",
"unicode": "e619",
"unicode_decimal": 58905
},
{
"icon_id": "6697991",
"name": "power_3",
"font_class": "power_3",
"unicode": "e61a",
"unicode_decimal": 58906
},
{
"icon_id": "6697992",
"name": "power_4",
"font_class": "power_4",
"unicode": "e61b",
"unicode_decimal": 58907
},
{
"icon_id": "6697993",
"name": "power_5",
"font_class": "power_5",
"unicode": "e61c",
"unicode_decimal": 58908
},
{
"icon_id": "6697994",
"name": "power_6",
"font_class": "power_6",
"unicode": "e61d",
"unicode_decimal": 58909
},
{
"icon_id": "6697995",
"name": "power_8",
"font_class": "power_8",
"unicode": "e61e",
"unicode_decimal": 58910
},
{
"icon_id": "6697996",
"name": "power_7",
"font_class": "power_7",
"unicode": "e61f",
"unicode_decimal": 58911
},
{
"icon_id": "6697997",
"name": "power_9",
"font_class": "power_9",
"unicode": "e625",
"unicode_decimal": 58917
}
]
}

View File

@ -0,0 +1,86 @@
<?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" >
<!--
2013-9-30: Created.
-->
<svg>
<metadata>
Created by iconfont
</metadata>
<defs>
<font id="iconfont" horiz-adv-x="1024" >
<font-face
font-family="iconfont"
font-weight="500"
font-stretch="normal"
units-per-em="1024"
ascent="896"
descent="-128"
/>
<missing-glyph />
<glyph glyph-name="abb_temperature-cels" unicode="&#58930;" d="M255.209807 191.012258V637.62942H191.407355v-446.617162a102.721947 102.721947 0 0 1-71.458746-95.703677 103.359972 103.359972 0 0 1 206.719943 0A102.721947 102.721947 0 0 1 255.209807 191.012258zM382.81471 765.234323v9.570368A169.076497 169.076497 0 0 1 262.228076 892.839227 174.180693 174.180693 0 0 1 63.802452 776.08074v-524.456153a223.308581 223.308581 0 0 1 15.950613-327.306577 225.222654 225.222654 0 0 1 144.19354-52.31801 213.100189 213.100189 0 0 1 39.55752 3.828147A222.670556 222.670556 0 0 1 382.81471 251.624587z m0-701.826968a159.506129 159.506129 0 0 0-259.675978-93.789604A161.420203 161.420203 0 0 0 63.802452 95.308581a158.868105 158.868105 0 0 0 52.956035 118.67256l10.846416 24.244932V758.854078A110.378241 110.378241 0 0 0 248.191537 829.036775 102.083923 102.083923 0 0 0 319.012258 760.130127v-521.904054l10.846417-24.244932A160.144154 160.144154 0 0 0 382.81471 63.407355zM870.903465 382.419613h-19.140735A86.771334 86.771334 0 0 0 765.62942 468.552923v146.745639A86.771334 86.771334 0 0 0 851.76273 701.431872h19.140735A86.771334 86.771334 0 0 0 957.036775 615.298562h63.802452A149.935761 149.935761 0 0 1 870.903465 765.234323h-19.140735A149.935761 149.935761 0 0 1 701.826968 615.298562v-146.745639A149.935761 149.935761 0 0 1 851.76273 318.617162h19.140735A149.935761 149.935761 0 0 1 1020.839227 468.552923h-63.802452A86.771334 86.771334 0 0 0 870.903465 382.419613zM606.123291 892.839227A95.703677 95.703677 0 1 1 701.826968 797.135549 95.703677 95.703677 0 0 1 606.123291 892.839227z m0-127.604904a31.901226 31.901226 0 1 0 31.901226 31.901226 31.901226 31.901226 0 0 0-31.901226-31.901226z" horiz-adv-x="1024" />
<glyph glyph-name="humidity" unicode="&#59439;" d="M241.664 252.928c21.504 34.816 51.712 63.488 87.04 83.968V771.072C328.704 839.168 384 894.976 452.608 894.976c68.608 0 123.904-55.296 123.904-123.904v-434.176c35.328-20.48 65.536-49.152 87.04-83.968 24.576-39.424 37.888-84.992 37.888-132.096 0-66.56-26.112-129.024-72.704-176.128-47.104-47.104-109.568-72.704-176.128-72.704s-129.024 26.112-176.128 72.704c-47.104 47.104-72.704 109.568-72.704 176.128 0.512 47.104 13.312 92.672 37.888 132.096zM453.12-87.04c114.688 0 207.872 93.184 207.872 207.872 0 78.848-43.52 149.504-113.664 185.344l-11.264 5.632V771.072c0 46.08-37.376 82.944-82.944 82.944s-82.944-37.376-82.944-82.944V312.32l-11.264-5.632c-70.144-35.84-113.664-107.008-113.664-185.344 0-114.688 93.184-208.384 207.872-208.384zM416.256 228.864V632.832c0 19.968 16.384 36.864 36.864 36.864 19.968 0 36.864-16.384 36.864-36.864v-403.456c42.496-14.848 73.216-55.808 73.216-103.424 0-60.416-49.152-110.08-110.08-110.08-60.416 0-110.08 49.152-110.08 110.08 0 47.616 30.72 88.064 73.216 102.912z m-167.936 532.48c0 23.04-41.984 92.672-41.984 92.672s-41.984-69.632-41.984-92.672c0-23.04 18.944-41.472 41.984-41.472 23.552-0.512 41.984 18.432 41.984 41.472zM164.352 393.216c0 34.304-62.976 138.24-62.976 138.24S38.4 427.52 38.4 393.216c0-34.304 28.16-62.464 62.976-62.464 34.816 0 62.976 28.16 62.976 62.464z m704.512-95.744c67.072 0 121.856 53.76 121.856 120.32s-121.856 267.776-121.856 267.776-121.856-201.216-121.856-267.776 54.272-120.32 121.856-120.32z" horiz-adv-x="1024" />
<glyph glyph-name="map" unicode="&#59011;" d="M590.385244 868.220491c-99.849476 0-180.759546-80.948617-180.759546-180.746697 0-99.836627 157.618521-277.833641 157.618521-412.118401l46.294899 0c0 133.809348 157.605672 320.415183 157.605672 412.118401C771.131941 787.271874 690.221871 868.220491 590.385244 868.220491zM590.385244 608.028509c-43.866441 0-79.458134 35.578844-79.458134 79.445285 0 43.866441 35.591693 79.445285 79.458134 79.445285 43.866441 0 79.445285-35.578844 79.445285-79.445285C669.830529 643.607353 634.251685 608.028509 590.385244 608.028509zM810.269954 775.643541c9.495401-23.616438 15.200351-49.108827 16.575193-75.744777l101.558391 50.804894 0-695.862576-152.645963-76.322981-230.896292 98.924349c-9.456854 4.073129-19.543309 6.09042-29.604065 6.09042-11.525541 0-23.038233-2.634042-33.587251-7.927825l-194.173888-97.086944-185.372332 79.406738L102.123747 758.335956l158.183876-67.778405c9.456854-4.073129 19.543309-6.09042 29.604065-6.09042 11.512692 0 23.025384 2.634042 33.587251 7.927825l30.799021 15.405935c3.122304 36.349784 14.493657 70.232562 32.21241 100.093607l-96.611531-48.299341L27.00857 872.255072l0-863.850229 262.915967-112.672765 225.34553 112.672765 262.915967-112.672765 225.34553 112.672765L1003.531564 872.255072 810.269954 775.643541zM515.270067 8.404843l224.369007-96.161817C729.53977 163.235134 608.283882 204.339043 515.270067 204.339043c-20.391342 0-36.349784-23.693532-75.128026-1.875952-65.465588 36.863743-44.444645 138.062363-150.217504 143.960048-93.913244 93.900395-225.358379 75.128026-225.358379 75.128026L27.00857 421.551164l0-413.14632 262.915967-112.672765L515.270067 8.404843z" horiz-adv-x="1031" />
<glyph glyph-name="xiangqing" unicode="&#58912;" d="M818.176 815.104c30.72 0 59.392-12.288 81.92-33.792 21.504-21.504 33.792-51.2 33.792-81.92v-628.736c0-30.72-12.288-59.392-33.792-81.92-21.504-21.504-51.2-33.792-81.92-33.792H205.824c-30.72 0-59.392 12.288-81.92 33.792-21.504 21.504-33.792 51.2-33.792 81.92V699.392c0 30.72 12.288 59.392 33.792 81.92 21.504 21.504 51.2 33.792 81.92 33.792h612.352m0 69.632H205.824c-102.4 0-185.344-83.968-185.344-185.344v-628.736c0-101.376 82.944-185.344 185.344-185.344h612.352c101.376 0 185.344 82.944 185.344 185.344V699.392c0 101.376-83.968 185.344-185.344 185.344z m0 0M191.488 416.768c-10.24 0-20.48 4.096-27.648 13.312-11.264 15.36-9.216 36.864 6.144 48.128L404.48 660.48c14.336 11.264 33.792 9.216 46.08-3.072l143.36-148.48L809.984 691.2c14.336 12.288 36.864 10.24 49.152-4.096 12.288-14.336 10.24-36.864-4.096-49.152L614.4 435.2c-14.336-11.264-34.816-10.24-47.104 2.048L421.888 587.776 212.992 424.96c-7.168-5.12-14.336-8.192-21.504-8.192zM727.04 251.904H295.936c-19.456 0-34.816 15.36-34.816 34.816s15.36 34.816 34.816 34.816H727.04c19.456 0 34.816-15.36 34.816-34.816 0-18.432-15.36-34.816-34.816-34.816z m0-161.792H295.936c-19.456 0-34.816 15.36-34.816 34.816s15.36 34.816 34.816 34.816H727.04c19.456 0 34.816-15.36 34.816-34.816s-15.36-34.816-34.816-34.816z m0 0" horiz-adv-x="1024" />
<glyph glyph-name="signal-2" unicode="&#59479;" d="M432 320h-96c-17.68 0-32-14.32-32-32v-384c0-17.68 14.32-32 32-32h96c17.68 0 32 14.32 32 32V288c0 17.68-14.32 32-32 32zM176 128H80c-17.68 0-32-14.32-32-32v-192c0-17.68 14.32-32 32-32h96c17.68 0 32 14.32 32 32v192c0 17.68-14.32 32-32 32z" horiz-adv-x="1280" />
<glyph glyph-name="signal-1" unicode="&#59416;" d="M176 128H80c-17.68 0-32-14.32-32-32v-192c0-17.68 14.32-32 32-32h96c17.68 0 32 14.32 32 32v192c0 17.68-14.32 32-32 32z" horiz-adv-x="1280" />
<glyph glyph-name="signal-3" unicode="&#59418;" d="M432 320h-96c-17.68 0-32-14.32-32-32v-384c0-17.68 14.32-32 32-32h96c17.68 0 32 14.32 32 32V288c0 17.68-14.32 32-32 32zM176 128H80c-17.68 0-32-14.32-32-32v-192c0-17.68 14.32-32 32-32h96c17.68 0 32 14.32 32 32v192c0 17.68-14.32 32-32 32z m512 384h-96c-17.68 0-32-14.32-32-32v-576c0-17.68 14.32-32 32-32h96c17.68 0 32 14.32 32 32V480c0 17.68-14.32 32-32 32z" horiz-adv-x="1280" />
<glyph glyph-name="signal-4" unicode="&#62990;" d="M432 320h-96c-17.68 0-32-14.32-32-32v-384c0-17.68 14.32-32 32-32h96c17.68 0 32 14.32 32 32V288c0 17.68-14.32 32-32 32zM176 128H80c-17.68 0-32-14.32-32-32v-192c0-17.68 14.32-32 32-32h96c17.68 0 32 14.32 32 32v192c0 17.68-14.32 32-32 32z m512 384h-96c-17.68 0-32-14.32-32-32v-576c0-17.68 14.32-32 32-32h96c17.68 0 32 14.32 32 32V480c0 17.68-14.32 32-32 32z m256 192h-96c-17.68 0-32-14.32-32-32v-768c0-17.68 14.32-32 32-32h96c17.68 0 32 14.32 32 32V672c0 17.68-14.32 32-32 32z" horiz-adv-x="1280" />
<glyph glyph-name="mosquito1" unicode="&#60406;" d="M965.973333 578.56c-85.333333 58.026667-283.306667-13.653333-351.573333-40.96l112.64 68.266667c3.413333 3.413333 6.826667 6.826667 6.826667 10.24L785.066667 800.426667l47.786666 47.786666c6.826667 6.826667 6.826667 17.066667 0 23.893334s-17.066667 6.826667-23.893333 0l-51.2-51.2c-3.413333 0-6.826667-3.413333-6.826667-6.826667l-47.786666-180.906667L580.266667 558.08v3.413333c13.653333 17.066667 17.066667 37.546667 17.066666 61.44 0 30.72-23.893333 75.093333-68.266666 81.92V759.466667c0 10.24-6.826667 17.066667-17.066667 17.066666s-17.066667-6.826667-17.066667-17.066666v-54.613334c-44.373333-10.24-68.266667-51.2-68.266666-81.92 0-23.893333 6.826667-44.373333 17.066666-61.44v-3.413333L320.853333 633.173333 273.066667 797.013333c0 3.413333 0 3.413333-3.413334 6.826667L218.453333 872.106667C211.626667 878.933333 201.386667 882.346667 194.56 875.52s-10.24-17.066667-3.413333-23.893333L238.933333 786.773333l51.2-167.253333c0-3.413333 3.413333-6.826667 6.826667-10.24l109.226667-68.266667c-68.266667 27.306667-262.826667 98.986667-348.16 44.373334-30.72-20.48-44.373333-51.2-44.373334-92.16 0-44.373333 17.066667-75.093333 47.786667-98.986667 30.72-20.48 71.68-27.306667 116.053333-27.306667 92.16 0 194.56 34.133333 221.866667 40.96l3.413333-10.24-102.4-34.133333c-6.826667-3.413333-10.24-6.826667-10.24-13.653333-3.413333-71.68-37.546667-256-119.466666-256-10.24 0-17.066667-6.826667-17.066667-17.066667s6.826667-17.066667 17.066667-17.066667c119.466667 0 146.773333 218.453333 153.6 276.48l88.746666 30.72 3.413334-20.48c-58.026667-34.133333-126.293333-249.173333-126.293334-303.786666 0-47.786667-61.44-105.813333-92.16-122.88-6.826667-3.413333-10.24-13.653333-6.826666-23.893334 3.413333-6.826667 10.24-10.24 13.653333-10.24 3.413333 0 6.826667 0 6.826667 3.413334 37.546667 20.48 112.64 85.333333 112.64 150.186666 0 54.613333 61.44 221.866667 98.986666 266.24l3.413334-10.24c-3.413333-37.546667-20.48-252.586667 37.546666-317.44 13.653333-13.653333 30.72-20.48 47.786667-20.48s34.133333 6.826667 47.786667 20.48c61.44 68.266667 40.96 283.306667 37.546666 317.44l3.413334 10.24c37.546667-44.373333 98.986667-211.626667 98.986666-266.24 0-64.853333 75.093333-133.12 112.64-150.186666 3.413333 0 6.826667-3.413333 6.826667-3.413334 6.826667 0 13.653333 3.413333 13.653333 10.24 3.413333 6.826667 0 17.066667-6.826666 23.893334-30.72 17.066667-92.16 75.093333-92.16 122.88 0 54.613333-68.266667 269.653333-126.293334 303.786666l3.413334 20.48 88.746666-30.72c6.826667-58.026667 34.133333-276.48 153.6-276.48 10.24 0 17.066667 6.826667 17.066667 17.066667s-6.826667 17.066667-17.066667 17.066667c-81.92 0-116.053333 184.32-119.466666 256 0 6.826667-3.413333 13.653333-10.24 13.653333l-102.4 34.133333 3.413333 10.24c27.306667-10.24 129.706667-40.96 221.866667-40.96 44.373333 0 88.746667 6.826667 119.466666 30.72 30.72 20.48 44.373333 51.2 44.373334 92.16-3.413333 40.96-17.066667 71.68-44.373334 88.746667z" horiz-adv-x="1024" />
<glyph glyph-name="mosquito" unicode="&#60405;" d="M958.933333 579.541333c-75.306667 49.365333-229.418667 4.778667-313.941333-25.856l70.826667 47.232a21.333333 21.333333 0 0 1 8.405333 11.008l62.421333 187.221334 39.082667 39.082666a21.333333 21.333333 0 0 1-30.165333 30.165334l-42.666667-42.666667a20.608 20.608 0 0 1-5.162667-8.32l-61.696-185.045333-98.133333-65.450667c7.381333 16.938667 9.429333 34.602667 9.429333 51.754667 0 30.848-20.096 72.490667-64 82.858666V768a21.333333 21.333333 0 0 1-42.666666 0v-66.474667C446.762667 691.157333 426.666667 649.514667 426.666667 618.666667c0-17.194667 2.048-34.858667 9.429333-51.797334L337.92 632.362667 276.224 817.408a20.608 20.608 0 0 1-5.162667 8.32l-42.666666 42.666667a21.333333 21.333333 0 0 1-30.165334-30.165334l39.125334-39.082666 62.421333-187.221334a21.162667 21.162667 0 0 1 8.405333-11.008l70.784-47.189333c-84.522667 30.677333-238.634667 75.264-313.898666 25.813333C45.098667 566.485333 21.333333 540.458667 21.333333 490.666667c0-41.813333 15.36-74.026667 45.696-95.701334 30.805333-21.973333 74.410667-29.653333 120.32-29.653333 70.656 0 146.730667 18.176 189.909334 30.421333l-86.528-34.602666a21.376 21.376 0 0 1-13.397334-18.773334C274.346667 281.216 248.277333 106.666667 170.666667 106.666667a21.333333 21.333333 0 0 1 0-42.666667c119.424 0 143.829333 202.752 148.394666 262.485333l88.661334 35.456 1.92-6.741333C353.536 312.32 277.333333 99.456 277.333333 42.666667c0-43.52-43.050667-92.885333-73.984-109.141334a21.333333 21.333333 0 1 1 19.925334-37.717333C262.272-83.669333 320-22.826667 320 42.666667c0 48 64.213333 216.917333 102.784 266.581333l3.541333-12.330667c-4.266667-37.76-22.656-229.845333 34.730667-294.570666 13.738667-15.488 31.36-23.68 50.944-23.68s37.205333 8.192 50.944 23.637333c57.386667 64.725333 38.997333 256.853333 34.730667 294.570667l3.541333 12.373333C639.829333 259.498667 704 90.666667 704 42.666667c0-65.493333 57.728-126.336 96.768-146.858667a21.12 21.12 0 0 1 28.757333 8.917333 21.333333 21.333333 0 0 1-8.917333 28.8C789.717333-50.218667 746.666667-0.853333 746.666667 42.666667c0 56.746667-76.117333 269.525333-132.309334 312.576l1.92 6.741333 88.618667-35.456c4.608-59.776 29.013333-262.528 148.437333-262.528a21.333333 21.333333 0 0 1-0.042666 42.709333c-77.568 0-103.68 174.549333-106.666667 235.690667a21.376 21.376 0 0 1-13.397333 18.773333l-85.888 34.346667c43.306667-12.245333 118.954667-30.250667 189.269333-30.250667 45.909333 0 89.514667 7.68 120.32 29.653334 30.378667 21.717333 45.738667 53.930667 45.738667 95.744 0 49.792-23.765333 75.818667-43.733334 88.874666z" horiz-adv-x="1024" />
<glyph glyph-name="power_" unicode="&#58903;" d="M172 42.666h100.66V725.334H172v-682.668z m1621.334 512V725.334C1793.334 819.2 1716.534 896 1622.666 896H172C78.134 896 1.334 819.2 1.334 725.334v-682.668C1.334-51.2 78.134-128 172-128h1450.666c93.868 0 170.668 76.8 170.668 170.666V213.334c46.932 0 85.332 38.4 85.332 85.332V469.334c0 46.932-38.4 85.332-85.332 85.332zM1708 469.334v-426.668c0-46.932-38.4-85.332-85.334-85.332H172c-46.934 0-85.334 38.4-85.334 85.332V725.334c0 46.932 38.4 85.332 85.334 85.332h1450.666c46.934 0 85.334-38.4 85.334-85.332v-256z" horiz-adv-x="1880" />
<glyph glyph-name="power_1" unicode="&#58904;" d="M172 42.666h280.66V725.334H172v-682.668z m1621.334 512V725.334C1793.334 819.2 1716.534 896 1622.666 896H172C78.134 896 1.334 819.2 1.334 725.334v-682.668C1.334-51.2 78.134-128 172-128h1450.666c93.868 0 170.668 76.8 170.668 170.666V213.334c46.932 0 85.332 38.4 85.332 85.332V469.334c0 46.932-38.4 85.332-85.332 85.332zM1708 469.334v-426.668c0-46.932-38.4-85.332-85.334-85.332H172c-46.934 0-85.334 38.4-85.334 85.332V725.334c0 46.932 38.4 85.332 85.334 85.332h1450.666c46.934 0 85.334-38.4 85.334-85.332v-256z" horiz-adv-x="1880" />
<glyph glyph-name="power_2" unicode="&#58905;" d="M172 42.666h462.66V725.334H172v-682.668z m1621.334 512V725.334C1793.334 819.2 1716.534 896 1622.666 896H172C78.134 896 1.334 819.2 1.334 725.334v-682.668C1.334-51.2 78.134-128 172-128h1450.666c93.868 0 170.668 76.8 170.668 170.666V213.334c46.932 0 85.332 38.4 85.332 85.332V469.334c0 46.932-38.4 85.332-85.332 85.332zM1708 469.334v-426.668c0-46.932-38.4-85.332-85.334-85.332H172c-46.934 0-85.334 38.4-85.334 85.332V725.334c0 46.932 38.4 85.332 85.334 85.332h1450.666c46.934 0 85.334-38.4 85.334-85.332v-256z" horiz-adv-x="1880" />
<glyph glyph-name="power_3" unicode="&#58906;" d="M172 42.666h590.66V725.334H172v-682.668z m1621.334 512V725.334C1793.334 819.2 1716.534 896 1622.666 896H172C78.134 896 1.334 819.2 1.334 725.334v-682.668C1.334-51.2 78.134-128 172-128h1450.666c93.868 0 170.668 76.8 170.668 170.666V213.334c46.932 0 85.332 38.4 85.332 85.332V469.334c0 46.932-38.4 85.332-85.332 85.332zM1708 469.334v-426.668c0-46.932-38.4-85.332-85.334-85.332H172c-46.934 0-85.334 38.4-85.334 85.332V725.334c0 46.932 38.4 85.332 85.334 85.332h1450.666c46.934 0 85.334-38.4 85.334-85.332v-256z" horiz-adv-x="1880" />
<glyph glyph-name="power_4" unicode="&#58907;" d="M172 42.666h720.66V725.334H172v-682.668z m1621.334 512V725.334C1793.334 819.2 1716.534 896 1622.666 896H172C78.134 896 1.334 819.2 1.334 725.334v-682.668C1.334-51.2 78.134-128 172-128h1450.666c93.868 0 170.668 76.8 170.668 170.666V213.334c46.932 0 85.332 38.4 85.332 85.332V469.334c0 46.932-38.4 85.332-85.332 85.332zM1708 469.334v-426.668c0-46.932-38.4-85.332-85.334-85.332H172c-46.934 0-85.334 38.4-85.334 85.332V725.334c0 46.932 38.4 85.332 85.334 85.332h1450.666c46.934 0 85.334-38.4 85.334-85.332v-256z" horiz-adv-x="1880" />
<glyph glyph-name="power_5" unicode="&#58908;" d="M172 42.666h830.66V725.334H172v-682.668z m1621.334 512V725.334C1793.334 819.2 1716.534 896 1622.666 896H172C78.134 896 1.334 819.2 1.334 725.334v-682.668C1.334-51.2 78.134-128 172-128h1450.666c93.868 0 170.668 76.8 170.668 170.666V213.334c46.932 0 85.332 38.4 85.332 85.332V469.334c0 46.932-38.4 85.332-85.332 85.332zM1708 469.334v-426.668c0-46.932-38.4-85.332-85.334-85.332H172c-46.934 0-85.334 38.4-85.334 85.332V725.334c0 46.932 38.4 85.332 85.334 85.332h1450.666c46.934 0 85.334-38.4 85.334-85.332v-256z" horiz-adv-x="1880" />
<glyph glyph-name="power_6" unicode="&#58909;" d="M172 42.666h970.66V725.334H172v-682.668z m1621.334 512V725.334C1793.334 819.2 1716.534 896 1622.666 896H172C78.134 896 1.334 819.2 1.334 725.334v-682.668C1.334-51.2 78.134-128 172-128h1450.666c93.868 0 170.668 76.8 170.668 170.666V213.334c46.932 0 85.332 38.4 85.332 85.332V469.334c0 46.932-38.4 85.332-85.332 85.332zM1708 469.334v-426.668c0-46.932-38.4-85.332-85.334-85.332H172c-46.934 0-85.334 38.4-85.334 85.332V725.334c0 46.932 38.4 85.332 85.334 85.332h1450.666c46.934 0 85.334-38.4 85.334-85.332v-256z" horiz-adv-x="1880" />
<glyph glyph-name="power_8" unicode="&#58910;" d="M172 42.666000000000054h1270.66V725.3340000000001H172v-682.668z m1621.334 512V725.3340000000001C1793.334 819.2 1716.534 896 1622.666 896H172C78.134 896 1.334 819.2 1.334 725.3340000000001v-682.668C1.334-51.200000000000045 78.134-128 172-128h1450.666c93.868 0 170.668 76.8 170.668 170.666V213.33399999999995c46.932 0 85.332 38.4 85.332 85.332V469.334c0 46.932-38.4 85.332-85.332 85.332zM1708 469.334v-426.668c0-46.932-38.4-85.332-85.334-85.332H172c-46.934 0-85.334 38.4-85.334 85.332V725.3340000000001c0 46.932 38.4 85.332 85.334 85.332h1450.666c46.934 0 85.334-38.4 85.334-85.332v-256z" horiz-adv-x="1880" />
<glyph glyph-name="power_7" unicode="&#58911;" d="M172 42.666000000000054h1110.66V725.3340000000001H172v-682.668z m1621.334 512V725.3340000000001C1793.334 819.2 1716.534 896 1622.666 896H172C78.134 896 1.334 819.2 1.334 725.3340000000001v-682.668C1.334-51.200000000000045 78.134-128 172-128h1450.666c93.868 0 170.668 76.8 170.668 170.666V213.33399999999995c46.932 0 85.332 38.4 85.332 85.332V469.334c0 46.932-38.4 85.332-85.332 85.332zM1708 469.334v-426.668c0-46.932-38.4-85.332-85.334-85.332H172c-46.934 0-85.334 38.4-85.334 85.332V725.3340000000001c0 46.932 38.4 85.332 85.334 85.332h1450.666c46.934 0 85.334-38.4 85.334-85.332v-256z" horiz-adv-x="1880" />
<glyph glyph-name="power_9" unicode="&#58917;" d="M172 42.666h1450.666V725.334H172v-682.668z m1621.334 512V725.334C1793.334 819.2 1716.534 896 1622.666 896H172C78.134 896 1.334 819.2 1.334 725.334v-682.668C1.334-51.2 78.134-128 172-128h1450.666c93.868 0 170.668 76.8 170.668 170.666V213.334c46.932 0 85.332 38.4 85.332 85.332V469.334c0 46.932-38.4 85.332-85.332 85.332zM1708 469.334v-426.668c0-46.932-38.4-85.332-85.334-85.332H172c-46.934 0-85.334 38.4-85.334 85.332V725.334c0 46.932 38.4 85.332 85.334 85.332h1450.666c46.934 0 85.334-38.4 85.334-85.332v-256z" horiz-adv-x="1880" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View File

@ -4,7 +4,8 @@
<svg-icon class-name='international-icon' icon-class="language" />
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="zh" :disabled="language==='zh'">中文</el-dropdown-item>
<el-dropdown-item command="zh" :disabled="language==='zh'">简体</el-dropdown-item>
<el-dropdown-item command="hk" :disabled="language==='hk'">繁体</el-dropdown-item>
<el-dropdown-item command="en" :disabled="language==='en'">English</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>

View File

@ -0,0 +1,42 @@
import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event'
/**
* How to use
* <el-table height="100px" v-el-height-adaptive-table="{bottomOffset: 30}">...</el-table>
* el-table height is must be set
* bottomOffset: 30(default) // The height of the table from the bottom of the page.
*/
const doResize = (el, binding, vnode) => {
const { componentInstance: $table } = vnode
const { value } = binding
if (!$table.height) {
throw new Error(`el-$table must set the height. Such as height='100px'`)
}
const bottomOffset = (value && value.bottomOffset) || 30
if (!$table) return
const height = window.innerHeight - el.getBoundingClientRect().top - bottomOffset
$table.layout.setHeight(height)
$table.doLayout()
}
export default {
bind(el, binding, vnode) {
el.resizeListener = () => {
doResize(el, binding, vnode)
}
addResizeListener(el, el.resizeListener)
},
inserted(el, binding, vnode) {
doResize(el, binding, vnode)
},
unbind(el) {
removeResizeListener(el, el.resizeListener)
}
}

View File

@ -0,0 +1,14 @@
import adaptive from './adaptive'
const install = function(Vue) {
Vue.directive('el-height-adaptive-table', adaptive)
}
if (window.Vue) {
window['el-height-adaptive-table'] = adaptive
Vue.use(install); // eslint-disable-line
}
adaptive.install = install
export default adaptive

1
src/icons/svg/device.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="1534320378407" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1009" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M959.68 642.944l-1.472-10.432-96.96-338.816C834.688 201.088 741.312 128 649.6 128L409.536 128C318.272 128 221.824 198.08 189.312 287.68l-123.008 339.2L64 640l0 73.088C64 813.952 141.568 896 236.992 896l550.656 0c95.488 0 172.864-82.24 172.352-183.424L959.68 642.944zM253.696 313.92c22.208-61.312 93.12-112.768 155.84-112.768l240.064 0c61.44 0 127.936 52.032 145.6 113.728l83.904 293.12L147.072 608 253.696 313.92zM787.648 822.784 236.992 822.784c-57.344 0-104-49.344-104-109.76L132.992 672l757.824 0 0.192 40.96C891.328 773.568 844.928 822.784 787.648 822.784z" p-id="1010"></path><path d="M736 704l64 0 0 64-64 0 0-64Z" p-id="1011"></path></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

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="1533866109364" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13626" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M683.323077 710.892308c9.846154-9.846154 9.846154-25.6 0-35.446154l-35.446154-35.446154c-9.846154-9.846154-25.6-9.846154-35.446154 0l-86.646154 86.646154c-5.907692 5.907692-17.723077 5.907692-23.630769 0l-86.646154-86.646154c-9.846154-9.846154-25.6-9.846154-35.446154 0l-35.446153 35.446154c-9.846154 9.846154-9.846154 25.6 0 35.446154l86.646153 86.646154c5.907692 5.907692 5.907692 17.723077 0 23.630769l-86.646153 86.646154c-9.846154 9.846154-9.846154 25.6 0 35.446153l35.446153 35.446154c9.846154 9.846154 25.6 9.846154 35.446154 0l86.646154-86.646154c5.907692-5.907692 17.723077-5.907692 23.630769 0l86.646154 86.646154c9.846154 9.846154 25.6 9.846154 35.446154 0l35.446154-35.446154c9.846154-9.846154 9.846154-25.6 0-35.446153l-86.646154-86.646154c-5.907692-5.907692-5.907692-17.723077 0-23.630769l86.646154-86.646154z m256-482.461539c-108.307692-120.123077-261.907692-187.076923-425.353846-187.076923S196.923077 108.307692 88.615385 228.430769c-7.876923 7.876923-5.907692 21.661538 1.96923 27.569231l59.076923 51.2c7.876923 7.876923 19.692308 5.907692 27.569231-1.969231 86.646154-92.553846 208.738462-145.723077 336.738462-145.723077s250.092308 53.169231 336.738461 145.723077c7.876923 7.876923 19.692308 7.876923 27.569231 1.969231l59.076923-51.2c7.876923-7.876923 9.846154-19.692308 1.969231-27.569231z m-425.353846 88.615385c-82.707692 0-161.476923 35.446154-216.615385 98.461538-7.876923 7.876923-5.907692 21.661538 1.969231 29.538462l63.015385 47.261538c7.876923 5.907692 19.692308 5.907692 25.6-1.96923 33.476923-35.446154 78.769231-55.138462 126.030769-55.138462s92.553846 19.692308 124.061538 53.169231c5.907692 7.876923 17.723077 7.876923 25.6 1.969231l63.015385-47.261539c9.846154-7.876923 9.846154-19.692308 1.969231-29.538461-53.169231-61.046154-131.938462-96.492308-214.646154-96.492308z" p-id="13627"></path></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

1
src/icons/svg/online.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

1
src/icons/svg/plus.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="1533866120081" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13747" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M832 1024H192c-106.048 0-192-86.016-192-192V192a192 192 0 0 1 192-192h640a192 192 0 0 1 192 192v640c0 105.984-85.952 192-192 192z m64-832a64 64 0 0 0-64-64H192a64 64 0 0 0-64 64v640c0 35.392 28.608 64 64 64h640c35.392 0 64-28.608 64-64V192z m-192 384h-128v128c0 35.392-28.608 64-64 64s-64-28.608-64-64v-128h-128a64 64 0 1 1 0-128h128v-128a64 64 0 1 1 128 0v128h128a64 64 0 1 1 0 128z" fill="" p-id="13748"></path></svg>

After

Width:  |  Height:  |  Size: 806 B

1
src/icons/svg/rise.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="1533866073593" class="icon" style="" viewBox="0 0 1025 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13505" xmlns:xlink="http://www.w3.org/1999/xlink" width="200.1953125" height="200"><defs><style type="text/css"></style></defs><path d="M977.19856 256H785.19856a48 48 0 1 0 0 96h76.112L655.26256 558.064l-27.808 27.808-4.768 4.768L561.19856 652.128 339.13456 430.064A47.824 47.824 0 0 0 305.19856 416a47.84 47.84 0 0 0-33.936 14.064l-256 256a48 48 0 1 0 67.872 67.872L305.19856 531.888l222.064 222.064A47.904 47.904 0 0 0 561.19856 768a47.84 47.84 0 0 0 33.936-14.064l95.424-95.44L929.19856 419.888V496a48 48 0 1 0 96 0V304a48 48 0 0 0-48-48z" fill="" p-id="13506"></path></svg>

After

Width:  |  Height:  |  Size: 836 B

1
src/icons/svg/system.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="1534320364216" class="icon" style="" viewBox="0 0 1170 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="895" xmlns:xlink="http://www.w3.org/1999/xlink" width="228.515625" height="200"><defs><style type="text/css"></style></defs><path d="M787.333533 588.946109a75.190803 75.190803 0 0 0-75.09328 75.09328 75.190803 75.190803 0 0 0 75.09328 75.093279 75.166423 75.166423 0 0 0 75.068899-75.093279 75.166423 75.166423 0 0 0-75.068899-75.09328m0 222.841745a147.919132 147.919132 0 0 1-147.748466-147.748465c0-81.456704 66.291762-147.748466 147.748466-147.748466 81.432323 0 147.748466 66.291762 147.748466 147.748466 0 81.481085-66.316143 147.748466-147.748466 147.748465m89.45365 102.107356c0.341333 0.243809 1.31657 0.585142 2.316189 0.585143h0.121905l71.484901-39.497115c-1.706665-4.022854-9.606088-23.47884-9.606088-43.739397a113.858966 113.858966 0 0 1 107.739351-113.615157c0.853333-4.729901 5.558853-31.524549 5.558853-51.638821s-4.70552-46.884538-5.558853-51.63882A113.858966 113.858966 0 0 1 941.10409 500.784648c0-20.358081 7.923804-39.814067 9.606088-43.81254l-70.314616-39.058258-0.292572-0.024381a5.339425 5.339425 0 0 0-2.706283 0.731428 196.754145 196.754145 0 0 1-26.014458 21.820937c-21.699032 15.238084-42.154637 22.966841-60.952337 22.966841-18.919606 0-39.594638-7.875042-61.391195-23.405698a194.706147 194.706147 0 0 1-26.160743-22.284174 5.778282 5.778282 0 0 0-2.730665-0.707048h-0.243809l-72.825853 40.033496c1.706665 4.047235 9.581707 23.47884 9.581708 43.739397a113.858966 113.858966 0 0 1-107.763733 113.566395c-0.853333 4.729901-5.510091 31.524549-5.510091 51.63882s4.656759 46.908919 5.534472 51.663202a113.858966 113.858966 0 0 1 107.763733 113.590776c0 20.3337-7.972566 39.862829-9.679231 43.788159l68.973665 38.546258h0.146285c1.023999 0 1.950475-0.365714 2.316189-0.585143a200.850142 200.850142 0 0 1 26.428933-23.161888c22.089127-16.188941 43.081112-24.429697 62.415194-24.429697 19.55351 0 40.716161 8.387042 62.951574 24.917316 14.921132 11.068944 25.258649 22.186651 26.550838 23.576364m22.67427 108.397637c-13.775228-0.024381-27.135981-5.705139-35.766832-15.213703-11.775992-12.897515-49.005679-46.445681-79.53061-46.445682-30.281121 0-68.120332 33.767595-78.994229 45.543587-8.60647 9.38666-21.869699 14.969894-35.498641 14.969894-6.485329 0-12.604943-1.243428-18.188178-3.705902l-0.975237-0.414476-92.696315-51.833868-0.926475-0.682666a44.470825 44.470825 0 0 1-14.921133-53.735581c0.048762-0.146286 8.533327-19.699795 8.533328-37.595401a98.377073 98.377073 0 0 0-98.255168-98.255168h-3.90095c-15.506275 0-28.15998-13.799609-32.182834-35.108547-0.341333-1.706665-7.923804-42.179017-7.923804-74.044899 0-31.914644 7.55809-72.362615 7.899423-74.118042 4.120378-21.577127 16.993512-35.449879 32.816738-35.084166h3.267046a98.401454 98.401454 0 0 0 98.279549-98.30393c0-17.846844-8.484565-37.400354-8.557709-37.619782a44.348921 44.348921 0 0 1 15.067418-53.662438l0.950857-0.658285 97.840692-53.759962 1.023999-0.414476c5.48571-2.364951 11.507801-3.535236 17.895606-3.535235 13.604562 0 26.892171 5.436948 35.596165 14.628561 11.580944 12.117325 48.176727 43.641874 77.775183 43.641873 29.354646 0 65.755382-30.915026 77.287564-42.812922 8.655232-8.996565 21.845318-14.33599 35.303594-14.335989 6.50971 0 12.653705 1.219047 18.285701 3.65714l0.975237 0.414476 94.476123 52.516534 0.950857 0.658285c16.895988 11.751611 23.332555 34.889118 14.945513 53.735581-0.048762 0.146286-8.533327 19.699795-8.533328 37.546639a98.401454 98.401454 0 0 0 98.255168 98.279549h3.291427c15.774465-0.341333 28.720741 13.507038 32.816738 35.108547 0.316952 1.706665 7.899423 42.203398 7.899423 74.06928 0 31.890263-7.582471 72.411377-7.948185 74.118042-4.047235 21.552747-16.993512 35.425499-32.767976 35.059785h-3.291427a98.401454 98.401454 0 0 0-98.255168 98.279549c0 17.846844 8.484565 37.449116 8.557709 37.619782a44.422064 44.422064 0 0 1-15.018656 53.7112l-0.926476 0.682666-96.134026 53.101677-0.975238 0.414475a44.885301 44.885301 0 0 1-17.846844 3.583998zM1121.523008 316.952398a48.76187 48.76187 0 1 1-97.523739 0V121.978061C1023.999269 108.519785 1013.125372 97.523984 999.691476 97.523984H121.831532C108.568303 97.523984 97.52374 108.495404 97.52374 121.978061v584.996154c0 13.458276 10.873897 24.454078 24.307792 24.454078H341.33309a48.76187 48.76187 0 1 1 0 97.52374H48.908156A48.76187 48.76187 0 0 1 0 780.190163V48.762114C0 21.821181 21.89408 0.000244 48.908156 0.000244h1023.706697A48.76187 48.76187 0 0 1 1121.523008 48.762114v268.190284zM219.428415 975.237642c0-26.940933 21.991603-48.76187 48.981298-48.761869h194.608623a48.76187 48.76187 0 1 1 0 97.523739H268.434094A48.76187 48.76187 0 0 1 219.428415 975.237642z" p-id="896"></path></svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -4,9 +4,14 @@ export default {
introduction: 'Introduction',
documentation: 'Documentation',
counter: 'Counter',
statistic: 'Statistic',
device: 'Device',
count: 'Count',
statistic: 'data statistics',
device: 'Device Status',
detail: 'Device Detail',
logs: 'Log List',
map: 'Map',
weather: 'Weather Station',
deviceSetting: 'Device Setting',
systemSetting: 'System Setting',
guide: 'Guide',
permission: 'Permission',
pagePermission: 'Page Permission',
@ -148,5 +153,86 @@ export default {
close: 'Close',
closeOthers: 'Close Others',
closeAll: 'Close All'
},
counter: {
online: 'online',
offline: 'offline',
all: 'all',
inputDeviceID: 'Device ID',
inputStatus: 'status',
search: 'search',
reset: 'reset',
detail: 'Detail',
map: 'Map',
sn: 'No.',
device: 'Device',
status: 'Status',
count: 'Count',
signal: 'Signal',
energy: 'Energy',
time: 'Time',
date: 'Date',
coordinate: 'Coordinate',
action: 'Action',
logDesc: 'Mosquito killer log list',
screen: 'Screen chart',
trendChart: 'Trend chart',
region: 'Region',
deviceName: 'Device Name',
noName: 'No Name',
humitureChart: 'Humiture chart',
temperature: 'Temperature',
humidity: 'Humidity',
logSeachContent: 'Device ID/Name',
to: 'To',
start_date: 'Start Date',
end_date: 'End Date'
},
weather: {
online: 'online',
offline: 'offline',
all: 'all',
inputDeviceID: 'Device ID',
inputStatus: 'status',
search: 'search',
reset: 'reset',
detail: 'Detail',
map: 'Map',
sn: 'No.',
device: 'Device ID',
status: 'Status',
count: 'Count',
signal: 'Signal',
energy: 'Energy',
time: 'Time',
date: 'Date',
coordinate: 'Coordinate',
action: 'Action',
logDesc: 'Mosquito killer log list',
screen: 'Screen chart',
trendChart: 'Trend chart',
region: 'Region',
deviceName: 'Device Name',
humitureChart: 'Humiture chart',
temperature: 'Temperature(℃)',
humidity: 'Humidity',
logSeachContent: 'Device ID/Name',
to: 'To',
start_date: 'Start Date',
end_date: 'End Date',
envTemp: 'Env. Temp(℃)',
dewPointTemp: 'Daw Point Temp(℃)',
envHumi: 'Env. Humi(%RH)',
airPressure: 'Air Pressure(hPa)',
totalRadiation1Ins: 'Total Radiation 1 Ins(W/㎡)',
windDirection: 'Wind Directiong(°)',
windSpeedIns: 'Wind Speed Ins(m/s)',
windSpeed2mins: 'Wind Speed 2mins(m/s)',
windSpeed10mins: 'Wind Speed 10mins(m/s)',
rainfallIntervalCum: 'Rainfall Interval Cum(mm)',
totalRadiation1IntervalCum: 'Total Radiation 1 Interval Cum(MJ/㎡)',
rainfallDailyCum: 'Rainfall Daily Cum(mm)',
totalRadiation1DailyCum: 'Total Radiation 1 Daily Cum(MJ/㎡)',
power: 'Power(%)'
}
}

238
src/lang/hk.js Normal file
View File

@ -0,0 +1,238 @@
export default {
route: {
dashboard: '儀表板',
introduction: '簡述',
documentation: '文檔',
counter: '滅蚊燈數據',
statistic: '數據統計',
device: '狀態監控',
detail: '設備詳情',
logs: '日誌列表',
map: '區域地圖',
weather: '氣象台',
deviceSetting: '設備設置',
systemSetting: '系統設置',
guide: '引導頁',
permission: '權限測試頁',
pagePermission: '頁面權限',
directivePermission: '指令權限',
icons: '圖標',
components: '組件',
componentIndex: '介紹',
tinymce: '富文本編輯器',
markdown: 'Markdown',
jsonEditor: 'JSON編輯器',
dndList: '列表拖拽',
splitPane: 'Splitpane',
avatarUpload: '頭像上傳',
dropzone: 'Dropzone',
sticky: 'Sticky',
countTo: 'CountTo',
componentMixin: '小組件',
backToTop: '返回頂部',
dragDialog: '拖拽 Dialog',
dragKanban: '可拖拽看板',
charts: '圖表',
keyboardChart: '鍵盤圖表',
lineChart: '折線圖',
mixChart: '混合圖表',
example: '綜合實例',
nested: '路由嵌套',
bar: 'Bar',
barProfile: 'Profile',
barPosts: 'Posts',
Table: 'Table',
dynamicTable: '動態Table',
dragTable: '拖拽Table',
inlineEditTable: 'Table內編輯',
complexTable: '綜合Table',
treeTable: '樹形表格',
customTreeTable: '自定義樹表',
tab: 'Tab',
form: '表單',
createArticle: '創建文章',
editArticle: '編輯文章',
articleList: '文章列表',
errorPages: '錯誤頁面',
page401: '401',
page404: '404',
errorLog: '錯誤日誌',
excel: 'Excel',
exportExcel: '導出 Excel',
selectExcel: '導出選定',
uploadExcel: '上傳 Excel',
zip: 'Zip',
exportZip: '導出 Zip',
theme: '換膚',
clipboardDemo: 'Clipboard',
i18n: '國際化'
},
navbar: {
logOut: '退出登錄',
dashboard: '首頁',
github: '項目地址',
screenfull: '全屏',
theme: '換膚'
},
login: {
title: '系統登錄',
logIn: '登錄',
username: '賬號',
password: '密碼',
any: '隨便填',
thirdparty: '第三方登錄',
thirdpartyTips: '本地不能模擬,請結合自己業務進行模擬!!!'
},
documentation: {
documentation: '文檔',
github: 'Github 地址'
},
permission: {
roles: '你的權限',
switchRoles: '切換權限'
},
guide: {
description: '引導頁對於一些第一次進入項目的人很有用,你可以簡單介紹下項目的功能。本 Demo 是基於',
button: '打開引導'
},
components: {
documentation: '文檔',
tinymceTips: '富文本是管理後臺一個核心的功能但同時又是一個有很多坑的地方。在選擇富文本的過程中我也走了不少的彎路市面上常見的富文本都基本用過了最終權衡了一下選擇了Tinymce。更詳細的富文本比較和介紹見',
dropzoneTips: '由於我司業務有特殊需求,而且要傳七牛 所以沒用第三方,選擇了自己封裝。代碼非常的簡單,具體代碼你可以在這裡看到 @/components/Dropzone',
stickyTips: '當頁面滾動到預設的位置會吸附在頂部',
backToTopTips1: '頁面滾動到指定位置會在右下角出現返回頂部按鈕',
backToTopTips2: '可自定義按鈕的樣式、show/hide、出現的高度、返回的位置 如需文字提示可在外部使用Element的el-tooltip元素',
imageUploadTips: '由於我在使用時它只有vue@1版本而且和mockjs不兼容所以自己改造了一下如果大家要使用的話優先還是使用官方版本。'
},
table: {
dynamicTips1: '固定表頭, 按照表頭順序排序',
dynamicTips2: '不固定表頭, 按照點擊順序排序',
dragTips1: '默認順序',
dragTips2: '拖拽後順序',
title: '標題',
importance: '重要性',
type: '類型',
remark: '點評',
search: '搜索',
add: '添加',
export: '導出',
reviewer: '審核人',
id: '序號',
date: '時間',
author: '作者',
readings: '閱讀數',
status: '狀態',
actions: '操作',
edit: '編輯',
publish: '發布',
draft: '草稿',
delete: '刪除',
cancel: '取 消',
confirm: '確 定'
},
errorLog: {
tips: '請點擊右上角bug小圖標',
description: '現在的管理後臺基本都是spa的形式了它增強了用戶體驗但同時也會增加頁面出問題的可能性可能一個小小的疏忽就導致整個頁面的死鎖。好在 Vue 官網提供了一個方法來捕獲處理異常,你可以在其中進行錯誤處理或者異常上報。',
documentation: '文檔介紹'
},
excel: {
export: '導出',
selectedExport: '導出已選擇項',
placeholder: '請輸入文件名(默認excel-list)'
},
zip: {
export: '導出',
placeholder: '請輸入文件名(默認file)'
},
theme: {
change: '換膚',
documentation: '換膚文檔',
tips: 'Tips: 它區別於 navbar 上的 theme-pick, 是兩種不同的換膚方法,各自有不同的應用場景,具體請參考文檔。'
},
tagsView: {
close: '關閉',
closeOthers: '關閉其它',
closeAll: '關閉所有'
},
counter: {
online: '在線',
offline: '離線',
all: '全部',
inputDeviceID: '設備 ID',
inputStatus: '狀態',
search: '搜索',
reset: '重置',
detail: '詳情',
map: '地圖',
sn: '序號',
device: '設備ID',
status: '狀態',
count: '計數',
signal: '信號',
energy: '電量',
time: '時間',
date: '日期',
coordinate: '坐標',
action: '操作',
logDesc: '滅蚊器日誌列表',
screen: '顯示屏',
trendChart: '趨勢圖',
region: '地區',
deviceName: '設備名稱',
noName: '未命名',
humitureChart: '溫濕度',
temperature: '溫度',
humidity: '濕度',
to: '至',
logSeachContent: '設備名稱/ID',
start_date: '開始日期',
end_date: '結束日期'
},
weather: {
online: '在線',
offline: '離線',
all: '全部',
inputDeviceID: '設備 ID',
inputStatus: '狀態',
search: '搜索',
reset: '重置',
detail: '詳情',
map: '地圖',
sn: '序號',
device: '設備ID',
status: '狀態',
count: '計數',
signal: '信號',
energy: '電量',
time: '時間',
date: '日期',
coordinate: '坐標',
action: '操作',
logDesc: '滅蚊器日誌列表',
screen: '顯示屏',
trendChart: '趨勢圖',
region: '地區',
deviceName: '設備名稱',
humitureChart: '溫濕度',
temperature: '溫度',
humidity: '濕度',
to: '至',
logSeachContent: '設備名稱/ID',
start_date: '開始日期',
end_date: '結束日期',
envTemp: '環溫(℃)',
dewPointTemp: '露點溫度(℃)',
envHumi: '環濕(%RH)',
airPressure: '氣壓(hPa)',
totalRadiation1Ins: '總輻射1瞬時(W/㎡)',
windDirection: '風向(°)',
windSpeedIns: '瞬時風速(m/s)',
windSpeed2mins: '2分鐘風速(m/s)',
windSpeed10mins: '10分鐘風速(m/s)',
rainfallIntervalCum: '雨量間隔累計(mm)',
totalRadiation1IntervalCum: '總輻射1間隔累計(MJ/㎡)',
rainfallDailyCum: '雨量日累計(mm)',
totalRadiation1DailyCum: '總輻射1日累計(MJ/㎡)',
power: '電量(%)'
}
}

View File

@ -3,8 +3,10 @@ import VueI18n from 'vue-i18n'
import Cookies from 'js-cookie'
import elementEnLocale from 'element-ui/lib/locale/lang/en' // element-ui lang
import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN'// element-ui lang
import elementHkLocale from 'element-ui/lib/locale/lang/zh-TW'// element-ui lang
import enLocale from './en'
import zhLocale from './zh'
import hkLocale from './hk'
Vue.use(VueI18n)
@ -16,6 +18,10 @@ const messages = {
zh: {
...zhLocale,
...elementZhLocale
},
hk: {
...hkLocale,
...elementHkLocale
}
}

View File

@ -1,12 +1,17 @@
export default {
route: {
dashboard: '首页',
dashboard: '仪表盘',
introduction: '简述',
documentation: '文档',
counter: '灭蚊器',
statistic: '统计',
device: '设备',
count: '计数',
counter: '灭蚊灯数据',
statistic: '数据统计',
device: '状态监控',
detail: '设备详情',
logs: '日志列表',
map: '区域地图',
weather: '气象台',
deviceSetting: '设备设置',
systemSetting: '系统设置',
guide: '引导页',
permission: '权限测试页',
pagePermission: '页面权限',
@ -148,5 +153,86 @@ export default {
close: '关闭',
closeOthers: '关闭其它',
closeAll: '关闭所有'
},
counter: {
online: '在线',
offline: '离线',
all: '全部',
inputDeviceID: '设备 ID',
inputStatus: '状态',
search: '搜索',
reset: '重置',
detail: '详情',
map: '地图',
sn: '序号',
device: '设备ID',
status: '状态',
count: '计数',
signal: '信号',
energy: '电量',
time: '时间',
date: '日期',
coordinate: '坐标',
action: '操作',
logDesc: '灭蚊器日志列表',
screen: '显示屏',
trendChart: '趋势图',
region: '地区',
deviceName: '设备名称',
noName: '未命名',
humitureChart: '温湿度',
temperature: '温度',
humidity: '湿度',
to: '至',
logSeachContent: '设备名称/ID',
start_date: '开始日期',
end_date: '结束日期'
},
weather: {
online: '在线',
offline: '离线',
all: '全部',
inputDeviceID: '设备 ID',
inputStatus: '状态',
search: '搜索',
reset: '重置',
detail: '详情',
map: '地图',
sn: '序号',
device: '设备ID',
status: '状态',
count: '计数',
signal: '信号',
energy: '电量',
time: '时间',
date: '日期',
coordinate: '坐标',
action: '操作',
logDesc: '灭蚊器日志列表',
screen: '显示屏',
trendChart: '趋势图',
region: '地区',
deviceName: '设备名称',
humitureChart: '温湿度',
temperature: '温度',
humidity: '湿度',
to: '至',
logSeachContent: '设备名称/ID',
start_date: '开始日期',
end_date: '结束日期',
envTemp: '环温(℃)',
dewPointTemp: '露点温度(℃)',
envHumi: '环湿(%RH)',
airPressure: '气压(hPa)',
totalRadiation1Ins: '总辐射1瞬时(W/㎡)',
windDirection: '风向(°)',
windSpeedIns: '瞬时风速(m/s)',
windSpeed2mins: '2分钟风速(m/s)',
windSpeed10mins: '10分钟风速(m/s)',
rainfallIntervalCum: '雨量间隔累计(mm)',
totalRadiation1IntervalCum: '总辐射1间隔累计(MJ/㎡)',
rainfallDailyCum: '雨量日累计(mm)',
totalRadiation1DailyCum: '总辐射1日累计(MJ/㎡)',
power: '电量(%)'
}
}

View File

@ -13,11 +13,33 @@ import store from './store'
import i18n from './lang' // Internationalization
import './icons' // icon
import './assets/icon/iconfont.css' // ali icon
import './errorLog'// error log
import './permission' // permission control
// import './mock' // simulation data
import * as filters from './filters' // global filters
// import VueAMap from 'vue-amap'
// Vue.use(VueAMap)
// VueAMap.initAMapApiLoader({
// key: '250fde87c69f9f46d0a2bdbc561a82a8',
// plugin: [
// 'AMap.Geolocation',
// 'AMap.Driving',
// 'AMap.Walking',
// 'AMap.Autocomplete',
// 'AMap.PlaceSearch',
// 'AMap.Scale',
// 'AMap.OverView',
// 'AMap.ToolBar',
// 'AMap.MapType',
// 'AMap.PolyEditor',
// 'AMap.CircleEditor'
// ],
// // 默认高德 sdk 版本为 1.4.4
// v: '1.4.4'
// })
Vue.use(Element, {
size: 'medium', // set element-ui default size

View File

@ -1,4 +1,4 @@
import { param2Obj } from '@/utils'
import { param2Obj } from '@/utils'
const userMap = {
admin: {

View File

@ -61,22 +61,24 @@ export const constantRouterMap = [
icon: 'chart'
},
children: [
{ path: 'index', component: () => import('@/views/counter/index'), name: 'statistic', meta: { title: 'statistic' }},
// { path: 'index', component: () => import('@/views/counter/index'), name: 'statistic', meta: { title: 'statistic' }},
{ path: 'device', component: () => import('@/views/counter/device'), name: 'device', meta: { title: 'device' }},
{ path: 'count', component: () => import('@/views/counter/count'), name: 'count', meta: { title: 'count' }}
{ path: 'detail', component: () => import('@/views/counter/detail'), name: 'detail', meta: { title: 'detail' }},
{ path: 'logs', component: () => import('@/views/counter/logs'), name: 'logs', meta: { title: 'logs' }},
{ path: 'map', component: () => import('@/views/counter/map2'), name: 'map', meta: { title: 'map' }}
]
},
{
path: '',
component: Layout,
redirect: 'weather',
children: [{
path: 'weather',
component: () => import('@/views/weather/index'),
name: 'weather',
meta: { title: 'weather', icon: 'international', noCache: true }
}]
}
// {
// path: '/guide',
// component: Layout,
// redirect: '/guide/index',
// children: [{
// path: 'index',
// component: () => import('@/views/guide/index'),
// name: 'guide',
// meta: { title: 'guide', icon: 'guide', noCache: true }
// }]
// }
]
export default new Router({
@ -86,233 +88,5 @@ export default new Router({
})
export const asyncRouterMap = [
{
path: '/permission',
component: Layout,
redirect: '/permission/index',
alwaysShow: true, // will always show the root menu
meta: {
title: 'permission',
icon: 'lock',
roles: ['admin', 'editor'] // you can set roles in root nav
},
children: [{
path: 'page',
component: () => import('@/views/permission/page'),
name: 'pagePermission',
meta: {
title: 'pagePermission',
roles: ['admin'] // or you can only set roles in sub nav
}
}, {
path: 'directive',
component: () => import('@/views/permission/directive'),
name: 'directivePermission',
meta: {
title: 'directivePermission'
// if do not set roles, means: this page does not require permission
}
}]
},
{
path: '/icon',
component: Layout,
children: [{
path: 'index',
component: () => import('@/views/svg-icons/index'),
name: 'icons',
meta: { title: 'icons', icon: 'icon', noCache: true }
}]
},
// {
// path: '/components',
// component: Layout,
// redirect: 'noredirect',
// name: 'component-demo',
// meta: {
// title: 'components',
// icon: 'component'
// },
// children: [
// { path: 'tinymce', component: () => import('@/views/components-demo/tinymce'), name: 'tinymce-demo', meta: { title: 'tinymce' }},
// { path: 'markdown', component: () => import('@/views/components-demo/markdown'), name: 'markdown-demo', meta: { title: 'markdown' }},
// { path: 'json-editor', component: () => import('@/views/components-demo/jsonEditor'), name: 'jsonEditor-demo', meta: { title: 'jsonEditor' }},
// { path: 'splitpane', component: () => import('@/views/components-demo/splitpane'), name: 'splitpane-demo', meta: { title: 'splitPane' }},
// { path: 'avatar-upload', component: () => import('@/views/components-demo/avatarUpload'), name: 'avatarUpload-demo', meta: { title: 'avatarUpload' }},
// { path: 'dropzone', component: () => import('@/views/components-demo/dropzone'), name: 'dropzone-demo', meta: { title: 'dropzone' }},
// { path: 'sticky', component: () => import('@/views/components-demo/sticky'), name: 'sticky-demo', meta: { title: 'sticky' }},
// { path: 'count-to', component: () => import('@/views/components-demo/countTo'), name: 'countTo-demo', meta: { title: 'countTo' }},
// { path: 'mixin', component: () => import('@/views/components-demo/mixin'), name: 'componentMixin-demo', meta: { title: 'componentMixin' }},
// { path: 'back-to-top', component: () => import('@/views/components-demo/backToTop'), name: 'backToTop-demo', meta: { title: 'backToTop' }},
// { path: 'drag-dialog', component: () => import('@/views/components-demo/dragDialog'), name: 'dragDialog-demo', meta: { title: 'dragDialog' }},
// { path: 'dnd-list', component: () => import('@/views/components-demo/dndList'), name: 'dndList-demo', meta: { title: 'dndList' }},
// { path: 'drag-kanban', component: () => import('@/views/components-demo/dragKanban'), name: 'dragKanban-demo', meta: { title: 'dragKanban' }}
// ]
// },
// {
// path: '/charts',
// component: Layout,
// redirect: 'noredirect',
// name: 'charts',
// meta: {
// title: 'charts',
// icon: 'chart'
// },
// children: [
// { path: 'keyboard', component: () => import('@/views/charts/keyboard'), name: 'keyboardChart', meta: { title: 'keyboardChart', noCache: true }},
// { path: 'line', component: () => import('@/views/charts/line'), name: 'lineChart', meta: { title: 'lineChart', noCache: true }},
// { path: 'mixchart', component: () => import('@/views/charts/mixChart'), name: 'mixChart', meta: { title: 'mixChart', noCache: true }}
// ]
// },
// {
// path: '/tab',
// component: Layout,
// children: [{
// path: 'index',
// component: () => import('@/views/tab/index'),
// name: 'tab',
// meta: { title: 'tab', icon: 'tab' }
// }]
// },
// {
// path: '/table',
// component: Layout,
// redirect: '/table/complex-table',
// name: 'table',
// meta: {
// title: 'Table',
// icon: 'table'
// },
// children: [
// { path: 'dynamic-table', component: () => import('@/views/table/dynamicTable/index'), name: 'dynamicTable', meta: { title: 'dynamicTable' }},
// { path: 'drag-table', component: () => import('@/views/table/dragTable'), name: 'dragTable', meta: { title: 'dragTable' }},
// { path: 'inline-edit-table', component: () => import('@/views/table/inlineEditTable'), name: 'inlineEditTable', meta: { title: 'inlineEditTable' }},
// { path: 'tree-table', component: () => import('@/views/table/treeTable/treeTable'), name: 'treeTableDemo', meta: { title: 'treeTable' }},
// { path: 'custom-tree-table', component: () => import('@/views/table/treeTable/customTreeTable'), name: 'customTreeTableDemo', meta: { title: 'customTreeTable' }},
// { path: 'complex-table', component: () => import('@/views/table/complexTable'), name: 'complexTable', meta: { title: 'complexTable' }}
// ]
// },
// {
// path: '/example',
// component: Layout,
// redirect: '/example/list',
// name: 'example',
// meta: {
// title: 'example',
// icon: 'example'
// },
// children: [
// { path: 'create', component: () => import('@/views/example/create'), name: 'createArticle', meta: { title: 'createArticle', icon: 'edit' }},
// { path: 'edit/:id(\\d+)', component: () => import('@/views/example/edit'), name: 'editArticle', meta: { title: 'editArticle', noCache: true }, hidden: true },
// { path: 'list', component: () => import('@/views/example/list'), name: 'articleList', meta: { title: 'articleList', icon: 'list' }}
// ]
// },
// {
// path: '/nested',
// component: Layout,
// redirect: '/nested/bar/profile',
// name: 'nested',
// meta: {
// title: 'nested',
// icon: 'nested'
// },
// children: [
// {
// path: '/nested/bar', // Must write the full path
// component: () => import('@/views/nested/bar/index'), // Parent router-view
// name: 'bar',
// meta: { title: 'bar' },
// children: [
// {
// path: 'profile',
// component: () => import('@/views/nested/bar/profile'),
// name: 'bar-profile',
// meta: { title: 'barProfile' }
// },
// {
// path: 'posts',
// component: () => import('@/views/nested/bar/posts'),
// name: 'bar-posts',
// meta: { title: 'barPosts' }
// }
// ]
// }
// ]
// },
// {
// path: '/error',
// component: Layout,
// redirect: 'noredirect',
// name: 'errorPages',
// meta: {
// title: 'errorPages',
// icon: '404'
// },
// children: [
// { path: '401', component: () => import('@/views/errorPage/401'), name: 'page401', meta: { title: 'page401', noCache: true }},
// { path: '404', component: () => import('@/views/errorPage/404'), name: 'page404', meta: { title: 'page404', noCache: true }}
// ]
// },
// {
// path: '/error-log',
// component: Layout,
// redirect: 'noredirect',
// children: [{ path: 'log', component: () => import('@/views/errorLog/index'), name: 'errorLog', meta: { title: 'errorLog', icon: 'bug' }}]
// },
// {
// path: '/excel',
// component: Layout,
// redirect: '/excel/export-excel',
// name: 'excel',
// meta: {
// title: 'excel',
// icon: 'excel'
// },
// children: [
// { path: 'export-excel', component: () => import('@/views/excel/exportExcel'), name: 'exportExcel', meta: { title: 'exportExcel' }},
// { path: 'export-selected-excel', component: () => import('@/views/excel/selectExcel'), name: 'selectExcel', meta: { title: 'selectExcel' }},
// { path: 'upload-excel', component: () => import('@/views/excel/uploadExcel'), name: 'uploadExcel', meta: { title: 'uploadExcel' }}
// ]
// },
// {
// path: '/zip',
// component: Layout,
// redirect: '/zip/download',
// alwaysShow: true,
// meta: { title: 'zip', icon: 'zip' },
// children: [{ path: 'download', component: () => import('@/views/zip/index'), name: 'exportZip', meta: { title: 'exportZip' }}]
// },
// {
// path: '/theme',
// component: Layout,
// redirect: 'noredirect',
// children: [{ path: 'index', component: () => import('@/views/theme/index'), name: 'theme', meta: { title: 'theme', icon: 'theme' }}]
// },
// {
// path: '/clipboard',
// component: Layout,
// redirect: 'noredirect',
// children: [{ path: 'index', component: () => import('@/views/clipboard/index'), name: 'clipboardDemo', meta: { title: 'clipboardDemo', icon: 'clipboard' }}]
// },
// {
// path: '/i18n',
// component: Layout,
// children: [{ path: 'index', component: () => import('@/views/i18n-demo/index'), name: 'i18n', meta: { title: 'i18n', icon: 'international' }}]
// },
{ path: '*', redirect: '/404', hidden: true }
]

View File

@ -13,6 +13,8 @@ const getters = {
setting: state => state.user.setting,
permission_routers: state => state.permission.routers,
addRouters: state => state.permission.addRouters,
errorLogs: state => state.errorLog.logs
errorLogs: state => state.errorLog.logs,
deviceID: state => state.counter.deviceID,
mapClick: state => state.counter.mapClick
}
export default getters

View File

@ -5,6 +5,7 @@ import errorLog from './modules/errorLog'
import permission from './modules/permission'
import tagsView from './modules/tagsView'
import user from './modules/user'
import counter from './modules/counter'
import getters from './getters'
Vue.use(Vuex)
@ -15,7 +16,8 @@ const store = new Vuex.Store({
errorLog,
permission,
tagsView,
user
user,
counter
},
getters
})

View File

@ -0,0 +1,33 @@
const counter = {
state: {
deviceID: '',
mapClick: false
},
mutations: {
CHANGE_DEVICE_ID: (state, deviceID) => {
state.deviceID = deviceID
localStorage.deviceID = deviceID
},
CHANGE_MAP_CLICK: (state, mapClick) => {
state.mapClick = mapClick
}
},
actions: {
changeDeviceID({ commit }, deviceID) {
commit('CHANGE_DEVICE_ID', deviceID)
},
changeMapClick({ commit }, mapClick) {
commit('CHANGE_MAP_CLICK', mapClick)
}
}
}
try {
if (localStorage.deviceID) {
counter.state.deviceID = localStorage.deviceID
}
} catch (e) {
console.log(e)
}
export default counter

View File

@ -100,11 +100,12 @@ const user = {
// },
// 登出
LogOut({ commit, state }) {
LogOut({ commit, state, rootState }) {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
commit('CHANGE_DEVICE_ID', '', { root: true })
removeToken()
resolve()
}).catch(error => {

View File

@ -4,6 +4,7 @@
@import './element-ui.scss';
@import './sidebar.scss';
@import './btn.scss';
@import './pagination.scss';
body {
height: 100%;
@ -128,7 +129,7 @@ code {
//main-container全局样式
.app-container {
padding: 20px;
padding: 10px;
}
.components-container {

View File

@ -0,0 +1,60 @@
.pagination {
float: right;
font-weight: normal;
padding: 2rem 0 1rem 0;
.btn-prev {
border: 1px solid #d1dbe5;
border-right: 0;
border-radius: 0 !important;
background: #fff !important;
margin: 0 !important;
}
.btn-next {
border: 1px solid #d1dbe5;
// border-left: 0;
background: #fff !important;
border-radius: 0!important;
margin: 0 !important;
}
.el-pager li {
border: 1px solid #d1dbe5;
box-sizing: border-box;
background: #fff !important;
border-radius: 0!important;
border-right: 0;
padding: 0;
margin: 0 !important;
}
.el-pager li:not(.disabled).active {
background: #409EFF !important;
border-color: #409EFF;
}
.el-pagination__jump {
margin-left: .8rem;
}
.el-pagination__editor.el-input {
width: 2.5rem;
}
}
// mobile
@media screen and (max-width: 375px) {
.pagination {
display: flex !important;
justify-content: center;
float: none;
padding: 1rem 0 1rem 0;
.el-pager li {
// height: 1.5rem;
// line-height: 1.5rem;
font-size: .5rem !important;
// min-width: 1.5rem !important;
}
.el-pagination__total {
// margin-right: 2rem;
display: none !important;
}
.el-pagination__jump {
display: none !important;
}
}
}

View File

@ -1,12 +1,12 @@
import axios from 'axios'
import { Message } from 'element-ui'
import { Message, MessageBox } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
// create an axios instance
const service = axios.create({
baseURL: process.env.BASE_API, // api的base_url
timeout: 5000 // request timeout
timeout: 50000 // request timeout
})
// request interceptor
@ -62,7 +62,27 @@ service.interceptors.response.use(
// },
error => {
console.log('err' + error)
if (error && error.response) {
if (error && error.response) { // 401 token 过期
if (error.response.status === 401) {
const ret = error.response
const url = ret.config.url
const target = '/users/info'
console.log(url.indexOf(target))
// check if 401 get /api/users/info/ then redirect to /login
if (url.indexOf(target) === -1) {
MessageBox.confirm('登录过期已被登出,取消继续留在该页面,或者重新登录', '确定登出', {
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
store.dispatch('FedLogOut').then(() => {
location.reload() // 为了重新实例化vue-router对象 避免bug
})
})
return Promise.reject(error)
}
error.message = ret.data.detail
}
// check login error response from server api
const login_error = error.response.data.non_field_errors
if (login_error) {

View File

@ -5,7 +5,7 @@
export function isvalidUsername(str) {
// const valid_map = ['xianfuxing', 'editor']
// return valid_map.indexOf(str.trim()) >= 0
const usernameRegex = /^(?![0-9]+$)[0-9A-Za-z]{4,}$/
const usernameRegex = /^(?![0-9]+$)[0-9A-Za-z_]{4,}$/
return usernameRegex.test(str)
}

View File

@ -1,45 +0,0 @@
<template>
<div class="app-container">
<el-tabs v-model="activeName">
<el-tab-pane label="use clipboard directly" name="directly">
<el-input v-model="inputData" placeholder="Please input" style='width:400px;'></el-input>
<el-button type="primary" icon="document" @click='handleCopy(inputData,$event)'>copy</el-button>
</el-tab-pane>
<el-tab-pane label="use clipboard by v-directive" name="v-directive">
<el-input v-model="inputData" placeholder="Please input" style='width:400px;'></el-input>
<el-button type="primary" icon="document" v-clipboard:copy='inputData' v-clipboard:success='clipboardSuccess'>copy</el-button>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import clip from '@/utils/clipboard' // use clipboard directly
import clipboard from '@/directive/clipboard/index.js' // use clipboard by v-directive
export default {
name: 'clipboardDemo',
directives: {
clipboard
},
data() {
return {
activeName: 'directly',
inputData: 'https://github.com/PanJiaChen/vue-element-admin'
}
},
methods: {
handleCopy(text, event) {
clip(text, event)
},
clipboardSuccess() {
this.$message({
message: '复制成功',
type: 'success',
duration: 1500
})
}
}
}
</script>

View File

@ -1,52 +0,0 @@
<template>
<div class="components-container">
<code>This is based on
<a class="link-type" href="//github.com/dai-siki/vue-image-crop-upload"> vue-image-crop-upload</a>.
{{$t('components.imageUploadTips')}}
</code>
<pan-thumb :image="image"></pan-thumb>
<el-button type="primary" icon="upload" style="position: absolute;bottom: 15px;margin-left: 40px;" @click="imagecropperShow=true">Change avatar
</el-button>
<image-cropper :width="300" :height="300" url="https://httpbin.org/post" @close='close' @crop-upload-success="cropSuccess" langType="en"
:key="imagecropperKey" v-show="imagecropperShow"></image-cropper>
</div>
</template>
<script>
import ImageCropper from '@/components/ImageCropper'
import PanThumb from '@/components/PanThumb'
export default {
name: 'avatarUpload-demo',
components: { ImageCropper, PanThumb },
data() {
return {
imagecropperShow: false,
imagecropperKey: 0,
image: 'https://wpimg.wallstcn.com/577965b9-bb9e-4e02-9f0c-095b41417191'
}
},
methods: {
cropSuccess(resData) {
this.imagecropperShow = false
this.imagecropperKey = this.imagecropperKey + 1
this.image = resData.files.avatar
},
close() {
this.imagecropperShow = false
}
}
}
</script>
<style scoped>
.avatar{
width: 200px;
height: 200px;
border-radius: 50%;
}
</style>

View File

@ -1,150 +0,0 @@
<template>
<div class="components-container">
<code>{{$t('components.backToTopTips1')}}</code>
<code>{{$t('components.backToTopTips2')}}</code>
<div class="placeholder-container">
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
</div>
<!--可自定义按钮的样式show/hide临界点返回的位置 -->
<!--如需文字提示可在外部添加element的<el-tooltip></el-tooltip> -->
<el-tooltip placement="top" content="tooltip">
<back-to-top transitionName="fade" :customStyle="myBackToTopStyle" :visibilityHeight="300" :backPosition="50"></back-to-top>
</el-tooltip>
</div>
</template>
<script>
import BackToTop from '@/components/BackToTop'
export default {
name: 'backToTop-demo',
components: { BackToTop },
data() {
return {
myBackToTopStyle: {
right: '50px',
bottom: '50px',
width: '40px',
height: '40px',
'border-radius': '4px',
'line-height': '45px', // Please keep consistent with height to center vertically
background: '#e7eaf1'// The background color of the button
}
}
}
}
</script>
<style scoped>
.placeholder-container div {
margin: 10px;
}
</style>

View File

@ -1,205 +0,0 @@
<template>
<div class="components-container">
<p class="warn-content">
<a href="https://github.com/PanJiaChen/vue-countTo" target="_blank">countTo-component</a>
</p>
<count-to ref="example" class="example" :start-val="_startVal" :end-val="_endVal" :duration="_duration" :decimals="_decimals"
:separator="_separator" :prefix="_prefix" :suffix="_suffix" :autoplay="false"></count-to>
<div style="margin-left: 25%;margin-top: 40px;">
<label class="label" for="startValInput">startVal:
<input type="number" v-model.number="setStartVal" name="startValInput" />
</label>
<label class="label" for="endValInput">endVal:
<input type="number" v-model.number="setEndVal" name="endVaInput" />
</label>
<label class="label" for="durationInput">duration:
<input type="number" v-model.number="setDuration" name="durationInput" />
</label>
<div class="startBtn example-btn" @click="start">开始</div>
<div class="pause-resume-btn example-btn" @click="pauseResume">暂停/恢复</div>
<br/>
<label class="label" for="decimalsInput">decimals:
<input type="number" v-model.number="setDecimals" name="decimalsInput" />
</label>
<label class="label" for="separatorInput">separator:
<input v-model="setSeparator" name="separatorInput" />
</label>
<label class="label" for="prefixInput">prefix:
<input v-model="setPrefix" name="prefixInput" />
</label>
<label class="label" for="suffixInput">suffix:
<input v-model="setSuffix" name="suffixInput" />
</label>
</div>
<code>&lt;count-to :start-val=&#x27;{{_startVal}}&#x27; :end-val=&#x27;{{_endVal}}&#x27; :duration=&#x27;{{_duration}}&#x27;
:decimals=&#x27;{{_decimals}}&#x27; :separator=&#x27;{{_separator}}&#x27; :prefix=&#x27;{{_prefix}}&#x27; :suffix=&#x27;{{_suffix}}&#x27;
:autoplay=false&gt;</code>
</div>
</template>
<script>
import countTo from 'vue-count-to'
export default {
name: 'countTo-demo',
components: { countTo },
data() {
return {
setStartVal: 0,
setEndVal: 2017,
setDuration: 4000,
setDecimals: 0,
setSeparator: ',',
setSuffix: ' rmb',
setPrefix: '¥ '
}
},
computed: {
_startVal() {
if (this.setStartVal) {
return this.setStartVal
} else {
return 0
}
},
_endVal() {
if (this.setEndVal) {
return this.setEndVal
} else {
return 0
}
},
_duration() {
if (this.setDuration) {
return this.setDuration
} else {
return 100
}
},
_decimals() {
if (this.setDecimals) {
if (this.setDecimals < 0 || this.setDecimals > 20) {
alert('digits argument must be between 0 and 20')
return 0
}
return this.setDecimals
} else {
return 0
}
},
_separator() {
return this.setSeparator
},
_suffix() {
return this.setSuffix
},
_prefix() {
return this.setPrefix
}
},
methods: {
start() {
this.$refs.example.start()
},
pauseResume() {
this.$refs.example.pauseResume()
}
}
}
</script>
<style scoped>
.example-btn {
display: inline-block;
margin-bottom: 0;
font-weight: 500;
text-align: center;
-ms-touch-action: manipulation;
touch-action: manipulation;
cursor: pointer;
background-image: none;
border: 1px solid transparent;
white-space: nowrap;
line-height: 1.5;
padding: 4px 15px;
font-size: 12px;
border-radius: 4px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-transition: all .3s cubic-bezier(.645, .045, .355, 1);
transition: all .3s cubic-bezier(.645, .045, .355, 1);
position: relative;
color: rgba(0, 0, 0, .65);
background-color: #fff;
border-color: #d9d9d9;
}
.example-btn:hover {
color: #4AB7BD;
background-color: #fff;
border-color: #4AB7BD;
}
.example {
font-size: 50px;
color: #F6416C;
display: block;
margin: 10px 0;
text-align: center;
font-size: 80px;
font-weight: 500;
}
.label {
color: #2f4f4f;
font-size: 16px;
display: inline-block;
margin: 15px 30px 15px 0;
}
input {
position: relative;
display: inline-block;
padding: 4px 7px;
width: 70px;
height: 28px;
cursor: text;
font-size: 12px;
line-height: 1.5;
color: rgba(0, 0, 0, .65);
background-color: #fff;
background-image: none;
border: 1px solid #d9d9d9;
border-radius: 4px;
-webkit-transition: all .3s;
transition: all .3s;
}
.startBtn {
margin-left: 20px;
font-size: 20px;
color: #30B08F;
background-color: #fff;
}
.startBtn:hover {
background-color: #30B08F;
color: #fff;
border-color: #30B08F;
}
.pause-resume-btn {
font-size: 20px;
color: #E65D6E;
background-color: #fff;
}
.pause-resume-btn:hover {
background-color: #E65D6E;
color: #fff;
border-color: #E65D6E;
}
</style>

View File

@ -1,40 +0,0 @@
<template>
<div class="components-container">
<code>drag-list base on
<a href="https://github.com/SortableJS/Vue.Draggable" target="_blank">Vue.Draggable</a>
</code>
<div class="editor-container">
<dnd-list :list1="list1" :list2="list2" list1Title="List" list2Title="Article pool"></dnd-list>
</div>
</div>
</template>
<script>
import DndList from '@/components/DndList'
import { fetchList } from '@/api/article'
export default {
name: 'dndList-demo',
components: { DndList },
data() {
return {
list1: [],
list2: []
}
},
created() {
this.getData()
},
methods: {
getData() {
this.listLoading = true
fetchList().then(response => {
this.list1 = response.data.items.splice(0, 5)
this.list2 = response.data.items
})
}
}
}
</script>

View File

@ -1,60 +0,0 @@
<template>
<div class="components-container">
<el-button type="primary" @click="dialogTableVisible = true">open a Drag Dialog</el-button>
<el-dialog v-el-drag-dialog @dragDialog="handleDrag" title="Shipping address" :visible.sync="dialogTableVisible">
<el-select ref="select" v-model="value" placeholder="请选择">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
<el-table :data="gridData">
<el-table-column property="date" label="Date" width="150"></el-table-column>
<el-table-column property="name" label="Name" width="200"></el-table-column>
<el-table-column property="address" label="Address"></el-table-column>
</el-table>
</el-dialog>
</div>
</template>
<script>
import elDragDialog from '@/directive/el-dragDialog' // base on element-ui
export default {
name: 'dragDialog-demo',
directives: { elDragDialog },
data() {
return {
dialogTableVisible: false,
options: [
{ value: '选项1', label: '黄金糕' },
{ value: '选项2', label: '双皮奶' },
{ value: '选项3', label: '蚵仔煎' },
{ value: '选项4', label: '龙须面' }
],
value: '',
gridData: [{
date: '2016-05-02',
name: 'John Smith',
address: 'No.1518, Jinshajiang Road, Putuo District'
}, {
date: '2016-05-04',
name: 'John Smith',
address: 'No.1518, Jinshajiang Road, Putuo District'
}, {
date: '2016-05-01',
name: 'John Smith',
address: 'No.1518, Jinshajiang Road, Putuo District'
}, {
date: '2016-05-03',
name: 'John Smith',
address: 'No.1518, Jinshajiang Road, Putuo District'
}]
}
},
methods: {
// v-el-drag-dialog onDrag callback function
handleDrag() {
this.$refs.select.blur()
}
}
}
</script>

View File

@ -1,68 +0,0 @@
<template>
<div class="components-container board">
<Kanban :key="1" class="kanban todo" :list="list1" :options="options" header-text="Todo"/>
<Kanban :key="2" class="kanban working" :list="list2" :options="options" header-text="Working"/>
<Kanban :key="3" class="kanban done" :list="list3" :options="options" header-text="Done"/>
</div>
</template>
<script>
import Kanban from '@/components/Kanban'
export default {
name: 'dragKanban-demo',
components: {
Kanban
},
data() {
return {
options: {
group: 'mission'
},
list1: [
{ name: 'Mission', id: 1 },
{ name: 'Mission', id: 2 },
{ name: 'Mission', id: 3 },
{ name: 'Mission', id: 4 }
],
list2: [
{ name: 'Mission', id: 5 },
{ name: 'Mission', id: 6 },
{ name: 'Mission', id: 7 }
],
list3: [
{ name: 'Mission', id: 8 },
{ name: 'Mission', id: 9 },
{ name: 'Mission', id: 10 }
]
}
}
}
</script>
<style lang="scss">
.board {
width: 1000px;
margin-left: 20px;
display: flex;
justify-content: space-around;
flex-direction: row;
align-items: flex-start;
}
.kanban {
&.todo {
.board-column-header {
background: #4A9FF9;
}
}
&.working {
.board-column-header {
background: #f9944a;
}
}
&.done {
.board-column-header {
background: #2ac06d;
}
}
}
</style>

View File

@ -1,32 +0,0 @@
<template>
<div class="components-container">
<code>
Based on <a class="link-type" href="https://github.com/rowanwins/vue-dropzone"> dropzone </a>.
{{$t('components.dropzoneTips')}}
</code>
<div class="editor-container">
<dropzone v-on:dropzone-removedFile="dropzoneR" v-on:dropzone-success="dropzoneS" id="myVueDropzone" url="https://httpbin.org/post"></dropzone>
</div>
</div>
</template>
<script>
import Dropzone from '@/components/Dropzone'
export default {
name: 'dropzone-demo',
components: { Dropzone },
methods: {
dropzoneS(file) {
console.log(file)
this.$message({ message: 'Upload success', type: 'success' })
},
dropzoneR(file) {
console.log(file)
this.$message({ message: 'Delete success', type: 'success' })
}
}
}
</script>

View File

@ -1,32 +0,0 @@
<template>
<div class="components-container">
<code>JsonEditor is base on <a href="https://github.com/codemirror/CodeMirror" target="_blank">CodeMirrorr</a> , lint base on json-lint </code>
<div class="editor-container">
<json-editor ref="jsonEditor" v-model="value"></json-editor>
</div>
</div>
</template>
<script>
import JsonEditor from '@/components/JsonEditor'
const jsonData = '[{"items":[{"market_type":"forexdata","symbol":"XAUUSD"},{"market_type":"forexdata","symbol":"UKOIL"},{"market_type":"forexdata","symbol":"CORN"}],"name":""},{"items":[{"market_type":"forexdata","symbol":"XAUUSD"},{"market_type":"forexdata","symbol":"XAGUSD"},{"market_type":"forexdata","symbol":"AUTD"},{"market_type":"forexdata","symbol":"AGTD"}],"name":"贵金属"},{"items":[{"market_type":"forexdata","symbol":"CORN"},{"market_type":"forexdata","symbol":"WHEAT"},{"market_type":"forexdata","symbol":"SOYBEAN"},{"market_type":"forexdata","symbol":"SUGAR"}],"name":"农产品"},{"items":[{"market_type":"forexdata","symbol":"UKOIL"},{"market_type":"forexdata","symbol":"USOIL"},{"market_type":"forexdata","symbol":"NGAS"}],"name":"能源化工"}]'
export default {
name: 'jsonEditor-demo',
components: { JsonEditor },
data() {
return {
value: JSON.parse(jsonData)
}
}
}
</script>
<style scoped>
.editor-container{
position: relative;
height: 100%;
}
</style>

View File

@ -1,49 +0,0 @@
<template>
<div class="components-container">
<code>Markdown is based on
<a href="https://github.com/sparksuite/simplemde-markdown-editor" target="_blank">simplemde-markdown-editor</a> Simply encapsulated in Vue.
<a target="_blank" href="https://segmentfault.com/a/1190000009762198#articleHeader14">
相关文章 </a>
</code>
<div class="editor-container">
<markdown-editor id="contentEditor" ref="contentEditor" v-model="content" :height="300" :zIndex="20"></markdown-editor>
</div>
<el-button @click="markdown2Html" style="margin-top:80px;" type="primary" icon="el-icon-document">To HTML</el-button>
<div v-html="html"></div>
</div>
</template>
<script>
import MarkdownEditor from '@/components/MarkdownEditor'
const content = `
**this is test**
* vue
* element
* webpack
## Simplemde
`
export default {
name: 'markdown-demo',
components: { MarkdownEditor },
data() {
return {
content: content,
html: ''
}
},
methods: {
markdown2Html() {
import('showdown').then(showdown => {
const converter = new showdown.Converter()
this.html = converter.makeHtml(this.content)
})
}
}
}
</script>

View File

@ -1,154 +0,0 @@
<template>
<div class="mixin-components-container">
<el-row>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>Buttons</span>
</div>
<div style="margin-bottom:50px;">
<el-col :span="4" class="text-center">
<router-link class="pan-btn blue-btn" to="/components/index">Components</router-link>
</el-col>
<el-col :span="4" class="text-center">
<router-link class="pan-btn light-blue-btn" to="/charts/index">Charts</router-link>
</el-col>
<el-col :span="4" class="text-center">
<router-link class="pan-btn pink-btn" to="/excel/download">Excel</router-link>
</el-col>
<el-col :span="4" class="text-center">
<router-link class="pan-btn green-btn" to="/example/table/complex-table">Table</router-link>
</el-col>
<el-col :span="4" class="text-center">
<router-link class="pan-btn tiffany-btn" to="/form/edit-form">Form</router-link>
</el-col>
<el-col :span="4" class="text-center">
<router-link class="pan-btn yellow-btn" to="/theme/index">Theme</router-link>
</el-col>
</div>
</el-card>
</el-row>
<el-row :gutter="20" style="margin-top:50px;">
<el-col :span="6">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>Material Design 的input</span>
</div>
<div style="height:100px;">
<el-form :model="demo" :rules="demoRules">
<el-form-item prop="title">
<md-input icon="search" name="title" placeholder="输入标题" v-model="demo.title">标题</md-input>
</el-form-item>
</el-form>
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>图片hover效果</span>
</div>
<div class="component-item">
<pan-thumb width="100px" height="100px" image="https://wpimg.wallstcn.com/577965b9-bb9e-4e02-9f0c-095b41417191">
vue-element-admin
</pan-thumb>
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>水波纹 waves v-directive</span>
</div>
<div class="component-item">
<el-button v-waves type="primary">水波纹效果</el-button>
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>hover text</span>
</div>
<div class="component-item">
<mallki className="mallki-text" text="vue-element-admin"></mallki>
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" style="margin-top:50px;">
<el-col :span="6">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>Share</span>
</div>
<div class="component-item" style="height:420px;">
<dropdown-menu style="margin:0 auto;" title='系列文章' :items='articleList'></dropdown-menu>
</div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import PanThumb from '@/components/PanThumb'
import MdInput from '@/components/MDinput'
import Mallki from '@/components/TextHoverEffect/Mallki'
import DropdownMenu from '@/components/Share/dropdownMenu'
import waves from '@/directive/waves/index.js' //
export default {
name: 'componentMixin-demo',
components: {
PanThumb,
MdInput,
Mallki,
DropdownMenu
},
directives: {
waves
},
data() {
const validate = (rule, value, callback) => {
if (value.length !== 6) {
callback(new Error('请输入六个字符'))
} else {
callback()
}
}
return {
demo: {
title: ''
},
demoRules: {
title: [{ required: true, trigger: 'change', validator: validate }]
},
articleList: [
{ title: '基础篇', href: 'https://segmentfault.com/a/1190000009275424' },
{ title: '登录权限篇', href: 'https://segmentfault.com/a/1190000009506097' },
{ title: '实战篇', href: 'https://segmentfault.com/a/1190000009762198' },
{ title: 'vueAdmin-template 篇', href: 'https://segmentfault.com/a/1190000010043013' },
{ title: '自行封装 component', href: 'https://segmentfault.com/a/1190000009090836' },
{ title: '优雅的使用 icon', href: 'https://segmentfault.com/a/https://segmentfault.com/a/1190000012213278' }
]
}
}
}
</script>
<style scoped>
.mixin-components-container {
background-color: #f0f2f5;
padding: 30px;
min-height: calc(100vh - 84px);
}
.component-item{
min-height: 100px;
}
</style>

View File

@ -1,67 +0,0 @@
<template>
<div class="components-container">
<code><strong>SplitPane</strong> If you've used
<a href="http://codepen.io/" target="_blank"> codepen</a>,
<a href="https://jsfiddle.net/" target="_blank"> jsfiddle </a>will not be unfamiliar.
<a href="https://github.com/PanJiaChen/vue-split-pane" target='_blank'> Github repository</a>
</code>
<split-pane v-on:resize="resize" split="vertical">
<template slot="paneL">
<div class="left-container"></div>
</template>
<template slot="paneR">
<split-pane split="horizontal">
<template slot="paneL">
<div class="top-container"></div>
</template>
<template slot="paneR">
<div class="bottom-container"></div>
</template>
</split-pane>
</template>
</split-pane>
</div>
</template>
<script>
import splitPane from 'vue-splitpane'
export default {
name: 'splitpane-demo',
components: { splitPane },
methods: {
resize() {
console.log('resize')
}
}
}
</script>
<style scoped>
.components-container {
position: relative;
height: 100vh;
}
.left-container {
background-color: #F38181;
height: 100%;
}
.right-container {
background-color: #FCE38A;
height: 200px;
}
.top-container {
background-color: #FCE38A;
width: 100%;
height: 100%;
}
.bottom-container {
width: 100%;
background-color: #95E1D3;
height: 100%;
}
</style>

View File

@ -1,130 +0,0 @@
<template>
<div>
<sticky className="sub-navbar">
<el-dropdown trigger="click">
<el-button plain>
Platform<i class="el-icon-caret-bottom el-icon--right"></i>
</el-button>
<el-dropdown-menu class="no-border" slot="dropdown">
<el-checkbox-group v-model="platforms" style="padding: 5px 15px;">
<el-checkbox v-for="item in platformsOptions" :label="item.key" :key="item.key">
{{item.name}}
</el-checkbox>
</el-checkbox-group>
</el-dropdown-menu>
</el-dropdown>
<el-dropdown trigger="click">
<el-button plain>
Link<i class="el-icon-caret-bottom el-icon--right"></i>
</el-button>
<el-dropdown-menu class="no-padding no-border" style="width:300px" slot="dropdown">
<el-input placeholder="Please enter the content" v-model="url">
<template slot="prepend">Url</template>
</el-input>
</el-dropdown-menu>
</el-dropdown>
<div class="time-container">
<el-date-picker v-model="time" type="datetime" :picker-options="pickerOptions" format="yyyy-MM-dd HH:mm:ss" placeholder="Release time">
</el-date-picker>
</div>
<el-button style="margin-left: 10px;" type="success">publish
</el-button>
</sticky>
<div class="components-container">
<code>Sticky header, {{$t('components.stickyTips')}}</code>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
</div>
</div>
</template>
<script>
import Sticky from '@/components/Sticky'
export default {
name: 'sticky-demo',
components: { Sticky },
data() {
return {
time: '',
url: '',
platforms: ['a-platform'],
platformsOptions: [
{ key: 'a-platform', name: 'platformA' },
{ key: 'b-platform', name: 'platformB' },
{ key: 'c-platform', name: 'platformC' }
],
pickerOptions: {
disabledDate(time) {
return time.getTime() > Date.now()
}
}
}
}
}
</script>
<style scoped>
.components-container div {
margin: 10px;
}
.time-container {
display: inline-block;
}
</style>

View File

@ -1,37 +0,0 @@
<template>
<div class="components-container">
<code>
{{$t('components.tinymceTips')}}
<a target="_blank" class="link-type" href="https://panjiachen.github.io/vue-element-admin-site/component/rich-editor.html"> {{$t('components.documentation')}}</a>
</code>
<div>
<tinymce :height="300" v-model="content"></tinymce>
</div>
<div class="editor-content" v-html="content"></div>
</div>
</template>
<script>
import Tinymce from '@/components/Tinymce'
export default {
name: 'tinymce-demo',
components: { Tinymce },
data() {
return {
content:
`<h1 style="text-align: center;">Welcome to the TinyMCE demo!</h1><p style="text-align: center; font-size: 15px;"><img title="TinyMCE Logo" src="//www.tinymce.com/images/glyph-tinymce@2x.png" alt="TinyMCE Logo" width="110" height="97" /><ul>
<li>Our <a href="//www.tinymce.com/docs/">documentation</a> is a great resource for learning how to configure TinyMCE.</li><li>Have a specific question? Visit the <a href="https://community.tinymce.com/forum/">Community Forum</a>.</li><li>We also offer enterprise grade support as part of <a href="https://tinymce.com/pricing">TinyMCE premium subscriptions</a>.</li>
</ul>`
}
}
}
</script>
<style scoped>
.editor-content{
margin-top: 20px;
}
</style>

View File

@ -0,0 +1,172 @@
<template>
<div id="chart" :class="className" :style="{height:height,width:width}"></div>
</template>
<script>
import echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme
import { debounce } from '@/utils'
export default {
props: {
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '350px'
},
autoResize: {
type: Boolean,
default: true
},
chartData: {
type: Object
},
showChart: {
type: Boolean
}
},
data() {
return {
chart: null,
rotate: 0,
screenWidth: document.body.clientWidth
}
},
mounted() {
window.screenWidth = document.body.clientWidth
if (window.screenWidth <= 400) {
this.rotate = 30
}
this.initChart()
if (this.autoResize) {
this.__resizeHanlder = debounce(() => {
if (this.chart) {
this.chart.resize()
}
}, 100)
window.addEventListener('resize', this.__resizeHanlder)
}
//
const sidebarElm = document.getElementsByClassName('sidebar-container')[0]
sidebarElm.addEventListener('transitionend', this.__resizeHanlder)
//
const that = this
window.onresize = () => {
return (() => {
window.screenWidth = document.body.clientWidth
that.screenWidth = window.screenWidth
console.log(window.screenWidth)
if (window.screenWidth <= 400) {
this.rotate = 30
}
})()
}
},
beforeDestroy() {
if (!this.chart) {
return
}
if (this.autoResize) {
window.removeEventListener('resize', this.__resizeHanlder)
}
const sidebarElm = document.getElementsByClassName('sidebar-container')[0]
sidebarElm.removeEventListener('transitionend', this.__resizeHanlder)
this.chart.dispose()
this.chart = null
},
watch: {
chartData: {
deep: true,
handler(val) {
this.setOptions(val)
}
},
showChart(val) {
if (val) {
this.chart.resize()
}
},
screenWidth(val) {
this.screenWidth = val
if (val <= 400) {
this.rotate = 30
this.setOptions(this.chartData)
} else {
this.rotate = 0
this.setOptions(this.chartData)
}
}
},
methods: {
setOptions({ historyData, xAxis, title } = {}) {
this.chart.setOption({
xAxis: {
// data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
data: xAxis,
boundaryGap: false,
axisLabel: {
interval: 0,
rotate: this.rotate
},
axisTick: {
show: false
}
},
grid: {
left: 10,
right: 10,
bottom: 20,
top: 30,
containLabel: true
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
padding: [5, 10]
},
yAxis: {
axisTick: {
show: false
}
},
legend: {
data: [title]
},
series: [{
name: title, itemStyle: {
normal: {
color: '#FF005A',
lineStyle: {
color: '#FF005A',
width: 2
}
}
},
smooth: true,
type: 'line',
data: historyData,
animationDuration: 2800,
animationEasing: 'cubicInOut'
}]
})
},
initChart() {
this.chart = echarts.init(this.$el, 'macarons')
// this.setOptions(this.chartData)
}
}
}
</script>

View File

@ -0,0 +1,189 @@
<template>
<div id="chart" :class="className" :style="{height:height,width:width}"></div>
</template>
<script>
import echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme
import { debounce } from '@/utils'
export default {
props: {
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '350px'
},
autoResize: {
type: Boolean,
default: true
},
HumitureData: {
type: Object
},
showHumiture: {
type: Boolean
}
},
data() {
return {
chart: null,
rotate: 0,
screenWidth: document.body.clientWidth
}
},
mounted() {
window.screenWidth = document.body.clientWidth
if (window.screenWidth <= 400) {
this.rotate = 30
}
this.initChart()
if (this.autoResize) {
this.__resizeHanlder = debounce(() => {
if (this.chart) {
this.chart.resize()
}
}, 100)
window.addEventListener('resize', this.__resizeHanlder)
}
//
const sidebarElm = document.getElementsByClassName('sidebar-container')[0]
sidebarElm.addEventListener('transitionend', this.__resizeHanlder)
//
const that = this
window.onresize = () => {
return (() => {
window.screenWidth = document.body.clientWidth
that.screenWidth = window.screenWidth
console.log(window.screenWidth)
if (window.screenWidth <= 400) {
this.rotate = 30
}
})()
}
},
beforeDestroy() {
if (!this.chart) {
return
}
if (this.autoResize) {
window.removeEventListener('resize', this.__resizeHanlder)
}
const sidebarElm = document.getElementsByClassName('sidebar-container')[0]
sidebarElm.removeEventListener('transitionend', this.__resizeHanlder)
this.chart.dispose()
this.chart = null
},
watch: {
HumitureData: {
deep: true,
handler(val) {
this.setOptions(val)
}
},
showHumiture(val) {
if (val) {
this.chart.resize()
}
},
screenWidth(val) {
this.screenWidth = val
if (val <= 400) {
this.rotate = 30
this.setOptions(this.HumitureData)
} else {
this.rotate = 0
this.setOptions(this.HumitureData)
}
}
},
methods: {
setOptions({ historyData, xAxis, title } = {}) {
this.chart.setOption({
xAxis: {
// data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
data: xAxis,
boundaryGap: false,
axisLabel: {
interval: 0,
rotate: this.rotate
},
axisTick: {
show: false
}
},
grid: {
left: 10,
right: 10,
bottom: 20,
top: 30,
containLabel: true
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
padding: [5, 10]
},
yAxis: {
axisTick: {
show: false
}
},
legend: {
data: title
},
series: [{
name: title[0], itemStyle: {
normal: {
color: '#FF005A',
lineStyle: {
color: '#FF005A',
width: 2
}
}
},
smooth: true,
type: 'line',
data: historyData.temperature,
animationDuration: 2800,
animationEasing: 'cubicInOut'
},
{
name: title[1], itemStyle: {
normal: {
color: '#3888fa',
lineStyle: {
color: '#3888fa',
width: 2
}
}
},
smooth: true,
type: 'line',
data: historyData.humidity,
animationDuration: 2800,
animationEasing: 'cubicInOut'
}]
})
},
initChart() {
this.chart = echarts.init(this.$el, 'macarons')
console.log(this.HumitureData)
// this.setOptions(this.HumitureData)
}
}
}
</script>

View File

@ -0,0 +1,296 @@
<template>
<div class="app-container">
<div class="base-wrapper">
<div class="device-base">
<p class="item"><span class="keyword">{{$t('counter.device')}}: </span><el-tag>{{deviceID}}</el-tag></p>
<p class="item" v-if="lastItem.device_name"><span class="keyword">{{$t('counter.deviceName')}}: </span><el-tag>{{lastItem.device_name}}</el-tag></p>
<p class="item" v-else><span class="keyword">{{$t('counter.deviceName')}}: </span><el-tag>{{$t('counter.noName')}}</el-tag></p>
</div>
</div>
<div class="screen-wrapper">
<div class="device-screen">
<table cellspacing="0">
<tbody>
<tr>
<td v-for="(item, index) of lastTime" :key="index">
{{item}}
</td>
</tr>
<tr>
<td v-for="(item, index) of lastCount" :key="index">
{{item}}
</td>
</tr>
</tbody>
</table>
</div>
<div class="device-status">
<ul>
<li>Status:
<span
:class="lastItem.status ? 'text-success' : 'text-danger'"
v-if="lastItem.status == 0"
>
Offline
</span>
<span
:class="lastItem.status ? 'text-success' : 'text-danger'"
v-if="lastItem.status == 1"
>
Online
</span>
</li>
<li class="signal">Signal: <span>{{lastItem.signal}}/31</span></li>
<li>Power: <span>{{lastItem.energy.replace('%','')}}%</span></li>
</ul>
</div>
<div class="device-status"
v-if="lastItem.chip_type === 'AIR-V2'"
>
<ul>
<li>
<p>LED开关
<el-switch
v-model="led"
active-color="#13ce66"
inactive-color="#ff4949"
@change="handleLedSwitchChange"
>
</el-switch>
</p>
</li>
<li>
<el-button type="primary" icon="el-icon-refresh" size="mini" @click="handleCountClear" :loading="clearCountLoading">计数清零</el-button>
</li>
<!-- <li>
<el-button type="primary" icon="el-icon-delete" size="mini" @click="handleMosqClean">自动清扫</el-button>
</li> -->
</ul>
</div>
<!-- 计数器清零确认弹窗 -->
<el-dialog
title="确认"
:visible.sync="dialogCountVisible"
:width="dialogWidth"
center
>
<span>确定要清零计数器吗</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogCountVisible = false">取消</el-button>
<el-button type="primary" @click="handleCountClear">确定</el-button>
</span>
</el-dialog>
<!-- 清理速度选择确认弹窗 -->
<el-dialog
title="请选择清理速度,并确定!"
:visible.sync="dialogMosqVisible"
:width="dialogWidth"
center
>
<div class="block">
<el-row>
<el-col :span="12"><div class="grid-content bg-purple">
<span style="display: flex; justify-content: flex-start;">🐢</span>
</div></el-col>
<el-col :span="12"><div class="grid-content bg-purple">
<span style="display: flex; justify-content: flex-end;">🐰</span>
</div></el-col>
</el-row>
<el-slider
v-model="cleanSpeed"
:step="1"
:min="1"
:max="9"
show-stops>
</el-slider>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogMosqVisible = false">取消</el-button>
<el-button type="primary" @click="handleMosqClean">确定</el-button>
</span>
</el-dialog>
</div>
</div>
</template>
<script>
import moment from 'moment'
import { fetchRemoteControl } from '@/api/counter'
export default {
name: 'screen',
props: {
deviceID: String,
lastItem: Object
},
data() {
return {
led: undefined,
dialogCountVisible: false,
dialogMosqVisible: false,
clearCountLoading: false,
cleanSpeed: 6
}
},
methods: {
sleep(time) {
return new Promise(resolve => setTimeout(resolve, time))
},
async handleLedSwitchChange() {
const action = this.led ? 'ledOn' : 'ledOff'
await this.sendRemoteControlCommand(action)
},
async handleCountClear() {
if (!this.dialogCountVisible) {
this.showCountConfirmationDialog()
} else {
await this.sendRemoteControlCommand('countClear')
this.clearCountLoading = true
this.sleep(7000).then(() => {
this.clearCountLoading = false
this.$emit('countClear')
})
}
},
async handleMosqClean() {
if (!this.dialogMosqVisible) {
this.showMosqConfirmationDialog()
} else {
await this.sendRemoteControlCommand('mosqClean', { speed: this.cleanSpeed })
}
},
async sendRemoteControlCommand(command, options = {}) {
try {
const { speed } = options
const deviceID = this.deviceID
console.log(deviceID, command, speed)
const requestData = { command, speed }
const response = await fetchRemoteControl(deviceID, requestData)
console.log('Command sent successfully:', response.data)
} catch (error) {
console.error('Error sending command:', error)
} finally {
this.dialogCountVisible = false
this.dialogMosqVisible = false
}
},
showCountConfirmationDialog() {
this.dialogCountVisible = true
},
showMosqConfirmationDialog() {
this.dialogMosqVisible = true
}
},
computed: {
lastTime() {
const curTime = moment().format('YYYY-MM-DD HH:mm')
return curTime.split('')
// return this.lastItem.calc_time.substr(0, 16).split('')
},
lastCount() {
const count = this.lastItem.count
const qty = 'Qty.' + ' '.repeat(10 - count.length) + '00' + count
return qty.split('')
},
dialogWidth() {
//
const windowWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth
// 80030%100%
return windowWidth > 600 ? '30%' : '100%'
}
},
mounted() {
this.led = this.lastItem.led_status !== 'OFF'
}
}
</script>
<style lang="scss">
.text-success {
color: #67C23A
}
.text-danger {
color: #F56C6C
}
.base-wrapper {
overflow: auto;
.device-base {
display: flex;
flex-direction: column;
align-items: center;
min-width: 350px;
.item {
width: 300px;
margin: 0 0 5px 0;
}
.keyword {
display: inline-block;
width: 100px;
font-size: 0.9em;
}
}
}
.screen-wrapper {
background: #F2F6FC;
.device-screen {
display: flex;
justify-content: center;
table {
font-size: 1.2rem;
font-family: 'Courier New', Courier, monospace;
border: 1px solid #666;
border-collapse: collapse;
text-align: center;
margin: 2rem 0 2rem 0;
td {
border: 1px solid #666;
width: 1rem;
height: 1.5rem;
line-height: 1.5rem;
font-weight: 600;
padding: .2rem;
}
}
}
.device-status {
display: flex;
justify-content: center;
margin: -2rem 0 1rem 0;
ul {
padding: 0;
li {
font-size: .85rem;
list-style-type: none;
display: inline-block;
}
.signal {
margin: 0 2rem 0 2rem
}
}
}
@media only screen and (max-width: 768px) {
.device-screen {
table {
margin: 1rem 0 1rem 0;
td {
font-size: 1rem;
}
}
}
.device-status {
margin: -1rem 0 1.5rem 0;
font-size: 1rem;
}
.signal {
margin: 0 1rem 0 1rem
}
}
}
</style>

View File

@ -0,0 +1,392 @@
<template>
<div class="app-container">
<el-tabs v-model="activeName" @tab-click="handleTabClick">
<el-tab-pane :label="$t('counter.screen')" name="screen">
<transition>
<screen
:deviceID="this.$store.getters.deviceID"
:lastItem="lastItem"
@countClear="countClear"
v-if="flag"
>
</screen>
</transition>
</el-tab-pane>
<el-tab-pane :label="$t('counter.trendChart')" name="chart">
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
<chart
:chart-data="lineChartData.total"
:showChart="showChart"
>
</chart>
</el-row>
</el-tab-pane>
<!-- <el-tab-pane :label="$t('counter.humitureChart')" name="humiture">
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
<humiture
:humiture-data="HumitureData.total"
:showHumiture="showHumiture"
>
</humiture>
</el-row>
</el-tab-pane> -->
</el-tabs>
<div class="filter-container">
<div class="date-selector filter-item">
<el-date-picker
v-model="dateRange"
size="small"
type="daterange"
align="right"
:range-separator="$t('counter.to')"
:start-placeholder="$t('counter.start_date')"
:end-placeholder="$t('counter.end_date')"
:picker-options="pickerOptions"
value-format="yyyy-MM-dd"
@change="handleDateSelect"
/>
</div>
<el-button class="filter-item" size="small" type="primary" v-waves icon="el-icon-search" @click="handleFilter">{{$t('table.search')}}</el-button>
</div>
<el-table
v-show="!showHumiture"
v-loading="listLoading"
:data="deviceLogs"
style="width: 100%">
<el-table-column
type="index"
:label="$t('counter.sn')"
width="50">
</el-table-column>
<el-table-column
prop="device_id"
:label="$t('counter.device')"
min-width="150">
</el-table-column>
<el-table-column
prop="total"
:label="$t('counter.count')"
min-width="80">
</el-table-column>
<el-table-column
prop="date"
:label="$t('counter.date')"
min-width="100">
</el-table-column>
</el-table>
<div v-show="!showHumiture" class="pagination-container">
<el-pagination background
:current-page="1"
:page-sizes="[10,20,30,50]"
:page-size="deviceHistoryListQuery.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="logsTotal" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
</div>
<!-- humiture table -->
<el-table
v-show="showHumiture"
v-loading="tempLoading"
:data="deviceTempTableLogs"
style="width: 100%">
<el-table-column
prop="create_time"
:label="$t('counter.date')"
min-width="100">
</el-table-column>
<el-table-column
prop="temperature"
:label="$t('counter.temperature')"
min-width="80">
</el-table-column>
<el-table-column
prop="humidity"
:label="$t('counter.humidity')"
min-width="80">
</el-table-column>
</el-table>
<!-- humiture paging -->
<div v-show="showHumiture" class="pagination-container">
<el-pagination background
:current-page="1"
:page-sizes="[10,20,30,50]"
:page-size="deviceTempListQuery.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="tempTotal" @size-change="handleTempSizeChange" @current-change="handleTempCurrentChange" />
</div>
</div>
</template>
<script>
import waves from '@/directive/waves' //
import { fetchDeviceList, fetchDeviceLogsHistory, fetchDeviceTempLog } from '@/api/counter'
import Screen from './components/screen'
import Chart from './components/chart'
import Humiture from './components/humiture'
export default {
name: 'deviceDetail',
components: {
Screen,
Chart,
Humiture
},
directives: {
waves
},
data() {
return {
lineChartData: {
total: {
historyData: [],
xAxis: [],
title: 'Trend'
}
},
HumitureData: {
total: {
historyData: {
temperature: [],
humidity: []
},
xAxis: [],
title: ['temperature', 'humidity']
}
},
deviceTempListQuery: {
device_id: undefined,
page: 1,
limit: 20,
start: undefined,
end: undefined,
ordering: '-create_time'
},
deviceHistoryListQuery: {
page: 1,
limit: 20,
device_id: undefined,
start: undefined,
end: undefined
},
listLoading: true,
tempLoading: true,
device_id: undefined,
deviceLogs: [],
deviceTempLogs: [],
deviceTempTableLogs: [],
activeName: 'screen',
logsTotal: 0,
tempTotal: 0,
lastItem: {},
showScreen: true,
showChart: false,
showHumiture: false,
flag: false,
pickerOptions: null,
dateRange: undefined
}
},
watch: {
activeName(val) {
if (val === 'chart') {
this.showChart = true
}
if (val === 'humiture') {
this.showHumiture = true
}
}
},
mounted() {
this.timer = setInterval(() => {
this.getDevices({ device_id: this.device_id })
}, 30 * 1000)
},
methods: {
getDeviceLogsHistory(params) {
fetchDeviceLogsHistory(params).then(response => {
const dateList = []
this.deviceLogs = response.data.results
this.deviceLogs.forEach((item, index) => {
this.lineChartData.total.historyData.push(item.total)
dateList.push(item.date.substr(5))
})
this.lineChartData.total.historyData = this.lineChartData.total.historyData.reverse()
this.lineChartData.total.xAxis = dateList.reverse()
this.logsTotal = response.data.count
this.listLoading = false
})
},
countClear() {
this.getDevices({ device_id: this.device_id })
},
// getDeviceLogsTableHistory(params) {
// fetchDeviceLogsHistory(params).then(response => {
// this.deviceLogs = response.data.results
// this.logsTotal = response.data.count
// this.listLoading = false
// })
// },
getDeviceTempLog(params) {
fetchDeviceTempLog(params).then(response => {
const dateList = []
this.deviceTempLogs = response.data.results
this.deviceTempLogs.forEach((item, index) => {
if (index % 2 === 0) {
this.HumitureData.total.historyData.temperature.push(item.temperature)
this.HumitureData.total.historyData.humidity.push(item.humidity)
dateList.push(item.last_time.substr(11, 5))
}
})
this.HumitureData.total.xAxis = dateList
this.tempTotal = response.data.count
this.tempLoading = false
})
},
getDeviceTempTableLog(params) {
fetchDeviceTempLog(params).then(response => {
this.deviceTempTableLogs = response.data.results
this.tempTotal = response.data.count
this.tempLoading = false
})
},
getDevices(params) {
let device_id = params.device_id
fetchDeviceList(params).then(response => {
this.deviceList = response.data.results
this.lastItem = this.deviceList[0]
if (!device_id) {
device_id = this.lastItem.device_id
this.$store.dispatch('changeDeviceID', device_id)
console.log(device_id)
}
this.getDeviceLogsHistory({ device_id, limit: 20 })
if (typeof (this.lastItem.count) === 'number') {
this.lastItem.count = this.lastItem.count.toString()
}
this.flag = true
})
},
coordinate(row, column) {
return row.longitude + ', ' + row.latitude
},
handleDateSelect(value) {
if (value === null) {
this.deviceHistoryListQuery.start = undefined
this.deviceHistoryListQuery.end = undefined
} else {
const [start, end] = value
this.deviceHistoryListQuery.start = start
this.deviceHistoryListQuery.end = end
this.deviceTempListQuery.start = start
this.deviceTempListQuery.end = end
}
},
handleFilter() {
this.deviceHistoryListQuery.page = 1
this.deviceTempListQuery.page = 1
this.getDeviceLogsHistory(this.deviceHistoryListQuery)
this.getDeviceTempTableLog(this.deviceTempListQuery)
},
handleCurrentChange(page) {
this.listLoading = true
this.deviceHistoryListQuery.device_id = this.device_id
this.deviceHistoryListQuery.page = page
// this.getDeviceLogsTableHistory(this.deviceHistoryListQuery)
this.getDeviceLogsHistory(this.deviceHistoryListQuery)
},
handleSizeChange(val) {
this.listLoading = true
this.deviceHistoryListQuery.device_id = this.device_id
this.deviceHistoryListQuery.limit = val
// this.getDeviceLogsTableHistory(this.deviceHistoryListQuery)
this.getDeviceLogsHistory(this.deviceHistoryListQuery)
},
handleTempCurrentChange(page) {
this.tempLoading = true
this.deviceTempListQuery.page = page
this.deviceTempListQuery.device_id = this.device_id
this.getDeviceTempLog(this.deviceTempListQuery)
},
handleTempSizeChange(val) {
this.tempLoading = true
this.deviceTempListQuery.limit = val
this.deviceTempListQuery.device_id = device_id
const device_id = this.$store.getters.deviceID
this.getDeviceTempLog(this.deviceTempListQuery)
},
handleTabClick(tab, event) {
// console.log(tab, event)
// siderbardisactiveTabresize
if (tab.name === 'chart') {
this.showHumiture = false
}
if (tab.name === 'humiture') {
this.showChart = false
}
if (tab.name === 'screen') {
this.showHumiture = false
}
}
},
created() {
this.device_id = this.$store.getters.deviceID
this.deviceHistoryListQuery.device_id = this.device_id
this.deviceTempListQuery.device_id = this.device_id
this.getDevices({ device_id: this.device_id })
// this.getDeviceLogsTableHistory({ device_id: this.device_id, limit: 20 })
this.getDeviceTempLog({ device_id: this.device_id, last_day: 1, limit: 30 })
this.getDeviceTempTableLog(this.deviceTempListQuery)
}
}
</script>
<style lang="scss" scoped>
.date-selector {
margin-left: 10px;
}
.date-selector /deep/ .el-date-editor .el-range-separator {
margin-right: 10px !important;
}
@media only screen and (max-width: 768px) {
.filter-container {
display: block;
.filter-item {
display: block;
float: left;
margin: 0 0 15px 10px;
}
.date-selector {
margin-left: 0;
margin-bottom: 0;
}
.time-selector {
margin-left: 0;
}
}
}
</style>
<style lang="scss">
@media only screen and (max-width: 500px) {
.el-date-range-picker {
width: 100% !important;
}
.el-date-range-picker__content {
float: none;
width: 80%;
}
}
</style>
<style lang="scss">
.v-enter, .v-leave-to {
opacity: 0;
}
.v-enter-active, .v-leave-active {
transition: opacity 1s
}
</style>

View File

@ -1,43 +1,133 @@
<template>
<div class="app-container">
<p class="warn-content">
无线智能设备信息表
</p>
<el-form :inline="true" :model="DeviceSearchForm" @submit.native.prevent>
<el-form-item
prop="device_id"
>
<el-input
size="mini"
type="text"
v-model="DeviceSearchForm.device_id"
style="width: 10rem"
auto-complete="off"
@keyup.enter.native="onSubmit"
:placeholder="$t('counter.inputDeviceID')"
></el-input>
</el-form-item>
<el-form-item>
<el-select size="mini"
style="width: 5.5rem"
v-model="DeviceSearchForm.status"
:placeholder="$t('counter.inputStatus')"
>
<el-option :label="$t('counter.all')" value=""></el-option>
<el-option :label="$t('counter.online')" value="1"></el-option>
<el-option :label="$t('counter.offline')" value="0"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" size="mini" @click="onSubmit">{{$t('counter.search')}}</el-button>
<el-button size="mini" @click="resetSearch">{{$t('counter.reset')}}</el-button>
</el-form-item>
</el-form>
<!-- table -->
<el-table
v-loading="listLoading"
:data="deviceList"
style="width: 100%">
<el-table-column
fixed="left"
type="index"
:label="$t('counter.sn')">
</el-table-column>
<el-table-column
fixed="left"
prop="device_id"
label="设备ID"
min-width="180">
:label="$t('counter.device')"
min-width="120">
<template slot-scope="scope">
<span>{{ scope.row.device_id }} <el-tag v-if="scope.row.chip_type === 'AIR-V2'" type="success" size="mini">V2</el-tag></span>
</template>
</el-table-column>
<el-table-column
prop="device_name"
label="设备名称"
:label="$t('counter.deviceName')"
min-width="150">
</el-table-column>
<el-table-column
prop="status"
:label="$t('counter.status')"
min-width="80">
<template slot-scope="scope">
<span v-if="scope.row.status==0" style="color: #F56C6C" ><i class="el-icon-error"></i> {{$t('counter.offline')}}</span>
<span v-if="scope.row.status==1" style="color: #67C23A" ><i class="el-icon-success"></i> {{$t('counter.online')}}</span>
</template>
</el-table-column>
<el-table-column
prop="count"
:label="$t('counter.count')"
min-width="80">
<template slot-scope="scope">
<span ><i class="el-icon-alimosquito"></i> {{scope.row.count}}</span>
</template>
</el-table-column>
<el-table-column
prop="signal"
:label="$t('counter.signal')"
min-width="80">
<template slot-scope="scope">
<span v-if="scope.row.signal>=24" style="color: #67C23A" ><i class="el-icon-alisignal-4"></i></span>
<span v-if="scope.row.signal>=16 && scope.row.signal<24" style="color: #67C23A" ><i class="el-icon-alisignal-3"></i></span>
<span v-if="scope.row.signal>=8 && scope.row.signal<16" style="color: #FF9B21" ><i class="el-icon-alisignal-2"></i></span>
<span v-if="scope.row.signal>=0 && scope.row.signal<8" style="color: #F56C6C" ><i class="el-icon-alisignal-1"></i></span>
</template>
</el-table-column>
<el-table-column
prop="energy"
:label="$t('counter.energy')"
min-width="100">
<template slot-scope="scope">
<span v-if="scope.row.energy.replace('%','') >= 90" style="color: #67C23A" ><i class="el-icon-alipower_9"></i> {{scope.row.energy.replace('%','')}}%</span>
<span v-if="scope.row.energy.replace('%','') >= 80 && scope.row.energy.replace('%','') < 90" style="color: #67C23A" ><i class="el-icon-alipower_8" size="small"></i> {{scope.row.energy.replace('%','')}}%</span>
<span v-if="scope.row.energy.replace('%','') >= 70 && scope.row.energy.replace('%','') < 80" style="color: #67C23A" ><i class="el-icon-alipower_7"></i> {{scope.row.energy.replace('%','')}}%</span>
<span v-if="scope.row.energy.replace('%','') >= 60 && scope.row.energy.replace('%','') < 70" style="color: #67C23A" ><i class="el-icon-alipower_6"></i> {{scope.row.energy.replace('%','')}}%</span>
<span v-if="scope.row.energy.replace('%','') >= 50 && scope.row.energy.replace('%','') < 60" style="color: #67C23A" ><i class="el-icon-alipower_5"></i> {{scope.row.energy.replace('%','')}}%</span>
<span v-if="scope.row.energy.replace('%','') >= 40 && scope.row.energy.replace('%','') < 50" style="color: #FF9B21" ><i class="el-icon-alipower_4"></i> {{scope.row.energy.replace('%','')}}%</span>
<span v-if="scope.row.energy.replace('%','') >= 30 && scope.row.energy.replace('%','') < 40" style="color: #FF9B21" ><i class="el-icon-alipower_3" ></i> {{scope.row.energy.replace('%','')}}%</span>
<span v-if="scope.row.energy.replace('%','') >= 20 && scope.row.energy.replace('%','') < 30" style="color: #FF9B21" ><i class="el-icon-alipower_2"></i> {{scope.row.energy.replace('%','')}}%</span>
<span v-if="scope.row.energy.replace('%','') >= 10 && scope.row.energy.replace('%','') < 20" style="color: #F56C6C" ><i class="el-icon-alipower_1"></i> {{scope.row.energy.replace('%','')}}%</span>
<span v-if="scope.row.energy.replace('%','') >= 0 && scope.row.energy.replace('%','') < 10" style="color: #F56C6C" ><i class="el-icon-alipower_"></i> &lt;{{'10.0%'}}</span>
</template>
</el-table-column>
<el-table-column
prop="time"
:label="$t('counter.time')"
min-width="100">
</el-table-column>
<el-table-column
prop="chip_type"
label="芯片类型"
min-width="100">
</el-table-column>
<el-table-column
prop="chip_id"
label="芯片ID"
min-width="180">
</el-table-column>
<el-table-column
prop="last_connect"
label="上次连接时间"
min-width="180">
</el-table-column>
<el-table-column
prop="last_offline_time"
label="上次离线时间"
min-width="180">
fixed="right"
:label="$t('counter.action')"
min-width="85">
<template slot-scope="scope">
<el-button type="text" title="Detail"
@click="handleDetailClick(scope.row.device_id)" ><i class="el-icon-alixiangqing"></i>
</el-button>
<el-button type="text" title="Map"
@click="handleMapClick(scope.row.device_id)" ><i class="el-icon-alimap"></i>
</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
class="pagination"
background
layout="total, prev, pager, next, jumper"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
:total="total">
</el-pagination>
</div>
</template>
@ -48,23 +138,71 @@ export default {
data() {
return {
deviceList: [],
listLoading: true
listLoading: true,
DeviceSearchForm: {
device_id: null,
status: null
},
total: 0
}
},
methods: {
getDevices() {
fetchDeviceList().then(response => {
getDevices(params) {
fetchDeviceList(params).then(response => {
this.deviceList = response.data.results
this.total = response.data.count
this.listLoading = false
})
},
onSubmit() {
const device_id = this.DeviceSearchForm.device_id
const status = this.DeviceSearchForm.status
this.getDevices({ device_id, status })
},
resetSearch() {
this.DeviceSearchForm.device_id = ''
this.DeviceSearchForm.status = ''
this.getDevices()
},
handleCurrentChange(page) {
this.listLoading = true
this.getDevices({ page })
},
handleSizeChange(page) {
this.listLoading = true
this.getDevices({ page })
},
handleDetailClick(deviceID) {
// console.log(deviceID)
this.$store.dispatch('changeDeviceID', deviceID).then(() => {
this.$router.push('/counter/detail')
}).catch(() => {
console.log('Err: get device_id failed in device page')
})
},
handleMapClick(deviceID) {
// console.log(deviceID)
this.$store.dispatch('changeMapClick', true).then(() => {
console.log('go to map')
}).catch(() => {
console.log('Err: click map failed')
})
this.$store.dispatch('changeDeviceID', deviceID).then(() => {
this.$router.push({ path: '/counter/map', query: { device_id: deviceID }})
}).catch(() => {
console.log('Err: get device_id failed in device page')
})
}
},
created() {
this.getDevices()
},
deactivated() {
this.$destroy(true)
}
}
</script>
<style lang="scss">
</style>

View File

@ -1,7 +1,7 @@
<template>
<div class="app-container">
<p class="warn-content">
灭蚊侠提供健康环境你值得拥有
这里是首页
</p>
</div>
</template>

252
src/views/counter/logs.vue Normal file
View File

@ -0,0 +1,252 @@
<template>
<div class="app-container">
<div class="filter-container">
<el-input
@keyup.enter.native="handleFilter"
@keyup.esc.native="handleEsc"
size="small" style="width: 220px;"
class="filter-item"
:placeholder="$t('counter.logSeachContent')" v-model="logsListQuery.device">
</el-input>
<div class="date-selector filter-item">
<el-date-picker
v-model="dateRange"
size="small"
type="daterange"
align="right"
:range-separator="$t('counter.to')"
:start-placeholder="$t('counter.start_date')"
:end-placeholder="$t('counter.end_date')"
:picker-options="pickerOptions"
value-format="yyyy-MM-dd"
@change="handleDateSelect"
/>
</div>
<el-button class="filter-item" size="small" type="primary" v-waves icon="el-icon-search" @click="handleFilter">{{$t('table.search')}}</el-button>
<el-button :disabled="downloadDisabled" class="filter-item export" :loading="downloadLoading" size="small"
type="primary" icon="el-icon-document" @click="handleDownload">{{ $t('table.export') }}</el-button>
</div>
<el-table
v-loading="listLoading"
:data="logList"
style="width: 100%"
:default-sort = "{prop: 'calc_time', order: 'descending'}"
>
<el-table-column
type="index"
:label="$t('counter.sn')">
</el-table-column>
<el-table-column
prop="device_id"
:label="$t('counter.device')"
sortable
min-width="150">
</el-table-column>
<el-table-column
prop="device_name"
:label="$t('counter.deviceName')"
sortable
min-width="150">
</el-table-column>
<el-table-column
prop="signal"
:label="$t('counter.signal')"
min-width="80">
</el-table-column>
<el-table-column
sortable
prop="mosq_count"
:label="$t('counter.count')"
min-width="100">
</el-table-column>
<el-table-column
prop="energy"
:label="$t('counter.energy')"
min-width="100">
</el-table-column>
<el-table-column
prop="coordinate"
:label="$t('counter.coordinate')"
min-width="280px"
:formatter="coordinate">
</el-table-column>
<el-table-column
prop="calc_time"
:label="$t('counter.time')"
min-width="150">
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination background
:current-page="1"
:page-sizes="[10,20,30,50]"
:page-size="logsListQuery.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="total" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
</div>
</div>
</template>
<script>
import { fetchDeviceLogs } from '@/api/counter'
import waves from '@/directive/waves' //
import { parseTime } from '@/utils'
export default {
name: 'count',
directives: {
waves
},
data() {
return {
logList: [],
logExportList: [],
listLoading: true,
total: 0,
logsListQuery: {
device: undefined,
limit: 10,
page: 1,
start: undefined,
end: undefined
},
pickerOptions: null,
dateRange: undefined,
downloadLoading: false,
downloadDisabled: false,
filename: undefined
}
},
methods: {
async getDeviceLogs(params, type = 'table') {
await fetchDeviceLogs(params).then(response => {
if (type === 'table') {
this.logList = response.data.results
}
if (type === 'export') {
this.logExportList = response.data.results
}
this.total = response.data.count
this.listLoading = false
})
},
coordinate(row, column) {
return row.longitude + ', ' + row.latitude
},
handleCurrentChange(page) {
// console.log(page)
this.listLoading = true
this.logsListQuery.page = page
this.getDeviceLogs(this.logsListQuery)
},
handleSizeChange(val) {
this.logsListQuery.limit = val
this.getDeviceLogs(this.logsListQuery)
},
handleFilter() {
this.logsListQuery.page = 1
this.getDeviceLogs(this.logsListQuery)
},
handleEsc() {
this.logsListQuery.page = 1
this.logsListQuery.device = undefined
this.getDeviceLogs(this.logsListQuery)
},
handleDateSelect(value) {
if (value === null) {
this.logsListQuery.start = undefined
this.logsListQuery.end = undefined
} else {
const [start, end] = value
this.logsListQuery.start = start
this.logsListQuery.end = end
}
// this.getDeviceLogs(this.logsListQuery)
},
async handleDownload() {
const start = this.logsListQuery.start
const end = this.logsListQuery.end
if (!start || !end) {
this.$message({
message: 'Please select the start/end date',
type: 'warning'
})
return
}
this.downloadLoading = true
const exportQuery = Object.assign({}, this.logsListQuery)
exportQuery.limit = 5000
await this.getDeviceLogs(exportQuery, 'export')
this.filename = 'Device Log List ' + String(start).replace(/-/g, '') + '_' + String(end).replace(/-/g, '') + '.xlsx'
import('@/vendor/Export2Excel').then(excel => {
const tHeader = ['Id', 'Time', 'Device ID', 'Device Name', 'Signal', 'Count', 'Energy', 'Coordinate']
const filterVal = ['id', 'calc_time', 'device_id', 'device_name', 'signal', 'mosq_count', 'energy', 'coordinate']
const list = this.logExportList
const data = this.formatJson(filterVal, list)
excel.export_json_to_excel({
header: tHeader,
data,
filename: this.filename,
autoWidth: this.autoWidth,
bookType: this.bookType
})
this.downloadLoading = false
this.logsListQuery.limit = 10
})
},
formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => {
if (j === 'timestamp') {
return parseTime(v[j])
} else {
return v[j]
}
}))
}
},
created() {
this.getDeviceLogs(this.logsListQuery)
},
deactivated() {
this.$destroy(true)
}
}
</script>
<style lang="scss" scoped>
.date-selector {
margin-left: 10px;
}
.date-selector /deep/ .el-date-editor .el-range-separator {
margin-right: 10px !important;
}
@media only screen and (max-width: 768px) {
.filter-container {
display: block;
.filter-item {
display: block;
float: left;
margin: 0 0 15px 10px;
}
.date-selector {
margin-left: 0;
margin-bottom: 0;
}
.time-selector {
margin-left: 0;
}
}
}
</style>
<style lang="scss">
@media only screen and (max-width: 500px) {
.el-date-range-picker {
width: 100% !important;
}
.el-date-range-picker__content {
float: none;
width: 80%;
}
}
</style>

156
src/views/counter/map.vue Normal file
View File

@ -0,0 +1,156 @@
<template>
<div class="app-container">
<div class="amap-wrapper">
<el-amap v-if="flag" :zoom="zoom" :center="center" :plugin="plugin" class="amap-box" :vid="'amap-vue'">
<el-amap-marker
v-for="(marker, index) in markers"
:key="index"
:position="marker.position"
:events="marker.events"
:visible="marker.visible" :draggable="marker.draggable" :vid="index"
>
</el-amap-marker>
</el-amap>
</div>
</div>
</template>
<script>
import { fetchDeviceList } from '@/api/counter'
const defaultEvents = {
click: () => {
alert('click marker')
},
dragend: (e) => {
console.log('---event---: dragend')
this.markers[0].position = [e.lnglat.lng, e.lnglat.lat]
}
}
export default {
name: 'amap',
data() {
const self = this
return {
flag: false,
defaultPositions: [
{
name: '海洋公园',
position: [114.186739, 22.250872]
},
{
name: '香港大学',
position: [114.143472, 22.284105]
},
{
name: '南丫北容村',
position: [114.126261, 22.22863]
},
{
name: '大帽山',
position: [114.124105, 22.401088]
},
{
name: '恒生管理学院',
position: [114.223565, 22.380771]
},
{
name: '盐田',
position: [114.223565, 22.380771]
},
{
name: '清水',
position: [114.312821, 22.301076]
}
],
zoom: 16,
center: [],
markers: [],
plugin: ['ToolBar', {
pName: 'Geolocation',
events: {
init(o) {
// o
o.getCurrentPosition((status, result) => {
if (result && result.position) {
const lng = result.position.lng
const lat = result.position.lat
self.center = [lng, lat]
// self.loaded = true
self.$nextTick()
}
})
}
}
},
{
pName: 'Driving',
policy: 'AMap.DrivingPolicy.LEAST_TIME',
events: {
init(o) {
o.search(self.center, [113.276316, 23.112071], (status, result) => {
console.log(status, result)
})
}
}
}]
}
},
// beforeRouteEnter(to, from, next) {
// next(vm => {
// vm.url = from.path
// console.log(from.path)
// })
// },
methods: {
getDevices(params) {
fetchDeviceList(params).then(response => {
this.deviceList = response.data.results
// console.log(this.deviceList)
this.coordinate = this.deviceList[0].coordinate
if (this.coordinate === null) {
this.coordinate = [113.203460828994, 22.64902452257]
}
// console.log(this.coordinate)
const marker = []
marker.position = this.coordinate
marker.visible = true
marker.dragend = false
marker.events = defaultEvents
this.markers.push(marker)
// this.center = this.coordinate
this.flag = true
})
}
},
created() {
const mapClick = this.$store.getters.mapClick
if (mapClick) {
const device_id = this.$store.getters.deviceID
console.log(device_id)
this.getDevices({ device_id })
} else {
this.defaultPositions.forEach((item, index) => {
const entry = {}
entry.position = item.position
entry.events = defaultEvents
entry.visible = true
entry.draggable = false
this.markers.push(entry)
})
this.zoom = 11
this.center = [114.186739, 22.250872]
this.flag = true
}
}
}
</script>
<style lang="scss">
.amap-wrapper {
width: 100%;
height: 80%;
overflow: hidden;
position: absolute;
}
</style>

399
src/views/counter/map2.vue Normal file
View File

@ -0,0 +1,399 @@
<template>
<div class="map-wrapper">
<div id="map-container" tabindex="0"></div>
<div v-show="flag" id="geo-tip"></div>
<div v-show="flag" id="panel"></div>
<div v-show="mapClick && flag" id='bt-wrapper'>
<div id='bt'>点击去高德地图</div>
</div>
</div>
</template>
<script>
import AMap from 'AMap'
import moment from 'moment'
import { fetchDeviceList } from '@/api/counter'
export default {
name: 'map2',
data() {
return {
geo_map: null,
map: null,
flag: false,
mapClick: false,
geo: [],
deviceList: [],
deviceListQuery: {
page: 1,
limit: 100
}
}
},
methods: {
sleep(time) {
for (var temp = Date.now(); Date.now() - temp <= time;);
},
async getDevices(params) {
await fetchDeviceList(params).then(response => {
this.deviceList = response.data.results
})
},
gotoDriving() {
this.$confirm('此操作将跳转到路线规划, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.map.clearMap()
this.handleDrivingClick()
this.flag = true
this.$message({
type: 'success',
message: '跳转成功!'
})
}).catch(() => {
document.getElementById('map-container').removeEventListener
this.$message({
type: 'info',
message: '已取消跳转'
})
})
},
async initMap() {
this.map = new AMap.Map('map-container', {
center: [114.143472, 22.284105],
resizeEnable: true,
zoom: 10
})
//
await this.getDevices(this.deviceListQuery)
const markers = []
this.deviceList.forEach((item, index) => {
console.log(item)
const marker = new AMap.Marker({
position: item.coordinate,
zIndex: 10,
title: item.device_name,
map: this.map
})
const infoWindow = this.instantiateInforWindow(item)
AMap.event.addListener(marker, 'click', () => {
infoWindow.open(this.map, marker.getPosition())
})
markers.push(marker)
})
AMap.plugin(['AMap.ToolBar', 'AMap.Scale'], () => {
this.map.addControl(new AMap.ToolBar())
this.map.addControl(new AMap.Scale())
})
},
createInfoWindow(title, content) {
const info = document.createElement('div')
info.className = 'info'
info.setAttribute('id', 'info')
//
// info.style.width = "400px"
//
const top = document.createElement('div')
const titleD = document.createElement('div')
titleD.className = 'title'
const closeX = document.createElement('img')
top.className = 'info-top'
titleD.innerHTML = title
closeX.src = 'https://webapi.amap.com/images/close2.gif'
closeX.onclick = this.closeInfoWindow
top.appendChild(titleD)
top.appendChild(closeX)
info.appendChild(top)
//
const middle = document.createElement('div')
middle.className = 'info-middle'
middle.innerHTML = content
info.appendChild(middle)
//
const bottom = document.createElement('div')
bottom.className = 'info-bottom'
bottom.style.position = 'relative'
bottom.style.top = '0px'
bottom.style.margin = '0 auto'
const sharp = document.createElement('img')
sharp.src = 'https://webapi.amap.com/images/sharp.png'
bottom.appendChild(sharp)
info.appendChild(bottom)
// console.log(info)
return info
},
instantiateInforWindow(item, drivingButton = false) {
const content = []
const curTime = moment().format('YYYY-MM-DD HH:mm:ss')
content.push('<div class="count">' + item.count + '</div>')
content.push('<div class="time">Time: ' + curTime + '</div>')
content.push('<div><span>Signal: ' + item.signal + '</span><span class="energy">Energy: ' + item.energy + '</span></div>')
content.push('<div><span>TEMP: ' + '30.3℃' + '</span><span class="humidity">HUM: ' + '69%' + '</span></div>')
// content.push('<div></div>\n')
// if (drivingButton) {
// content.push('<button id="btn" class="btn"></button>')
// }
const infoWindow = new AMap.InfoWindow({
isCustom: true,
closeWhenClickMap: true,
content: this.createInfoWindow(item.device_name, content.join('\n')),
offset: new AMap.Pixel(16, -45)
})
return infoWindow
},
closeInfoWindow() {
this.map.clearInfoWindow()
},
onComplete(data) {
var str = ['定位成功']
this.geo = [data.position.getLng(), data.position.getLat()]
str.push(data.position.getLng())
str.push(data.position.getLat())
console.log(this.geo)
if (data.accuracy) {
str.push('精度:' + data.accuracy + ' 米')
}
str.push('是否经过偏移:' + (data.isConverted ? '是' : '否'))
document.getElementById('geo-tip').innerHTML = str.join('<br>')
const drivingOptions = {
map: this.geo_map,
panel: 'panel'
}
//
const driving = new AMap.Driving(drivingOptions)
const button = document.getElementById('bt')
driving.search(new AMap.LngLat(data.position.getLng(), data.position.getLat()), new AMap.LngLat(113.203460828994, 22.64902452257), (status, result) => {
button.onclick = () => {
driving.searchOnAMAP({
origin: result.origin,
destination: result.destination
})
}
})
},
onError() {
document.getElementById('geo-tip').innerHTML = '定位失败'
},
handleDrivingClick() {
const geo_map = new AMap.Map('map-container')
this.geo_map = geo_map
AMap.plugin(['AMap.ToolBar', 'AMap.Scale', 'AMap.Driving', 'AMap.Geolocation'], () => {
geo_map.addControl(new AMap.ToolBar())
geo_map.addControl(new AMap.Scale())
const geolocation = new AMap.Geolocation({
enableHighAccuracy: true,
timeout: 10000,
buttonOffset: new AMap.Pixel(10, 20),
zoomToAccuracy: true,
panToLocation: false,
buttonPosition: 'RB'
})
geo_map.addControl(geolocation)
geolocation.getCurrentPosition()
//
AMap.event.addListener(geolocation, 'complete', this.onComplete)
//
AMap.event.addListener(geolocation, 'error', this.onError)
})
},
gotoDrivingEvent(e) {
const event = e || window.event
const target = event.target || event.srcElement
if (target.nodeName.toLocaleLowerCase() === 'button') {
console.log('the content is: ', target.innerHTML)
this.gotoDriving()
}
},
getDevicesInitMap(params) {
fetchDeviceList(params).then(response => {
this.deviceList = response.data.results
const item = this.deviceList[0]
this.coordinate = item.coordinate
if (!this.coordinate) {
this.coordinate = [113.203460828994, 22.64902452257]
}
this.map = new AMap.Map('map-container', {
center: this.coordinate,
resizeEnable: true,
zoom: 15
})
const marker = new AMap.Marker({
position: this.coordinate,
zIndex: 10,
map: this.map
})
item.title = item.device_name
const infoWindow = this.instantiateInforWindow(item, true)
AMap.event.addListener(marker, 'click', () => {
infoWindow.open(this.map, marker.getPosition())
})
// this.handleDrivingClick()
// this.flag = true
// if (AMap.UA.mobile) {
// document.getElementById('panel').style.display = 'none'
// // document.getElementById('bt-wrapper').style.display = 'normal'
// }
})
const mapContainer = document.getElementById('map-container')
mapContainer.addEventListener('click', this.gotoDrivingEvent)
}
},
created() {
// this.mapClick = this.$store.getters.mapClick
},
async mounted() {
const device_id = this.$route.query.device_id
if (device_id) {
// const device_id = this.$store.getters.deviceID
// this.sleep(2000)
this.getDevicesInitMap({ device_id })
} else {
await this.initMap()
}
}
}
</script>
<style lang="css">
#map-container {
width: 100%;
height: 90%;
overflow: hidden;
position: absolute;
}
.info {
border: solid 1px silver;
}
div.info-top {
position: relative;
background: none repeat scroll 0 0 #F9F9F9;
border-bottom: 1px solid #CCC;
border-radius: 5px 5px 0 0;
}
div.info-top .title {
display: inline-block;
color: rgb(236, 110, 37);
font-size: 14px;
font-weight: bold;
line-height: 31px;
padding: 0 10px;
}
div.info-top img {
position: absolute;
top: 10px;
right: 10px;
transition-duration: 0.25s;
}
div.info-top img:hover {
box-shadow: 0px 0px 5px #000;
}
div.info-middle {
font-size: 12px;
padding: .4rem .8rem .5rem .5rem;
line-height: 20px;
background-color: white;
}
.info-middle .count {
display: flex;
justify-content: flex-end;
font-size: 1.5rem;
font-weight: bold;
color: #666;
margin: 0 0 .4rem 0;
}
.info-middle span.energy {
margin-left: 2.4rem;
}
.info-middle span.humidity {
margin-left: 1.0rem;
}
div.info-bottom {
height: 0px;
width: 100%;
clear: both;
text-align: center;
}
div.info-bottom img {
position: relative;
z-index: 104;
}
#panel {
position: absolute;
background-color: white;
max-height: 80%;
overflow-y: auto;
top: 10px;
right: 10px;
width: 250px;
border: solid 1px silver;
margin-top: 100px;
}
@media only screen and (max-width: 768px) {
#panel {
display: none;
}
.el-message-box {
width: 100%;
}
}
#geo-tip {
font-size: .8rem;
position: absolute;
padding: 5px;
color: white;
background-color:goldenrod;
width: 150px;
top: 15%;
left: 10%;
border-radius: 5px;
text-align: center;
}
#bt-wrapper {
position: absolute;
width: 2rem;
bottom: 15%;
right: 10rem;
}
#bt {
font-size: .8rem;
text-align: center;
cursor: pointer;
border-radius: 5px;
background-color: #0D9BF2;
padding: 6px;
width: 160px;
color: white;
margin: 0 auto;
}
#btn {
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
background: #fff;
border: 1px solid #dcdfe6;
border-color: #dcdfe6;
color: #606266;
-webkit-appearance: none;
text-align: center;
box-sizing: border-box;
outline: none;
margin: 0;
transition: .1s;
font-weight: 500;
padding: 5px 5px;
font-size: 12px;
border-radius: 2px;
}
#btn:focus, #btn:hover {
color: #409eff;
border-color: #c6e2ff;
background-color: #ecf5ff;
}
</style>

View File

@ -67,16 +67,22 @@ export default {
chartData: {
deep: true,
handler(val) {
this.chart.resize()
this.setOptions(val)
// setTimeout(() => { this.chart.resize() }, 3000)
}
}
},
methods: {
setOptions({ expectedData, actualData } = {}) {
setOptions({ historyData, xAxis, title } = {}) {
this.chart.setOption({
xAxis: {
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
// data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
data: xAxis,
boundaryGap: false,
axisLabel: {
interval: 0
},
axisTick: {
show: false
}
@ -101,10 +107,10 @@ export default {
}
},
legend: {
data: ['expected', 'actual']
data: [title]
},
series: [{
name: 'expected', itemStyle: {
name: title, itemStyle: {
normal: {
color: '#FF005A',
lineStyle: {
@ -115,35 +121,16 @@ export default {
},
smooth: true,
type: 'line',
data: expectedData,
data: historyData,
animationDuration: 2800,
animationEasing: 'cubicInOut'
},
{
name: 'actual',
smooth: true,
type: 'line',
itemStyle: {
normal: {
color: '#3888fa',
lineStyle: {
color: '#3888fa',
width: 2
},
areaStyle: {
color: '#f3f8ff'
}
}
},
data: actualData,
animationDuration: 2800,
animationEasing: 'quadraticOut'
}]
})
},
initChart() {
this.chart = echarts.init(this.$el, 'macarons')
this.setOptions(this.chartData)
console.log(this.chartData)
// this.setOptions(this.chartData)
}
}
}

View File

@ -0,0 +1,54 @@
<template>
<div>
<el-table
v-loading="listLoading"
:data="historyList"
style="width: 100%">
<el-table-column
type="index"
label="序号">
</el-table-column>
<el-table-column
prop="date"
label="日期"
min-width="100">
</el-table-column>
<el-table-column
prop="increment"
label="数量"
min-width="100">
</el-table-column>
</el-table>
</div>
</template>
<script>
import { fetchLogStatisticHistory } from '@/api/counter'
export default {
name: 'LogHistoryTable',
data() {
return {
listLoading: true,
historyList: []
}
},
methods: {
getLogStatisticHistory() {
fetchLogStatisticHistory().then(response => {
this.historyList = response.data.results
this.historyList.forEach((item, index) => {
})
this.listLoading = false
this.$emit('history', this.historyList)
})
}
},
created() {
this.getLogStatisticHistory()
}
}
</script>
<style rel="stylesheet/scss" lang="scss">
</style>

View File

@ -1,46 +1,46 @@
<template>
<el-row class="panel-group" :gutter="40">
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
<div class='card-panel' @click="handleSetLineChartData('newVisitis')">
<div class="card-panel-icon-wrapper icon-people">
<svg-icon icon-class="peoples" class-name="card-panel-icon" />
<div class='card-panel' @click="handleSetLineChartData('total')">
<div class="card-panel-icon-wrapper icon-plus">
<svg-icon icon-class="plus" class-name="card-panel-icon" />
</div>
<div class="card-panel-description">
<div class="card-panel-text">New Visits</div>
<count-to class="card-panel-num" :startVal="0" :endVal="102400" :duration="2600"></count-to>
<div class="card-panel-text">Monthly Mosquito</div>
<count-to class="card-panel-num" :startVal="0" :endVal="curMonthCount" :duration="2600"></count-to>
</div>
</div>
</el-col>
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
<div class="card-panel" @click="handleSetLineChartData('messages')">
<div class="card-panel-icon-wrapper icon-message">
<svg-icon icon-class="message" class-name="card-panel-icon" />
<div class="card-panel" @click="handleSetLineChartData('increment')">
<div class="card-panel-icon-wrapper icon-rise">
<svg-icon icon-class="rise" class-name="card-panel-icon" />
</div>
<div class="card-panel-description">
<div class="card-panel-text">Messages</div>
<count-to class="card-panel-num" :startVal="0" :endVal="81212" :duration="3000"></count-to>
<div class="card-panel-text">Daily Mosquito</div>
<count-to class="card-panel-num" :startVal="0" :endVal="dailyCount" :duration="3000"></count-to>
</div>
</div>
</el-col>
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
<div class="card-panel" @click="handleSetLineChartData('purchases')">
<div class="card-panel-icon-wrapper icon-money">
<svg-icon icon-class="money" class-name="card-panel-icon" />
<div class="card-panel">
<div class="card-panel-icon-wrapper icon-online">
<svg-icon icon-class="online" class-name="card-panel-icon" />
</div>
<div class="card-panel-description">
<div class="card-panel-text">Purchases</div>
<count-to class="card-panel-num" :startVal="0" :endVal="9280" :duration="3200"></count-to>
<div class="card-panel-text">Online Device</div>
<count-to class="card-panel-num" :startVal="0" :endVal="onlineCount" :duration="3200"></count-to>
</div>
</div>
</el-col>
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
<div class="card-panel" @click="handleSetLineChartData('shoppings')">
<div class="card-panel-icon-wrapper icon-shoppingCard">
<svg-icon icon-class="shoppingCard" class-name="card-panel-icon" />
<div class="card-panel">
<div class="card-panel-icon-wrapper icon-offline">
<svg-icon icon-class="offline" class-name="card-panel-icon" />
</div>
<div class="card-panel-description">
<div class="card-panel-text">Shoppings</div>
<count-to class="card-panel-num" :startVal="0" :endVal="13600" :duration="3600"></count-to>
<div class="card-panel-text">Offline Device</div>
<count-to class="card-panel-num" :startVal="0" :endVal="offlineCount" :duration="3600"></count-to>
</div>
</div>
</el-col>
@ -51,6 +51,12 @@
import CountTo from 'vue-count-to'
export default {
props: {
curMonthCount: Number,
dailyCount: Number,
onlineCount: Number,
offlineCount: Number
},
components: {
CountTo
},
@ -82,30 +88,30 @@ export default {
.card-panel-icon-wrapper {
color: #fff;
}
.icon-people {
background: #40c9c6;
}
.icon-message {
.icon-plus {
background: #36a3f7;
}
.icon-money {
background: #f4516c;
.icon-rise {
background: #40c9c6;
}
.icon-shoppingCard {
background: #34bfa3
.icon-online {
background: #5be496;
}
.icon-offline {
background: #f4516c
}
}
.icon-people {
color: #40c9c6;
}
.icon-message {
.icon-plus {
color: #36a3f7;
}
.icon-money {
color: #f4516c;
.icon-rise {
color: #40c9c6;
}
.icon-shoppingCard {
color: #34bfa3
.icon-online {
color: #5be496;
}
.icon-offline {
color: #f4516c
}
.card-panel-icon-wrapper {
float: left;
@ -119,10 +125,10 @@ export default {
font-size: 48px;
}
.card-panel-description {
float: right;
// float: right;
font-weight: bold;
margin: 26px;
margin-left: 0px;
margin-left: 120px;
.card-panel-text {
line-height: 18px;
color: rgba(0, 0, 0, 0.45);
@ -134,5 +140,30 @@ export default {
}
}
}
@media only screen and (max-width: 768px) {
.card-panel-icon-wrapper {
float: none!important;
text-align: center;
margin: 0!important;
border-radius: 0!important;
padding: 1rem 0 1rem 0!important;
}
.card-panel-icon {
float: none!important;
font-size: 2.2rem!important;
}
.card-panel-description {
float: none!important;
font-weight: bold;
text-align: center;
margin: .5rem 0 0 0!important;
.card-panel-text {
display: none;
}
.card-panel-num {
font-size: 1rem!important;
}
}
}
}
</style>

View File

@ -1,98 +1,109 @@
<template>
<div class="dashboard-editor-container">
<github-corner></github-corner>
<!-- <github-corner></github-corner> -->
<panel-group @handleSetLineChartData="handleSetLineChartData"></panel-group>
<panel-group
@handleSetLineChartData="handleSetLineChartData"
:curMonthCount="curMonthCount"
:dailyCount="dailyCount"
:onlineCount="onlineCount"
:offlineCount="offlineCount"
>
</panel-group>
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
<line-chart :chart-data="lineChartData"></line-chart>
</el-row>
<el-row :gutter="32">
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">
<raddar-chart></raddar-chart>
</div>
</el-col>
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">
<pie-chart></pie-chart>
</div>
</el-col>
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">
<bar-chart></bar-chart>
</div>
</el-col>
</el-row>
<el-row :gutter="8">
<!-- <el-col :xs="{span: 24}" :sm="{span: 24}" :md="{span: 24}" :lg="{span: 12}" :xl="{span: 12}" style="padding-right:8px;margin-bottom:30px;">
<transaction-table></transaction-table>
</el-col> -->
<el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 5}" style="margin-bottom:30px;">
<todo-list></todo-list>
</el-col>
<el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 5}" style="margin-bottom:30px;" >
<box-card></box-card>
</el-col>
<el-row>
<log-history-table
@history="handleHistoryLine"
></log-history-table>
</el-row>
</div>
</template>
<script>
import GithubCorner from '@/components/GithubCorner'
import PanelGroup from './components/PanelGroup'
import LineChart from './components/LineChart'
import RaddarChart from './components/RaddarChart'
import PieChart from './components/PieChart'
import BarChart from './components/BarChart'
import LogHistoryTable from './components/LogHistoryTable'
import TransactionTable from './components/TransactionTable'
import TodoList from './components/TodoList'
import BoxCard from './components/BoxCard'
import
{
fetchDeviceLogStatistic,
fetchDeviceInfoStatistic
// fetchLogStatisticHistory
} from '@/api/counter'
const lineChartData = {
newVisitis: {
expectedData: [100, 120, 161, 134, 105, 160, 165],
actualData: [120, 82, 91, 154, 162, 140, 145]
total: {
historyData: [],
xAxis: [],
title: 'Total'
},
messages: {
expectedData: [200, 192, 120, 144, 160, 130, 140],
actualData: [180, 160, 151, 106, 145, 150, 130]
},
purchases: {
expectedData: [80, 100, 121, 104, 105, 90, 100],
actualData: [120, 90, 100, 138, 142, 130, 130]
},
shoppings: {
expectedData: [130, 140, 141, 142, 145, 150, 160],
actualData: [120, 82, 91, 154, 162, 140, 130]
increment: {
historyData: [],
xAxis: [],
title: 'Increment'
}
}
export default {
name: 'dashboard-admin',
components: {
GithubCorner,
PanelGroup,
LineChart,
RaddarChart,
PieChart,
BarChart,
TransactionTable,
TodoList,
BoxCard
LogHistoryTable,
TransactionTable
},
data() {
return {
lineChartData: lineChartData.newVisitis
lineChartData: lineChartData.total,
curMonthCount: 0,
dailyCount: 0,
onlineCount: 0,
offlineCount: 0,
historyList: []
}
},
methods: {
handleSetLineChartData(type) {
this.lineChartData = lineChartData[type]
},
getDeviceInfoStatistic() {
fetchDeviceInfoStatistic().then(response => {
const infoData = response.data
this.onlineCount = infoData['online_count']
this.offlineCount = infoData['offline_count']
})
},
getDeviceLogStatistic() {
fetchDeviceLogStatistic().then(response => {
const data = response.data
this.curMonthCount = data['cur_month_count']
this.dailyCount = data['daily_count']
})
},
handleHistoryLine(historyList) {
const totalList = []
const incrementList = []
const dateList = []
console.log(historyList)
historyList.forEach((item, index) => {
totalList.push(item.total)
incrementList.push(item.increment)
dateList.push(item.date.substr(5))
})
lineChartData.total.historyData = totalList.reverse()
lineChartData.increment.historyData = incrementList.reverse()
lineChartData.total.xAxis = dateList.reverse()
lineChartData.increment.xAxis = dateList
}
},
created() {
this.getDeviceInfoStatistic()
this.getDeviceLogStatistic()
}
}
</script>

View File

@ -23,7 +23,11 @@ export default {
])
},
created() {
if (!this.roles.includes('admin')) {
const adminDashboardRoles = new Set(['manager', 'admin', 'staff'])
const userRoles = new Set(this.roles)
const intersection = new Set([...userRoles].filter(role => adminDashboardRoles.has(role)))
console.log(intersection.size)
if (intersection.size === 0) {
this.currentRole = 'editorDashboard'
}
}

View File

@ -1,47 +0,0 @@
<template>
<div class="app-container documentation-container">
<a class="document-btn" target='_blank' href="https://panjiachen.github.io/vue-element-admin-site/">{{$t('documentation.documentation')}}</a>
<a class="document-btn" target='_blank' href="https://github.com/PanJiaChen/vue-element-admin/">{{$t('documentation.github')}}</a>
<dropdown-menu style="float:left;margin-left:50px;" title='系列文章' :items='articleList'></dropdown-menu>
</div>
</template>
<script>
import DropdownMenu from '@/components/Share/dropdownMenu'
export default {
name: 'documentation',
components: { DropdownMenu },
data() {
return {
articleList: [
{ title: '基础篇', href: 'https://segmentfault.com/a/1190000009275424' },
{ title: '登录权限篇', href: 'https://segmentfault.com/a/1190000009506097' },
{ title: '实战篇', href: 'https://segmentfault.com/a/1190000009762198' },
{ title: 'vueAdmin-template 篇', href: 'https://segmentfault.com/a/1190000010043013' },
{ title: '自行封装 component', href: 'https://segmentfault.com/a/1190000009090836' },
{ title: '优雅的使用 icon', href: 'https://segmentfault.com/a/1190000012213278' }
]
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.documentation-container {
margin: 50px;
.document-btn {
float: left;
margin-left: 50px;
vertical-align: middle;
display: block;
cursor: pointer;
background: black;
color: white;
height: 60px;
width: 200px;
line-height: 60px;
font-size: 20px;
text-align: center;
}
}
</style>

View File

@ -1,253 +0,0 @@
<template>
<div class="createPost-container">
<el-form class="form-container" :model="postForm" :rules="rules" ref="postForm">
<sticky :className="'sub-navbar '+postForm.status">
<CommentDropdown v-model="postForm.comment_disabled" />
<PlatformDropdown v-model="postForm.platforms" />
<SourceUrlDropdown v-model="postForm.source_uri" />
<el-button v-loading="loading" style="margin-left: 10px;" type="success" @click="submitForm">发布
</el-button>
<el-button v-loading="loading" type="warning" @click="draftForm">草稿</el-button>
</sticky>
<div class="createPost-main-container">
<el-row>
<Warning />
<el-col :span="21">
<el-form-item style="margin-bottom: 40px;" prop="title">
<MDinput name="name" v-model="postForm.title" required :maxlength="100">
标题
</MDinput>
</el-form-item>
<div class="postInfo-container">
<el-row>
<el-col :span="8">
<el-form-item label-width="45px" label="作者:" class="postInfo-container-item">
<el-select v-model="postForm.author" filterable remote placeholder="搜索用户" :remote-method="getRemoteUserList">
<el-option v-for="(item,index) in userListOptions" :key="item+index" :label="item" :value="item">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label-width="80px" label="发布时间:" class="postInfo-container-item">
<el-date-picker v-model="postForm.display_time" type="datetime" format="yyyy-MM-dd HH:mm:ss" placeholder="选择日期时间">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label-width="60px" label="重要性:" class="postInfo-container-item">
<el-rate style="margin-top:8px;" v-model="postForm.importance" :max='3' :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :low-threshold="1"
:high-threshold="3">
</el-rate>
</el-form-item>
</el-col>
</el-row>
</div>
</el-col>
</el-row>
<el-form-item style="margin-bottom: 40px;" label-width="45px" label="摘要:">
<el-input type="textarea" class="article-textarea" :rows="1" autosize placeholder="请输入内容" v-model="postForm.content_short">
</el-input>
<span class="word-counter" v-show="contentShortLength">{{contentShortLength}}</span>
</el-form-item>
<div class="editor-container">
<Tinymce :height=400 ref="editor" v-model="postForm.content" />
</div>
<div style="margin-bottom: 20px;">
<Upload v-model="postForm.image_uri" />
</div>
</div>
</el-form>
</div>
</template>
<script>
import Tinymce from '@/components/Tinymce'
import Upload from '@/components/Upload/singleImage3'
import MDinput from '@/components/MDinput'
import Multiselect from 'vue-multiselect'// 使element-uiselect
import 'vue-multiselect/dist/vue-multiselect.min.css'// css
import Sticky from '@/components/Sticky' // header
import { validateURL } from '@/utils/validate'
import { fetchArticle } from '@/api/article'
import { userSearch } from '@/api/remoteSearch'
import Warning from './Warning'
import { CommentDropdown, PlatformDropdown, SourceUrlDropdown } from './Dropdown'
const defaultForm = {
status: 'draft',
title: '', //
content: '', //
content_short: '', //
source_uri: '', //
image_uri: '', //
display_time: undefined, //
id: undefined,
platforms: ['a-platform'],
comment_disabled: false,
importance: 0
}
export default {
name: 'articleDetail',
components: { Tinymce, MDinput, Upload, Multiselect, Sticky, Warning, CommentDropdown, PlatformDropdown, SourceUrlDropdown },
props: {
isEdit: {
type: Boolean,
default: false
}
},
data() {
const validateRequire = (rule, value, callback) => {
if (value === '') {
this.$message({
message: rule.field + '为必传项',
type: 'error'
})
callback(null)
} else {
callback()
}
}
const validateSourceUri = (rule, value, callback) => {
if (value) {
if (validateURL(value)) {
callback()
} else {
this.$message({
message: '外链url填写不正确',
type: 'error'
})
callback(null)
}
} else {
callback()
}
}
return {
postForm: Object.assign({}, defaultForm),
loading: false,
userListOptions: [],
rules: {
image_uri: [{ validator: validateRequire }],
title: [{ validator: validateRequire }],
content: [{ validator: validateRequire }],
source_uri: [{ validator: validateSourceUri, trigger: 'blur' }]
}
}
},
computed: {
contentShortLength() {
return this.postForm.content_short.length
}
},
created() {
if (this.isEdit) {
const id = this.$route.params && this.$route.params.id
this.fetchData(id)
} else {
this.postForm = Object.assign({}, defaultForm)
}
},
methods: {
fetchData(id) {
fetchArticle(id).then(response => {
this.postForm = response.data
// Just for test
this.postForm.title += ` Article Id:${this.postForm.id}`
this.postForm.content_short += ` Article Id:${this.postForm.id}`
}).catch(err => {
console.log(err)
})
},
submitForm() {
this.postForm.display_time = parseInt(this.display_time / 1000)
console.log(this.postForm)
this.$refs.postForm.validate(valid => {
if (valid) {
this.loading = true
this.$notify({
title: '成功',
message: '发布文章成功',
type: 'success',
duration: 2000
})
this.postForm.status = 'published'
this.loading = false
} else {
console.log('error submit!!')
return false
}
})
},
draftForm() {
if (this.postForm.content.length === 0 || this.postForm.title.length === 0) {
this.$message({
message: '请填写必要的标题和内容',
type: 'warning'
})
return
}
this.$message({
message: '保存成功',
type: 'success',
showClose: true,
duration: 1000
})
this.postForm.status = 'draft'
},
getRemoteUserList(query) {
userSearch(query).then(response => {
if (!response.data.items) return
this.userListOptions = response.data.items.map(v => v.name)
})
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
@import "src/styles/mixin.scss";
.createPost-container {
position: relative;
.createPost-main-container {
padding: 40px 45px 20px 50px;
.postInfo-container {
position: relative;
@include clearfix;
margin-bottom: 10px;
.postInfo-container-item {
float: left;
}
}
.editor-container {
min-height: 500px;
margin: 0 0 30px;
.editor-upload-btn-container {
text-align: right;
margin-right: 10px;
.editor-upload-btn {
display: inline-block;
}
}
}
}
.word-counter {
width: 40px;
position: absolute;
right: -10px;
top: 0px;
}
}
</style>

View File

@ -1,31 +0,0 @@
<template>
<el-dropdown trigger="click" :show-timeout="100">
<el-button plain>{{!comment_disabled?'评论已打开':'评论已关闭'}}
<i class="el-icon-caret-bottom el-icon--right"></i>
</el-button>
<el-dropdown-menu class="no-padding" slot="dropdown">
<el-dropdown-item>
<el-radio-group style="padding: 10px;" v-model="comment_disabled">
<el-radio :label="true">关闭评论</el-radio>
<el-radio :label="false">打开评论</el-radio>
</el-radio-group>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<script>
export default {
props: ['value'],
computed: {
comment_disabled: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
}
}
}
</script>

View File

@ -1,40 +0,0 @@
<template>
<el-dropdown :hide-on-click="false" :show-timeout="100" trigger="click">
<el-button plain>
平台({{platforms.length}})
<i class="el-icon-caret-bottom el-icon--right"></i>
</el-button>
<el-dropdown-menu class="no-border" slot="dropdown">
<el-checkbox-group v-model="platforms" style="padding: 5px 15px;">
<el-checkbox v-for="item in platformsOptions" :label="item.key" :key="item.key">
{{item.name}}
</el-checkbox>
</el-checkbox-group>
</el-dropdown-menu>
</el-dropdown>
</template>
<script>
export default {
props: ['value'],
data() {
return {
platformsOptions: [
{ key: 'a-platform', name: 'a-platform' },
{ key: 'b-platform', name: 'b-platform' },
{ key: 'c-platform', name: 'c-platform' }
]
}
},
computed: {
platforms: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
}
}
}
</script>

View File

@ -1,31 +0,0 @@
<template>
<el-dropdown :show-timeout="100" trigger="click">
<el-button plain>
外链
<i class="el-icon-caret-bottom el-icon--right"></i>
</el-button>
<el-dropdown-menu class="no-padding no-border" style="width:400px" slot="dropdown">
<el-form-item label-width="0px" style="margin-bottom: 0px" prop="source_uri">
<el-input placeholder="请输入内容" v-model="source_uri">
<template slot="prepend">填写url</template>
</el-input>
</el-form-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<script>
export default {
props: ['value'],
computed: {
source_uri: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
}
}
}
</script>

View File

@ -1,3 +0,0 @@
export { default as CommentDropdown } from './Comment'
export { default as PlatformDropdown } from './Platform'
export { default as SourceUrlDropdown } from './SourceUrl'

View File

@ -1,9 +0,0 @@
<template>
<p class="warn-content">
创建和编辑页面是不能被keep-alive 缓存的因为keep-alive 的include 目前不支持根据路由来缓存所以目前都是基于component name 来缓存的如果你想要实现缓存的效果可以使用localstorage 等游览器缓存方案或者不要使用keep-alive
的include直接缓存所有页面详情见
<a href="https://panjiachen.github.io/vue-element-admin-site/guide/essentials/tags-view.html"
target="_blank">文档</a>
</p>
</template>

View File

@ -1,13 +0,0 @@
<template>
<article-detail :is-edit='false'></article-detail>
</template>
<script>
import ArticleDetail from './components/ArticleDetail'
export default {
name: 'createForm',
components: { ArticleDetail }
}
</script>

View File

@ -1,13 +0,0 @@
<template>
<article-detail :is-edit='true'></article-detail>
</template>
<script>
import ArticleDetail from './components/ArticleDetail'
export default {
name: 'editForm',
components: { ArticleDetail }
}
</script>

View File

@ -1,121 +0,0 @@
<template>
<div class="app-container">
<el-table :data="list" v-loading.body="listLoading" border fit highlight-current-row style="width: 100%">
<el-table-column align="center" label="ID" width="80">
<template slot-scope="scope">
<span>{{scope.row.id}}</span>
</template>
</el-table-column>
<el-table-column width="180px" align="center" label="Date">
<template slot-scope="scope">
<span>{{scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}')}}</span>
</template>
</el-table-column>
<el-table-column width="120px" align="center" label="Author">
<template slot-scope="scope">
<span>{{scope.row.author}}</span>
</template>
</el-table-column>
<el-table-column width="100px" label="Importance">
<template slot-scope="scope">
<svg-icon v-for="n in +scope.row.importance" icon-class="star" class="meta-item__icon" :key="n"></svg-icon>
</template>
</el-table-column>
<el-table-column class-name="status-col" label="Status" width="110">
<template slot-scope="scope">
<el-tag :type="scope.row.status | statusFilter">{{scope.row.status}}</el-tag>
</template>
</el-table-column>
<el-table-column min-width="300px" label="Title">
<template slot-scope="scope">
<router-link class="link-type" :to="'/example/edit/'+scope.row.id">
<span>{{ scope.row.title }}</span>
</router-link>
</template>
</el-table-column>
<el-table-column align="center" label="Actions" width="120">
<template slot-scope="scope">
<router-link :to="'/example/edit/'+scope.row.id">
<el-button type="primary" size="small" icon="el-icon-edit">Edit</el-button>
</router-link>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.page"
:page-sizes="[10,20,30, 50]" :page-size="listQuery.limit" layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
</div>
</div>
</template>
<script>
import { fetchList } from '@/api/article'
export default {
name: 'articleList',
data() {
return {
list: null,
total: 0,
listLoading: true,
listQuery: {
page: 1,
limit: 10
}
}
},
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'info',
deleted: 'danger'
}
return statusMap[status]
}
},
created() {
this.getList()
},
methods: {
getList() {
this.listLoading = true
fetchList(this.listQuery).then(response => {
this.list = response.data.items
this.total = response.data.total
this.listLoading = false
})
},
handleSizeChange(val) {
this.listQuery.limit = val
this.getList()
},
handleCurrentChange(val) {
this.listQuery.page = val
this.getList()
}
}
}
</script>
<style scoped>
.edit-input {
padding-right: 100px;
}
.cancel-btn {
position: absolute;
right: 15px;
top: 10px;
}
</style>

View File

@ -1,108 +0,0 @@
<template>
<!-- $t is vue-i18n global function to translate lang -->
<div class="app-container">
<label class="radio-label" style="padding-left:0;">Filename: </label>
<el-input style='width:340px;' :placeholder="$t('excel.placeholder')" prefix-icon="el-icon-document" v-model="filename"></el-input>
<label class="radio-label">Cell Auto Width: </label>
<el-radio-group v-model="autoWidth">
<el-radio :label="true" border>True</el-radio>
<el-radio :label="false" border>False</el-radio>
</el-radio-group>
<el-button style='margin:0 0 20px 20px;' type="primary" icon="document" @click="handleDownload" :loading="downloadLoading">{{$t('excel.export')}} excel</el-button>
<el-table :data="list" v-loading="listLoading" element-loading-text="拼命加载中" border fit highlight-current-row>
<el-table-column align="center" label='Id' width="95">
<template slot-scope="scope">
{{scope.$index}}
</template>
</el-table-column>
<el-table-column label="Title">
<template slot-scope="scope">
{{scope.row.title}}
</template>
</el-table-column>
<el-table-column label="Author" width="110" align="center">
<template slot-scope="scope">
<el-tag>{{scope.row.author}}</el-tag>
</template>
</el-table-column>
<el-table-column label="Readings" width="115" align="center">
<template slot-scope="scope">
{{scope.row.pageviews}}
</template>
</el-table-column>
<el-table-column align="center" label="Date" width="220">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span>{{scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}')}}</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import { fetchList } from '@/api/article'
import { parseTime } from '@/utils'
export default {
name: 'exportExcel',
data() {
return {
list: null,
listLoading: true,
downloadLoading: false,
filename: '',
autoWidth: true
}
},
created() {
this.fetchData()
},
methods: {
fetchData() {
this.listLoading = true
fetchList().then(response => {
this.list = response.data.items
this.listLoading = false
})
},
handleDownload() {
this.downloadLoading = true
import('@/vendor/Export2Excel').then(excel => {
const tHeader = ['Id', 'Title', 'Author', 'Readings', 'Date']
const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time']
const list = this.list
const data = this.formatJson(filterVal, list)
excel.export_json_to_excel({
header: tHeader,
data,
filename: this.filename,
autoWidth: this.autoWidth
})
this.downloadLoading = false
})
},
formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => {
if (j === 'timestamp') {
return parseTime(v[j])
} else {
return v[j]
}
}))
}
}
}
</script>
<style>
.radio-label {
font-size: 14px;
color: #606266;
line-height: 40px;
padding: 0 12px 0 30px;
}
</style>

View File

@ -1,95 +0,0 @@
<template>
<div class="app-container">
<!-- $t is vue-i18n global function to translate lang -->
<el-input style='width:340px;' :placeholder="$t('excel.placeholder')" prefix-icon="el-icon-document" v-model="filename"></el-input>
<el-button style='margin-bottom:20px' type="primary" icon="document" @click="handleDownload" :loading="downloadLoading">{{$t('excel.selectedExport')}}</el-button>
<el-table :data="list" v-loading="listLoading" element-loading-text="拼命加载中" border fit highlight-current-row @selection-change="handleSelectionChange"
ref="multipleTable">
<el-table-column type="selection" align="center"></el-table-column>
<el-table-column align="center" label='Id' width="95">
<template slot-scope="scope">
{{scope.$index}}
</template>
</el-table-column>
<el-table-column label="Title">
<template slot-scope="scope">
{{scope.row.title}}
</template>
</el-table-column>
<el-table-column label="Author" width="110" align="center">
<template slot-scope="scope">
<el-tag>{{scope.row.author}}</el-tag>
</template>
</el-table-column>
<el-table-column label="Readings" width="115" align="center">
<template slot-scope="scope">
{{scope.row.pageviews}}
</template>
</el-table-column>
<el-table-column align="center" label="PDate" width="220">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span>{{scope.row.display_time}}</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import { fetchList } from '@/api/article'
export default {
name: 'selectExcel',
data() {
return {
list: null,
listLoading: true,
multipleSelection: [],
downloadLoading: false,
filename: ''
}
},
created() {
this.fetchData()
},
methods: {
fetchData() {
this.listLoading = true
fetchList(this.listQuery).then(response => {
this.list = response.data.items
this.listLoading = false
})
},
handleSelectionChange(val) {
this.multipleSelection = val
},
handleDownload() {
if (this.multipleSelection.length) {
this.downloadLoading = true
import('@/vendor/Export2Excel').then(excel => {
const tHeader = ['Id', 'Title', 'Author', 'Readings', 'Date']
const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time']
const list = this.multipleSelection
const data = this.formatJson(filterVal, list)
excel.export_json_to_excel({
header: tHeader,
data,
filename: this.filename
})
this.$refs.multipleTable.clearSelection()
this.downloadLoading = false
})
} else {
this.$message({
message: 'Please select at least one item',
type: 'warning'
})
}
},
formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => v[j]))
}
}
}
</script>

View File

@ -1,43 +0,0 @@
<template>
<div class="app-container">
<upload-excel-component :on-success='handleSuccess' :before-upload="beforeUpload"></upload-excel-component>
<el-table :data="tableData" border highlight-current-row style="width: 100%;margin-top:20px;">
<el-table-column v-for='item of tableHeader' :prop="item" :label="item" :key='item'>
</el-table-column>
</el-table>
</div>
</template>
<script>
import UploadExcelComponent from '@/components/UploadExcel/index.vue'
export default {
name: 'uploadExcel',
components: { UploadExcelComponent },
data() {
return {
tableData: [],
tableHeader: []
}
},
methods: {
beforeUpload(file) {
const isLt1M = file.size / 1024 / 1024 < 1
if (isLt1M) {
return true
}
this.$message({
message: 'Please do not upload files larger than 1m in size.',
type: 'warning'
})
return false
},
handleSuccess({ results, header }) {
this.tableData = results
this.tableHeader = header
}
}
}
</script>

View File

@ -1,52 +0,0 @@
const steps = [
{
element: '.hamburger-container',
popover: {
title: 'Hamburger',
description: 'Open && Close sidebar',
position: 'bottom'
}
},
{
element: '.breadcrumb-container',
popover: {
title: 'Breadcrumb',
description: 'Indicate the current page location',
position: 'bottom'
}
},
{
element: '.screenfull',
popover: {
title: 'Screenfull',
description: 'Bring the page into fullscreen',
position: 'left'
}
},
{
element: '.international-icon',
popover: {
title: 'Switch language',
description: 'Switch the system language',
position: 'left'
}
},
{
element: '.theme-switch',
popover: {
title: 'Theme Switch',
description: 'Custom switch system theme',
position: 'left'
}
},
{
element: '.tags-view-container',
popover: {
title: 'Tags view',
description: 'The history of the page you visited',
position: 'bottom'
}
}
]
export default steps

View File

@ -1,34 +0,0 @@
<template>
<div class="app-container">
<p class="warn-content">
{{$t('guide.description')}}
<a href="https://github.com/kamranahmedse/driver.js" target="_blank">driver.js.
</a>
</p>
<el-button icon='el-icon-question' type="primary" @click.prevent.stop="guide">{{$t('guide.button')}}</el-button>
</div>
</template>
<script>
import * as Driver from 'driver.js' // import driver.js
import 'driver.js/dist/driver.min.css' // import driver.js css
import steps from './defineSteps'
export default {
name: 'guide',
data() {
return {
driver: null
}
},
mounted() {
this.driver = new Driver()
},
methods: {
guide() {
this.driver.defineSteps(steps)
this.driver.start()
}
}
}
</script>

View File

@ -1,111 +0,0 @@
<template>
<div>
<el-card class="box-card" style="margin-top:40px;">
<div slot="header" class="clearfix">
<svg-icon icon-class="international" />
<span style='margin-left:10px;'>{{$t('i18nView.title')}}</span>
</div>
<div>
<el-radio-group v-model="lang" size="small">
<el-radio label="zh" border>简体中文</el-radio>
<el-radio label="en" border>English</el-radio>
</el-radio-group>
<el-tag style='margin-top:15px;display:block;' type="info">{{$t('i18nView.note')}}</el-tag>
</div>
</el-card>
<el-row :gutter="20" style="margin:100px 15px 50px;">
<el-col :span="12">
<div class="block">
<el-date-picker v-model="date" type="date" :placeholder="$t('i18nView.datePlaceholder')"></el-date-picker>
</div>
<div class="block">
<el-pagination background :current-page="currentPage" :page-sizes="[100, 200, 300, 400]" :page-size="100" layout="total, sizes, prev, pager, next"
:total="400">
</el-pagination>
</div>
<div class="block">
<el-button class="item-btn" size="small">{{$t('i18nView.default')}}</el-button>
<el-button class="item-btn" size="small" type="primary">{{$t('i18nView.primary')}}</el-button>
<el-button class="item-btn" size="small" type="success">{{$t('i18nView.success')}}</el-button>
<el-button class="item-btn" size="small" type="info">{{$t('i18nView.info')}}</el-button>
<el-button class="item-btn" size="small" type="warning">{{$t('i18nView.warning')}}</el-button>
<el-button class="item-btn" size="small" type="danger">{{$t('i18nView.danger')}}</el-button>
</div>
</el-col>
<el-col :span="12">
<el-table :data="tableData" fit highlight-current-row border style="width: 100%">
<el-table-column prop="name" :label="$t('i18nView.tableName')" width="100" align="center"></el-table-column>
<el-table-column prop="date" :label="$t('i18nView.tableDate')" width="120" align="center"></el-table-column>
<el-table-column prop="address" :label="$t('i18nView.tableAddress')"></el-table-column>
</el-table>
</el-col>
</el-row>
</div>
</template>
<script>
import local from './local'
const viewName = 'i18nView'
export default {
name: 'i18n',
data() {
return {
date: '',
currentPage: 5,
tableData: [{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
}]
}
},
created() {
if (!this.$i18n.getLocaleMessage('en')[viewName]) {
this.$i18n.mergeLocaleMessage('en', local.en)
this.$i18n.mergeLocaleMessage('zh', local.zh)
}
},
computed: {
lang: {
get() {
return this.$store.state.app.language
},
set(lang) {
this.$i18n.locale = lang
this.$store.dispatch('setLanguage', lang)
}
}
}
}
</script>
<style scoped>
.box-card {
width: 600px;
margin: 20px auto;
}
.item-btn{
margin-bottom: 15px;
margin-left: 0px;
}
.block {
padding: 25px;
}
</style>

View File

@ -1,36 +0,0 @@
export default {
zh: {
i18nView: {
title: '切换语言',
note: '目前只翻译了当前页面和侧边栏和导航,未完待续,敬请期待...',
datePlaceholder: '请选择日期',
tableDate: '日期',
tableName: '姓名',
tableAddress: '地址',
default: '默认按钮',
primary: '主要按钮',
success: '成功按钮',
info: '信息按钮',
warning: '警告按钮',
danger: '危险按钮'
}
},
en: {
i18nView: {
title: 'Switch Language',
note: 'Currently only translated the i18n page and the sidebar and levelbar, please look forword to...',
datePlaceholder: 'Pick a day',
tableDate: 'tableDate',
tableName: 'tableName',
tableAddress: 'tableAddress',
default: 'default:',
primary: 'primary',
success: 'success',
info: 'info',
warning: 'warning',
danger: 'danger'
}
}
}

View File

@ -13,26 +13,29 @@
<lang-select class="international right-menu-item"></lang-select>
<el-tooltip effect="dark" :content="$t('navbar.theme')" placement="bottom">
<!-- <el-tooltip effect="dark" :content="$t('navbar.theme')" placement="bottom">
<theme-picker class="theme-switch right-menu-item"></theme-picker>
</el-tooltip>
</el-tooltip> -->
<el-dropdown class="avatar-container right-menu-item" trigger="click">
<div class="avatar-wrapper">
<img class="user-avatar" :src="avatar+'?imageView2/1/w/80/h/80'">
<img class="user-avatar" :src="avatar+'?x-oss-process=image/resize,m_fixed,h_80,w_80'">
<i class="el-icon-caret-bottom"></i>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item disabled>
<span style="color: #999;">{{$store.getters.name}}</span>
</el-dropdown-item>
<router-link to="/">
<el-dropdown-item>
<el-dropdown-item divided>
{{$t('navbar.dashboard')}}
</el-dropdown-item>
</router-link>
<a target='_blank' href="https://github.com/PanJiaChen/vue-element-admin/">
<!-- <a target='_blank' href="https://github.com/PanJiaChen/vue-element-admin/">
<el-dropdown-item>
{{$t('navbar.github')}}
</el-dropdown-item>
</a>
</a> -->
<el-dropdown-item divided>
<span @click="logout" style="display:block;">{{$t('navbar.logOut')}}</span>
</el-dropdown-item>
@ -49,7 +52,7 @@ import Hamburger from '@/components/Hamburger'
import ErrorLog from '@/components/ErrorLog'
import Screenfull from '@/components/Screenfull'
import LangSelect from '@/components/LangSelect'
import ThemePicker from '@/components/ThemePicker'
// import ThemePicker from '@/components/ThemePicker'
export default {
components: {
@ -57,8 +60,8 @@ export default {
Hamburger,
ErrorLog,
Screenfull,
LangSelect,
ThemePicker
LangSelect
// ThemePicker
},
computed: {
...mapGetters([

View File

@ -1,7 +0,0 @@
<template>
<div class="app-container">
<code>Parent View: Bar</code>
<img src="https://wpimg.wallstcn.com/be29a7d2-5ccf-4a2b-888d-8a6c2bbb7aac.png">
<router-view></router-view>
</div>
</template>

View File

@ -1,6 +0,0 @@
<template>
<div style="margin-top:30px;">
<el-alert title="Children: Posts" type="warning" :closable="false">
</el-alert>
</div>
</template>

View File

@ -1,6 +0,0 @@
<template>
<div style="margin-top:30px;">
<el-alert title="Children: Profile" type="success" :closable="false">
</el-alert>
</div>
</template>

View File

@ -1,30 +0,0 @@
<template>
<div>
<div style="margin-bottom:15px;">{{$t('permission.roles')}} {{roles}}</div>
{{$t('permission.switchRoles')}}
<el-radio-group v-model="switchRoles">
<el-radio-button label="editor"></el-radio-button>
<el-radio-button label="admin"></el-radio-button>
</el-radio-group>
</div>
</template>
<script>
export default {
computed: {
roles() {
return this.$store.getters.roles
},
switchRoles: {
get() {
return this.roles[0]
},
set(val) {
this.$store.dispatch('ChangeRoles', val).then(() => {
this.$emit('change')
})
}
}
}
}
</script>

View File

@ -1,72 +0,0 @@
<template>
<div class="app-container">
<switch-roles @change="handleRolesChange" />
<div :key="key" style="margin-top:30px;">
<span v-permission="['admin']" class="permission-alert">
Only
<el-tag class="permission-tag" size="small">admin</el-tag> can see this
</span>
<span v-permission="['editor']" class="permission-alert">
Only
<el-tag class="permission-tag" size="small">editor</el-tag> can see this
</span>
<span v-permission="['admin','editor']" class="permission-alert">
Both
<el-tag class="permission-tag" size="small">admin</el-tag> and
<el-tag class="permission-tag" size="small">editor</el-tag> can see this
</span>
</div>
<div style="margin-top:30px;" :key="'checkPermission'+key">
<code>In some cases it is not suitable to use v-permission, such as element Tab component which can only be achieved by manually setting the v-if.
<br> e.g.
</code>
<el-tabs type="border-card" style="width:500px;">
<el-tab-pane v-if="checkPermission(['admin'])" label="Admin">Admin can see this</el-tab-pane>
<el-tab-pane v-if="checkPermission(['editor'])" label="Editor">Editor can see this</el-tab-pane>
<el-tab-pane v-if="checkPermission(['admin','editor'])" label="Admin-OR-Editor">Both admin or editor can see this</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script>
import permission from '@/directive/permission/index.js' //
import checkPermission from '@/utils/permission' //
import SwitchRoles from './components/SwitchRoles'
export default{
name: 'directivePermission',
components: { SwitchRoles },
directives: { permission },
data() {
return {
key: 1 //
}
},
methods: {
checkPermission,
handleRolesChange() {
this.key++
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.app-container {
/deep/ .permission-alert {
width: 320px;
margin-top: 30px;
background-color: #f0f9eb;
color: #67c23a;
padding: 8px 16px;
border-radius: 4px;
display: block;
}
/deep/ .permission-tag{
background-color: #ecf5ff;
}
}
</style>

View File

@ -1,19 +0,0 @@
<template>
<div class="app-container">
<switch-roles @change="handleRolesChange" />
</div>
</template>
<script>
import SwitchRoles from './components/SwitchRoles'
export default{
name: 'pagePermission',
components: { SwitchRoles },
methods: {
handleRolesChange() {
this.$router.push({ path: '/permission/index?' + +new Date() })
}
}
}
</script>

View File

@ -1,40 +0,0 @@
<template>
<el-upload action="https://upload.qbox.me" :data="dataObj" drag :multiple="true" :before-upload="beforeUpload">
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
</el-upload>
</template>
<script>
import { getToken } from '@/api/qiniu'
// token Access Key,Secret Key,buckettoken
// sdk https://developer.qiniu.com/sdk#official-sdk
export default{
data() {
return {
dataObj: { token: '', key: '' },
image_uri: [],
fileList: []
}
},
methods: {
beforeUpload() {
const _self = this
return new Promise((resolve, reject) => {
getToken().then(response => {
const key = response.data.qiniu_key
const token = response.data.qiniu_token
_self._data.dataObj.token = token
_self._data.dataObj.key = key
resolve(true)
}).catch(err => {
console.log(err)
reject(false)
})
})
}
}
}
</script>

View File

@ -1,14 +1,12 @@
<template>
<div class="app-container">
<p class="warn-content">
只能模块消息推送列表
</p>
<p class="warn-content">设备设置</p>
</div>
</template>
<script>
export default {
name: 'count'
name: 'deviceSetting'
}
</script>

View File

@ -0,0 +1,15 @@
<template>
<div class="app-container">
<p class="warn-content">系统设置</p>
</div>
</template>
<script>
export default {
name: 'systemSetting'
}
</script>
<style lang="scss">
</style>

View File

@ -1,98 +0,0 @@
<template>
<el-table :data="list" border fit highlight-current-row style="width: 100%">
<el-table-column align="center" label="ID" width="65" v-loading="loading"
element-loading-text="请给我点时间!">
<template slot-scope="scope">
<span>{{scope.row.id}}</span>
</template>
</el-table-column>
<el-table-column width="180px" align="center" label="Date">
<template slot-scope="scope">
<span>{{scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}')}}</span>
</template>
</el-table-column>
<el-table-column min-width="300px" label="Title">
<template slot-scope="scope">
<span>{{scope.row.title}}</span>
<el-tag>{{scope.row.type}}</el-tag>
</template>
</el-table-column>
<el-table-column width="110px" align="center" label="Author">
<template slot-scope="scope">
<span>{{scope.row.author}}</span>
</template>
</el-table-column>
<el-table-column width="120px" label="Importance">
<template slot-scope="scope">
<svg-icon v-for="n in +scope.row.importance" icon-class="star" :key="n"></svg-icon>
</template>
</el-table-column>
<el-table-column align="center" label="Readings" width="95">
<template slot-scope="scope">
<span>{{scope.row.pageviews}}</span>
</template>
</el-table-column>
<el-table-column class-name="status-col" label="Status" width="110">
<template slot-scope="scope">
<el-tag :type="scope.row.status | statusFilter">{{scope.row.status}}</el-tag>
</template>
</el-table-column>
</el-table>
</template>
<script>
import { fetchList } from '@/api/article'
export default {
props: {
type: {
type: String,
default: 'CN'
}
},
data() {
return {
list: null,
listQuery: {
page: 1,
limit: 5,
type: this.type,
sort: '+id'
},
loading: false
}
},
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'info',
deleted: 'danger'
}
return statusMap[status]
}
},
created() {
this.getList()
},
methods: {
getList() {
this.loading = true
this.$emit('create') // for test
fetchList(this.listQuery).then(response => {
this.list = response.data.items
this.loading = false
})
}
}
}
</script>

View File

@ -1,46 +0,0 @@
<template>
<div class="tab-container">
<el-tag>mounted times {{createdTimes}}</el-tag>
<el-alert style="width:200px;display:inline-block;vertical-align: middle;margin-left:30px;" title="Tab with keep-alive" type="success" :closable="false">
</el-alert>
<el-tabs style='margin-top:15px;' v-model="activeName" type="border-card">
<el-tab-pane v-for="item in tabMapOptions" :label="item.label" :key='item.key' :name="item.key">
<keep-alive>
<tab-pane v-if='activeName==item.key' :type='item.key' @create='showCreatedTimes'></tab-pane>
</keep-alive>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import tabPane from './components/tabPane'
export default {
name: 'tab',
components: { tabPane },
data() {
return {
tabMapOptions: [
{ label: 'China', key: 'CN' },
{ label: 'USA', key: 'US' },
{ label: 'Japan', key: 'JP' },
{ label: 'Eurozone', key: 'EU' }
],
activeName: 'CN',
createdTimes: 0
}
},
methods: {
showCreatedTimes() {
this.createdTimes = this.createdTimes + 1
}
}
}
</script>
<style scoped>
.tab-container{
margin: 30px;
}
</style>

View File

@ -1,361 +0,0 @@
<template>
<div class="app-container">
<div class="filter-container">
<el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" :placeholder="$t('table.title')" v-model="listQuery.title">
</el-input>
<el-select clearable style="width: 90px" class="filter-item" v-model="listQuery.importance" :placeholder="$t('table.importance')">
<el-option v-for="item in importanceOptions" :key="item" :label="item" :value="item">
</el-option>
</el-select>
<el-select clearable class="filter-item" style="width: 130px" v-model="listQuery.type" :placeholder="$t('table.type')">
<el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name+'('+item.key+')'" :value="item.key">
</el-option>
</el-select>
<el-select @change='handleFilter' style="width: 140px" class="filter-item" v-model="listQuery.sort">
<el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key">
</el-option>
</el-select>
<el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">{{$t('table.search')}}</el-button>
<el-button class="filter-item" style="margin-left: 10px;" @click="handleCreate" type="primary" icon="el-icon-edit">{{$t('table.add')}}</el-button>
<el-button class="filter-item" type="primary" :loading="downloadLoading" v-waves icon="el-icon-download" @click="handleDownload">{{$t('table.export')}}</el-button>
<el-checkbox class="filter-item" style='margin-left:15px;' @change='tableKey=tableKey+1' v-model="showReviewer">{{$t('table.reviewer')}}</el-checkbox>
</div>
<el-table :key='tableKey' :data="list" v-loading="listLoading" border fit highlight-current-row
style="width: 100%;min-height:1000px;">
<el-table-column align="center" :label="$t('table.id')" width="65">
<template slot-scope="scope">
<span>{{scope.row.id}}</span>
</template>
</el-table-column>
<el-table-column width="150px" align="center" :label="$t('table.date')">
<template slot-scope="scope">
<span>{{scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}')}}</span>
</template>
</el-table-column>
<el-table-column min-width="150px" :label="$t('table.title')">
<template slot-scope="scope">
<span class="link-type" @click="handleUpdate(scope.row)">{{scope.row.title}}</span>
<el-tag>{{scope.row.type | typeFilter}}</el-tag>
</template>
</el-table-column>
<el-table-column width="110px" align="center" :label="$t('table.author')">
<template slot-scope="scope">
<span>{{scope.row.author}}</span>
</template>
</el-table-column>
<el-table-column width="110px" v-if='showReviewer' align="center" :label="$t('table.reviewer')">
<template slot-scope="scope">
<span style='color:red;'>{{scope.row.reviewer}}</span>
</template>
</el-table-column>
<el-table-column width="80px" :label="$t('table.importance')">
<template slot-scope="scope">
<svg-icon v-for="n in +scope.row.importance" icon-class="star" class="meta-item__icon" :key="n"></svg-icon>
</template>
</el-table-column>
<el-table-column align="center" :label="$t('table.readings')" width="95">
<template slot-scope="scope">
<span v-if="scope.row.pageviews" class="link-type" @click='handleFetchPv(scope.row.pageviews)'>{{scope.row.pageviews}}</span>
<span v-else>0</span>
</template>
</el-table-column>
<el-table-column class-name="status-col" :label="$t('table.status')" width="100">
<template slot-scope="scope">
<el-tag :type="scope.row.status | statusFilter">{{scope.row.status}}</el-tag>
</template>
</el-table-column>
<el-table-column align="center" :label="$t('table.actions')" width="230" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button type="primary" size="mini" @click="handleUpdate(scope.row)">{{$t('table.edit')}}</el-button>
<el-button v-if="scope.row.status!='published'" size="mini" type="success" @click="handleModifyStatus(scope.row,'published')">{{$t('table.publish')}}
</el-button>
<el-button v-if="scope.row.status!='draft'" size="mini" @click="handleModifyStatus(scope.row,'draft')">{{$t('table.draft')}}
</el-button>
<el-button v-if="scope.row.status!='deleted'" size="mini" type="danger" @click="handleModifyStatus(scope.row,'deleted')">{{$t('table.delete')}}
</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.page" :page-sizes="[10,20,30, 50]" :page-size="listQuery.limit" layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
</div>
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
<el-form :rules="rules" ref="dataForm" :model="temp" label-position="left" label-width="70px" style='width: 400px; margin-left:50px;'>
<el-form-item :label="$t('table.type')" prop="type">
<el-select class="filter-item" v-model="temp.type" placeholder="Please select">
<el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name" :value="item.key">
</el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('table.date')" prop="timestamp">
<el-date-picker v-model="temp.timestamp" type="datetime" placeholder="Please pick a date">
</el-date-picker>
</el-form-item>
<el-form-item :label="$t('table.title')" prop="title">
<el-input v-model="temp.title"></el-input>
</el-form-item>
<el-form-item :label="$t('table.status')">
<el-select class="filter-item" v-model="temp.status" placeholder="Please select">
<el-option v-for="item in statusOptions" :key="item" :label="item" :value="item">
</el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('table.importance')">
<el-rate style="margin-top:8px;" v-model="temp.importance" :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :max='3'></el-rate>
</el-form-item>
<el-form-item :label="$t('table.remark')">
<el-input type="textarea" :autosize="{ minRows: 2, maxRows: 4}" placeholder="Please input" v-model="temp.remark">
</el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">{{$t('table.cancel')}}</el-button>
<el-button v-if="dialogStatus=='create'" type="primary" @click="createData">{{$t('table.confirm')}}</el-button>
<el-button v-else type="primary" @click="updateData">{{$t('table.confirm')}}</el-button>
</div>
</el-dialog>
<el-dialog title="Reading statistics" :visible.sync="dialogPvVisible">
<el-table :data="pvData" border fit highlight-current-row style="width: 100%">
<el-table-column prop="key" label="Channel"> </el-table-column>
<el-table-column prop="pv" label="Pv"> </el-table-column>
</el-table>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogPvVisible = false">{{$t('table.confirm')}}</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article'
import waves from '@/directive/waves' //
import { parseTime } from '@/utils'
const calendarTypeOptions = [
{ key: 'CN', display_name: 'China' },
{ key: 'US', display_name: 'USA' },
{ key: 'JP', display_name: 'Japan' },
{ key: 'EU', display_name: 'Eurozone' }
]
// arr to obj ,such as { CN : "China", US : "USA" }
const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => {
acc[cur.key] = cur.display_name
return acc
}, {})
export default {
name: 'complexTable',
directives: {
waves
},
data() {
return {
tableKey: 0,
list: null,
total: null,
listLoading: true,
listQuery: {
page: 1,
limit: 20,
importance: undefined,
title: undefined,
type: undefined,
sort: '+id'
},
importanceOptions: [1, 2, 3],
calendarTypeOptions,
sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }],
statusOptions: ['published', 'draft', 'deleted'],
showReviewer: false,
temp: {
id: undefined,
importance: 1,
remark: '',
timestamp: new Date(),
title: '',
type: '',
status: 'published'
},
dialogFormVisible: false,
dialogStatus: '',
textMap: {
update: 'Edit',
create: 'Create'
},
dialogPvVisible: false,
pvData: [],
rules: {
type: [{ required: true, message: 'type is required', trigger: 'change' }],
timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }],
title: [{ required: true, message: 'title is required', trigger: 'blur' }]
},
downloadLoading: false
}
},
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'info',
deleted: 'danger'
}
return statusMap[status]
},
typeFilter(type) {
return calendarTypeKeyValue[type]
}
},
created() {
this.getList()
},
methods: {
getList() {
this.listLoading = true
fetchList(this.listQuery).then(response => {
this.list = response.data.items
this.total = response.data.total
// Just to simulate the time of the request
setTimeout(() => {
this.listLoading = false
}, 1.5 * 1000)
})
},
handleFilter() {
this.listQuery.page = 1
this.getList()
},
handleSizeChange(val) {
this.listQuery.limit = val
this.getList()
},
handleCurrentChange(val) {
this.listQuery.page = val
this.getList()
},
handleModifyStatus(row, status) {
this.$message({
message: '操作成功',
type: 'success'
})
row.status = status
},
resetTemp() {
this.temp = {
id: undefined,
importance: 1,
remark: '',
timestamp: new Date(),
title: '',
status: 'published',
type: ''
}
},
handleCreate() {
this.resetTemp()
this.dialogStatus = 'create'
this.dialogFormVisible = true
this.$nextTick(() => {
this.$refs['dataForm'].clearValidate()
})
},
createData() {
this.$refs['dataForm'].validate((valid) => {
if (valid) {
this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id
this.temp.author = 'vue-element-admin'
createArticle(this.temp).then(() => {
this.list.unshift(this.temp)
this.dialogFormVisible = false
this.$notify({
title: '成功',
message: '创建成功',
type: 'success',
duration: 2000
})
})
}
})
},
handleUpdate(row) {
this.temp = Object.assign({}, row) // copy obj
this.temp.timestamp = new Date(this.temp.timestamp)
this.dialogStatus = 'update'
this.dialogFormVisible = true
this.$nextTick(() => {
this.$refs['dataForm'].clearValidate()
})
},
updateData() {
this.$refs['dataForm'].validate((valid) => {
if (valid) {
const tempData = Object.assign({}, this.temp)
tempData.timestamp = +new Date(tempData.timestamp) // change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464
updateArticle(tempData).then(() => {
for (const v of this.list) {
if (v.id === this.temp.id) {
const index = this.list.indexOf(v)
this.list.splice(index, 1, this.temp)
break
}
}
this.dialogFormVisible = false
this.$notify({
title: '成功',
message: '更新成功',
type: 'success',
duration: 2000
})
})
}
})
},
handleDelete(row) {
this.$notify({
title: '成功',
message: '删除成功',
type: 'success',
duration: 2000
})
const index = this.list.indexOf(row)
this.list.splice(index, 1)
},
handleFetchPv(pv) {
fetchPv(pv).then(response => {
this.pvData = response.data.pvData
this.dialogPvVisible = true
})
},
handleDownload() {
this.downloadLoading = true
import('@/vendor/Export2Excel').then(excel => {
const tHeader = ['timestamp', 'title', 'type', 'importance', 'status']
const filterVal = ['timestamp', 'title', 'type', 'importance', 'status']
const data = this.formatJson(filterVal, this.list)
excel.export_json_to_excel({
header: tHeader,
data,
filename: 'table-list'
})
this.downloadLoading = false
})
},
formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => {
if (j === 'timestamp') {
return parseTime(v[j])
} else {
return v[j]
}
}))
}
}
}
</script>

View File

@ -1,152 +0,0 @@
<template>
<div class="app-container">
<!-- Note that row-key is necessary to get a correct row order. -->
<el-table :data="list" row-key="id" v-loading="listLoading" border fit highlight-current-row style="width: 100%">
<el-table-column align="center" label="ID" width="65">
<template slot-scope="scope">
<span>{{scope.row.id}}</span>
</template>
</el-table-column>
<el-table-column width="180px" align="center" label="Date">
<template slot-scope="scope">
<span>{{scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}')}}</span>
</template>
</el-table-column>
<el-table-column min-width="300px" label="Title">
<template slot-scope="scope">
<span>{{scope.row.title}}</span>
</template>
</el-table-column>
<el-table-column width="110px" align="center" label="Author">
<template slot-scope="scope">
<span>{{scope.row.author}}</span>
</template>
</el-table-column>
<el-table-column width="100px" label="Importance">
<template slot-scope="scope">
<svg-icon v-for="n in +scope.row.importance" icon-class="star" class="icon-star" :key="n"></svg-icon>
</template>
</el-table-column>
<el-table-column align="center" label="Readings" width="95">
<template slot-scope="scope">
<span>{{scope.row.pageviews}}</span>
</template>
</el-table-column>
<el-table-column class-name="status-col" label="Status" width="110">
<template slot-scope="scope">
<el-tag :type="scope.row.status | statusFilter">{{scope.row.status}}</el-tag>
</template>
</el-table-column>
<el-table-column align="center" label="Drag" width="80">
<template slot-scope="scope">
<svg-icon class='drag-handler' icon-class="drag"></svg-icon>
</template>
</el-table-column>
</el-table>
<!-- $t is vue-i18n global function to translate lang (lang in @/lang) -->
<div class='show-d'>{{$t('table.dragTips1')}} : &nbsp; {{ oldList}}</div>
<div class='show-d'>{{$t('table.dragTips2')}} : {{newList}}</div>
</div>
</template>
<script>
import { fetchList } from '@/api/article'
import Sortable from 'sortablejs'
export default {
name: 'dragTable',
data() {
return {
list: null,
total: null,
listLoading: true,
listQuery: {
page: 1,
limit: 10
},
sortable: null,
oldList: [],
newList: []
}
},
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'info',
deleted: 'danger'
}
return statusMap[status]
}
},
created() {
this.getList()
},
methods: {
getList() {
this.listLoading = true
fetchList(this.listQuery).then(response => {
this.list = response.data.items
this.total = response.data.total
this.listLoading = false
this.oldList = this.list.map(v => v.id)
this.newList = this.oldList.slice()
this.$nextTick(() => {
this.setSort()
})
})
},
setSort() {
const el = document.querySelectorAll('.el-table__body-wrapper > table > tbody')[0]
this.sortable = Sortable.create(el, {
ghostClass: 'sortable-ghost', // Class name for the drop placeholder,
setData: function(dataTransfer) {
dataTransfer.setData('Text', '')
// to avoid Firefox bug
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
},
onEnd: evt => {
const targetRow = this.list.splice(evt.oldIndex, 1)[0]
this.list.splice(evt.newIndex, 0, targetRow)
// for show the changes, you can delete in you code
const tempIndex = this.newList.splice(evt.oldIndex, 1)[0]
this.newList.splice(evt.newIndex, 0, tempIndex)
}
})
}
}
}
</script>
<style>
.sortable-ghost{
opacity: .8;
color: #fff!important;
background: #42b983!important;
}
</style>
<style scoped>
.icon-star{
margin-right:2px;
}
.drag-handler{
width: 20px;
height: 20px;
cursor: pointer;
}
.show-d{
margin-top: 15px;
}
</style>

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