提交更改版本
This commit is contained in:
@@ -25,14 +25,17 @@
|
||||
"file-saver": "v2.0.5",
|
||||
"html2canvas": "^1.4.1",
|
||||
"jquery": "^3.7.1",
|
||||
"jszip": "^3.10.1",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.21",
|
||||
"luckyexcel": "v1.0.1",
|
||||
"luckysheet": "2.1.13",
|
||||
"mitt": "^3.0.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"screenfull": "^6.0.2",
|
||||
"splitpanes": "3.1.5",
|
||||
"use-element-plus-theme": "^0.0.5",
|
||||
"vue": "^3.3.11",
|
||||
"vue-draggable-resizable": "3.0.0-beta.2",
|
||||
@@ -43,6 +46,7 @@
|
||||
"devDependencies": {
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/node": "^20.10.5",
|
||||
"@types/splitpanes": "2.2.6",
|
||||
"@vitejs/plugin-vue": "^4.5.2",
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"sass": "^1.69.5",
|
||||
|
||||
83
pnpm-lock.yaml
generated
83
pnpm-lock.yaml
generated
@@ -56,6 +56,9 @@ importers:
|
||||
jquery:
|
||||
specifier: ^3.7.1
|
||||
version: 3.7.1
|
||||
jszip:
|
||||
specifier: ^3.10.1
|
||||
version: 3.10.1
|
||||
lodash:
|
||||
specifier: ^4.17.21
|
||||
version: 4.17.21
|
||||
@@ -65,6 +68,9 @@ importers:
|
||||
luckyexcel:
|
||||
specifier: v1.0.1
|
||||
version: 1.0.1
|
||||
luckysheet:
|
||||
specifier: 2.1.13
|
||||
version: 2.1.13
|
||||
mitt:
|
||||
specifier: ^3.0.1
|
||||
version: 3.0.1
|
||||
@@ -80,6 +86,9 @@ importers:
|
||||
screenfull:
|
||||
specifier: ^6.0.2
|
||||
version: 6.0.2
|
||||
splitpanes:
|
||||
specifier: 3.1.5
|
||||
version: 3.1.5
|
||||
use-element-plus-theme:
|
||||
specifier: ^0.0.5
|
||||
version: 0.0.5(@types/node@20.10.5)(rollup@4.9.1)(typescript@5.3.3)(vite@5.0.10(@types/node@20.10.5)(sass@1.69.5))
|
||||
@@ -105,6 +114,9 @@ importers:
|
||||
'@types/node':
|
||||
specifier: ^20.10.5
|
||||
version: 20.10.5
|
||||
'@types/splitpanes':
|
||||
specifier: 2.2.6
|
||||
version: 2.2.6
|
||||
'@vitejs/plugin-vue':
|
||||
specifier: ^4.5.2
|
||||
version: 4.5.2(vite@5.0.10(@types/node@20.10.5)(sass@1.69.5))(vue@3.3.13(typescript@5.3.3))
|
||||
@@ -256,7 +268,7 @@ packages:
|
||||
'@babel/core': ^7.0.0-0
|
||||
|
||||
'@babel/runtime@7.23.8':
|
||||
resolution: {integrity: sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==}
|
||||
resolution: {integrity: sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==, tarball: https://registry.npmmirror.com/@babel/runtime/-/runtime-7.23.8.tgz}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/template@7.22.15':
|
||||
@@ -588,6 +600,9 @@ packages:
|
||||
'@types/node@20.10.5':
|
||||
resolution: {integrity: sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==, tarball: https://registry.npmmirror.com/@types/node/-/node-20.10.5.tgz}
|
||||
|
||||
'@types/splitpanes@2.2.6':
|
||||
resolution: {integrity: sha512-3dV5sO1Ht74iER4jJU03mreL3f+Q2h47ZqXS6Sfbqc6hkCvsDrX1GA0NbYWRdNvZemPyTDzUoApWKeoGbALwkQ==, tarball: https://registry.npmmirror.com/@types/splitpanes/-/splitpanes-2.2.6.tgz}
|
||||
|
||||
'@types/web-bluetooth@0.0.16':
|
||||
resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==, tarball: https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz}
|
||||
|
||||
@@ -648,6 +663,9 @@ packages:
|
||||
'@vue/compiler-dom@3.3.13':
|
||||
resolution: {integrity: sha512-EYRDpbLadGtNL0Gph+HoKiYqXLqZ0xSSpR5Dvnu/Ep7ggaCbjRDIus1MMxTS2Qm0koXED4xSlvTZaTnI8cYAsw==, tarball: https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.3.13.tgz}
|
||||
|
||||
'@vue/compiler-sfc@2.7.16':
|
||||
resolution: {integrity: sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg==, tarball: https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz}
|
||||
|
||||
'@vue/compiler-sfc@3.3.13':
|
||||
resolution: {integrity: sha512-DQVmHEy/EKIgggvnGRLx21hSqnr1smUS9Aq8tfxiiot8UR0/pXKHN9k78/qQ7etyQTFj5em5nruODON7dBeumw==, tarball: https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.3.13.tgz}
|
||||
|
||||
@@ -1074,6 +1092,9 @@ packages:
|
||||
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==, tarball: https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
flatpickr@4.6.13:
|
||||
resolution: {integrity: sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==, tarball: https://registry.npmmirror.com/flatpickr/-/flatpickr-4.6.13.tgz}
|
||||
|
||||
follow-redirects@1.15.3:
|
||||
resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==, tarball: https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.3.tgz}
|
||||
engines: {node: '>=4.0'}
|
||||
@@ -1213,6 +1234,9 @@ packages:
|
||||
jju@1.4.0:
|
||||
resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==}
|
||||
|
||||
jquery@2.2.4:
|
||||
resolution: {integrity: sha512-lBHj60ezci2u1v2FqnZIraShGgEXq35qCzMv4lITyHGppTnA13rwR0MgwyNJh9TnDs3aXUvd1xjAotfraMHX/Q==, tarball: https://registry.npmmirror.com/jquery/-/jquery-2.2.4.tgz}
|
||||
|
||||
jquery@3.7.1:
|
||||
resolution: {integrity: sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==}
|
||||
|
||||
@@ -1334,6 +1358,9 @@ packages:
|
||||
luckyexcel@1.0.1:
|
||||
resolution: {integrity: sha512-hvbJmCXNp/vST/huA6sieDn32Ib8bd80L9aIu5ZGxniJvZle7VlpHZrl6weLGaEnX99+t7cPAoYGqrqbfZp/AQ==, tarball: https://registry.npmmirror.com/luckyexcel/-/luckyexcel-1.0.1.tgz}
|
||||
|
||||
luckysheet@2.1.13:
|
||||
resolution: {integrity: sha512-ZotItRKh3fxEtYz0GrZxkf97jeQSGsJpFNAu1I0NMDQ6rVrHAWKeggFak5pClGQ3DP62Gi8kd+8rzOpyY/UNZw==, tarball: https://registry.npmmirror.com/luckysheet/-/luckysheet-2.1.13.tgz}
|
||||
|
||||
magic-string@0.30.5:
|
||||
resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==, tarball: https://registry.npmmirror.com/magic-string/-/magic-string-0.30.5.tgz}
|
||||
engines: {node: '>=12'}
|
||||
@@ -1403,6 +1430,9 @@ packages:
|
||||
nprogress@0.2.0:
|
||||
resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==, tarball: https://registry.npmmirror.com/nprogress/-/nprogress-0.2.0.tgz}
|
||||
|
||||
numeral@2.0.6:
|
||||
resolution: {integrity: sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==, tarball: https://registry.npmmirror.com/numeral/-/numeral-2.0.6.tgz}
|
||||
|
||||
once@1.4.0:
|
||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, tarball: https://registry.npmmirror.com/once/-/once-1.4.0.tgz}
|
||||
|
||||
@@ -1450,6 +1480,11 @@ packages:
|
||||
preact@10.19.3:
|
||||
resolution: {integrity: sha512-nHHTeFVBTHRGxJXKkKu5hT8C/YWBkPso4/Gad6xuj5dbptt9iF9NZr9pHbPhBrnT2klheu7mHTxTZ/LjwJiEiQ==}
|
||||
|
||||
prettier@2.8.8:
|
||||
resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==, tarball: https://registry.npmmirror.com/prettier/-/prettier-2.8.8.tgz}
|
||||
engines: {node: '>=10.13.0'}
|
||||
hasBin: true
|
||||
|
||||
prismjs@1.29.0:
|
||||
resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -1479,7 +1514,7 @@ packages:
|
||||
engines: {node: '>=8.10.0'}
|
||||
|
||||
regenerator-runtime@0.14.1:
|
||||
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
|
||||
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==, tarball: https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz}
|
||||
|
||||
resolve@1.19.0:
|
||||
resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==}
|
||||
@@ -1549,6 +1584,9 @@ packages:
|
||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
splitpanes@3.1.5:
|
||||
resolution: {integrity: sha512-r3Mq2ITFQ5a2VXLOy4/Sb2Ptp7OfEO8YIbhVJqJXoFc9hc5nTXXkCvtVDjIGbvC0vdE7tse+xTM9BMjsszP6bw==, tarball: https://registry.npmmirror.com/splitpanes/-/splitpanes-3.1.5.tgz}
|
||||
|
||||
sprintf-js@1.0.3:
|
||||
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
|
||||
|
||||
@@ -1720,6 +1758,10 @@ packages:
|
||||
peerDependencies:
|
||||
typescript: '*'
|
||||
|
||||
vue@2.7.16:
|
||||
resolution: {integrity: sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==, tarball: https://registry.npmmirror.com/vue/-/vue-2.7.16.tgz}
|
||||
deprecated: Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.
|
||||
|
||||
vue@3.3.13:
|
||||
resolution: {integrity: sha512-LDnUpQvDgsfc0u/YgtAgTMXJlJQqjkxW1PVcOnJA5cshPleULDjHi7U45pl2VJYazSSvLH8UKcid/kzH8I0a0Q==, tarball: https://registry.npmmirror.com/vue/-/vue-3.3.13.tgz}
|
||||
peerDependencies:
|
||||
@@ -2210,6 +2252,10 @@ snapshots:
|
||||
dependencies:
|
||||
undici-types: 5.26.5
|
||||
|
||||
'@types/splitpanes@2.2.6':
|
||||
dependencies:
|
||||
vue: 2.7.16
|
||||
|
||||
'@types/web-bluetooth@0.0.16': {}
|
||||
|
||||
'@types/web-bluetooth@0.0.20': {}
|
||||
@@ -2300,6 +2346,14 @@ snapshots:
|
||||
'@vue/compiler-core': 3.3.13
|
||||
'@vue/shared': 3.3.13
|
||||
|
||||
'@vue/compiler-sfc@2.7.16':
|
||||
dependencies:
|
||||
'@babel/parser': 7.23.6
|
||||
postcss: 8.4.32
|
||||
source-map: 0.6.1
|
||||
optionalDependencies:
|
||||
prettier: 2.8.8
|
||||
|
||||
'@vue/compiler-sfc@3.3.13':
|
||||
dependencies:
|
||||
'@babel/parser': 7.23.6
|
||||
@@ -2868,6 +2922,8 @@ snapshots:
|
||||
dependencies:
|
||||
to-regex-range: 5.0.1
|
||||
|
||||
flatpickr@4.6.13: {}
|
||||
|
||||
follow-redirects@1.15.3: {}
|
||||
|
||||
form-data@4.0.0:
|
||||
@@ -2981,6 +3037,8 @@ snapshots:
|
||||
|
||||
jju@1.4.0: {}
|
||||
|
||||
jquery@2.2.4: {}
|
||||
|
||||
jquery@3.7.1: {}
|
||||
|
||||
js-tokens@4.0.0: {}
|
||||
@@ -3076,6 +3134,15 @@ snapshots:
|
||||
dependencies:
|
||||
jszip: 3.10.1
|
||||
|
||||
luckysheet@2.1.13:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.8
|
||||
dayjs: 1.11.10
|
||||
flatpickr: 4.6.13
|
||||
jquery: 2.2.4
|
||||
numeral: 2.0.6
|
||||
pako: 1.0.11
|
||||
|
||||
magic-string@0.30.5:
|
||||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.4.15
|
||||
@@ -3130,6 +3197,8 @@ snapshots:
|
||||
|
||||
nprogress@0.2.0: {}
|
||||
|
||||
numeral@2.0.6: {}
|
||||
|
||||
once@1.4.0:
|
||||
dependencies:
|
||||
wrappy: 1.0.2
|
||||
@@ -3166,6 +3235,9 @@ snapshots:
|
||||
|
||||
preact@10.19.3: {}
|
||||
|
||||
prettier@2.8.8:
|
||||
optional: true
|
||||
|
||||
prismjs@1.29.0: {}
|
||||
|
||||
process-nextick-args@2.0.1: {}
|
||||
@@ -3275,6 +3347,8 @@ snapshots:
|
||||
|
||||
source-map@0.6.1: {}
|
||||
|
||||
splitpanes@3.1.5: {}
|
||||
|
||||
sprintf-js@1.0.3: {}
|
||||
|
||||
ssr-window@3.0.0: {}
|
||||
@@ -3428,6 +3502,11 @@ snapshots:
|
||||
semver: 7.5.4
|
||||
typescript: 5.3.3
|
||||
|
||||
vue@2.7.16:
|
||||
dependencies:
|
||||
'@vue/compiler-sfc': 2.7.16
|
||||
csstype: 3.1.3
|
||||
|
||||
vue@3.3.13(typescript@5.3.3):
|
||||
dependencies:
|
||||
'@vue/compiler-dom': 3.3.13
|
||||
|
||||
@@ -15,3 +15,22 @@ export function getDeviceData(deviceId: string, type: string, lineId = '') {
|
||||
data: form
|
||||
})
|
||||
}
|
||||
|
||||
//获取趋势数据、暂态数据、实时数据
|
||||
export function getTabsDataByType(data: any) {
|
||||
return createAxios({
|
||||
url: '/cs-device-boot/csGroup/deviceDataByType',
|
||||
method: 'POST',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//获取实时数据列表数据
|
||||
export function getRealTimeTableList() {
|
||||
return createAxios({
|
||||
url: '/cs-device-boot/csGroup/getGroupPortableStatistical',
|
||||
method: 'GET',
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ export function getTemplateList(data:any) {
|
||||
})
|
||||
}
|
||||
//删除报表模板
|
||||
export function delTemplate(data) {
|
||||
export function delTemplate(data:any) {
|
||||
return createAxios({
|
||||
url: '/harmonic-boot/customReport/delTemplate',
|
||||
method: 'post',
|
||||
|
||||
@@ -16,7 +16,7 @@ export const queryStatistical = (id:string) => {
|
||||
// 绑定指标
|
||||
export const addStatistical = (params:any) => {
|
||||
return createAxios({
|
||||
url: '/system-boot/csstatisticalset/addStatistical',
|
||||
url: '/system-boocs-device-boot/wlRecord/saveDataRecordt/csstatisticalset/addStatistical',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
|
||||
@@ -20,8 +20,7 @@ const config = useConfig()
|
||||
color[0] = config.layout.elementUiPrimary[0]
|
||||
const chartRef = ref<HTMLDivElement>()
|
||||
|
||||
const props = defineProps(['options', 'isExport'])
|
||||
const ExportOptions: any = ref({})
|
||||
const props = defineProps(['options'])
|
||||
let chart: echarts.ECharts | any = null
|
||||
const resizeHandler = () => {
|
||||
// 不在视野中的时候不进行resize
|
||||
@@ -110,7 +109,6 @@ const initChart = () => {
|
||||
handlerBar(options)
|
||||
// 处理柱状图
|
||||
chart.setOption(options)
|
||||
ExportOptions.value = options
|
||||
setTimeout(() => {
|
||||
chart.resize()
|
||||
}, 0)
|
||||
|
||||
@@ -23,7 +23,7 @@ const props = withDefaults(
|
||||
}>(),
|
||||
{
|
||||
showCheckbox: false,
|
||||
defaultCheckedKeys: [],
|
||||
defaultCheckedKeys: []
|
||||
}
|
||||
)
|
||||
|
||||
@@ -64,9 +64,9 @@ getDeviceTree().then(res => {
|
||||
}
|
||||
})
|
||||
})
|
||||
const getTreeList = (list:any) => {
|
||||
const getTreeList = (list: any) => {
|
||||
let arr: any[] = []
|
||||
list.forEach((item: any) => {
|
||||
list.forEach((item: any) => {
|
||||
item.icon = 'el-icon-HomeFilled'
|
||||
item.color = config.getColorVal('elementUiPrimary')
|
||||
item.children.forEach((item2: any) => {
|
||||
@@ -83,7 +83,7 @@ const getTreeList = (list:any) => {
|
||||
})
|
||||
})
|
||||
})
|
||||
tree.value = list;
|
||||
tree.value = list
|
||||
nextTick(() => {
|
||||
if (arr.length) {
|
||||
treRef.value.treeRef.setCurrentKey(arr[0].id)
|
||||
@@ -103,5 +103,5 @@ const handleCheckChange = (data: any) => {
|
||||
data
|
||||
})
|
||||
}
|
||||
defineExpose({getTreeList})
|
||||
defineExpose({ getTreeList })
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<Tree ref="treRef" :data="tree" />
|
||||
<Tree ref="treRef" :width="width" :data="tree" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@@ -14,6 +14,7 @@ const emit = defineEmits(['init', 'checkChange'])
|
||||
const config = useConfig()
|
||||
const tree = ref()
|
||||
const treRef = ref()
|
||||
const width=ref('')
|
||||
getLineTree().then(res => {
|
||||
console.log(res.data, '设备监控666')
|
||||
let arr1: any[] = []
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
size="18"
|
||||
class="fold ml10 mt20 menu-collapse"
|
||||
style="cursor: pointer"
|
||||
v-if="route.path!='/admin/govern/reportCore/statistics/index'"
|
||||
/>
|
||||
<div class="cn-tree" :style="{ opacity: menuCollapse ? 0 : 1 }">
|
||||
<div style="display: flex; align-items: center" class="mb10">
|
||||
@@ -27,7 +28,7 @@
|
||||
size="18"
|
||||
class="fold ml10 menu-collapse"
|
||||
style="cursor: pointer"
|
||||
v-if="props.canExpand"
|
||||
v-if="props.canExpand&&route.path!='/admin/govern/reportCore/statistics/index'"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -91,7 +92,7 @@
|
||||
import useCurrentInstance from '@/utils/useCurrentInstance'
|
||||
import { ElTree } from 'element-plus'
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
import {useRoute} from 'vue-router'
|
||||
defineOptions({
|
||||
name: 'govern/tree'
|
||||
})
|
||||
@@ -104,11 +105,14 @@ interface Props {
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
width: '280px',
|
||||
width: '100%',
|
||||
canExpand: true,
|
||||
type: '',
|
||||
data: []
|
||||
})
|
||||
|
||||
const route=useRoute()
|
||||
console.log(route,"6666677788889")
|
||||
const { proxy } = useCurrentInstance()
|
||||
const menuCollapse = ref(false)
|
||||
const activeName = ref(0)
|
||||
@@ -204,6 +208,7 @@ defineExpose({ treeRef1, treeRef2 })
|
||||
padding: 10px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
|
||||
:deep(.el-tree) {
|
||||
border: 1px solid var(--el-border-color);
|
||||
|
||||
@@ -24,6 +24,16 @@ export const adminBaseRoute = {
|
||||
meta: {
|
||||
title: `pagesTitle.loading`
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
// 设备补招
|
||||
path: '/supplementaryRecruitment',
|
||||
name: 'supplementaryRecruitment',
|
||||
component: () => import('@/views/govern/device/control/supplementaryRecruitment.vue'),
|
||||
meta: {
|
||||
title: pageTitle('router.supplementaryRecruitment')
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -8,6 +8,40 @@
|
||||
<PointTree @node-click="nodeClick" @init="nodeClick"></PointTree>
|
||||
<div class="device-control-right" v-if="deviceData">
|
||||
<el-descriptions title="设备基本信息" class="mb10" :column="3" border>
|
||||
<template #extra>
|
||||
<el-button
|
||||
v-if="dataSet.indexOf('_realtimedata') != -1"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleDownLoad"
|
||||
>
|
||||
模版下载
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="dataSet.indexOf('_realtimedata') != -1"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleImport"
|
||||
>
|
||||
离线数据导入
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="dataSet.indexOf('_realtimedata') != -1"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleaddDevice"
|
||||
>
|
||||
设备补招
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="dataSet.indexOf('_realtimedata') != -1"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleImport"
|
||||
>
|
||||
解析列表
|
||||
</el-button>
|
||||
</template>
|
||||
<el-descriptions-item label="名称">
|
||||
{{ deviceData.name ? deviceData.name : '/' }}
|
||||
</el-descriptions-item>
|
||||
@@ -166,8 +200,28 @@
|
||||
</div>
|
||||
<!-- 实时数据 -->
|
||||
<div style="height: calc(100vh - 200px)" v-if="dataSet.indexOf('_realtimedata') != -1">
|
||||
实时数据
|
||||
<RealTime></RealTime>
|
||||
<div class="view_top_btn" v-if="realTimeFlag">
|
||||
<el-button type="primary" size="small" :icon="Platform" @click="handleRecordWaves">
|
||||
实时录波
|
||||
</el-button>
|
||||
<el-button type="primary" size="small" :icon="TrendCharts" @click="handleTrend">
|
||||
实时趋势
|
||||
</el-button>
|
||||
<el-button type="primary" size="small" :icon="DataLine" @click="handleHarmonicSpectrum">
|
||||
谐波频谱
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="view_top_btn" v-if="!realTimeFlag">
|
||||
<el-button type="primary" :icon="ArrowLeft" size="small" @click="handleReturn">返回</el-button>
|
||||
</div>
|
||||
<!-- 实时数据主界面组件 -->
|
||||
<realTime v-if="realTimeFlag" ref="realTimeRef"></realTime>
|
||||
<!-- 实时数据-实时录波组件 -->
|
||||
<recordWoves v-if="!realTimeFlag && sonTab == 0"></recordWoves>
|
||||
<!-- 实时数据-实时趋势组件 -->
|
||||
<realTrend v-if="!realTimeFlag && sonTab == 1"></realTrend>
|
||||
<!-- 实时数据-谐波频谱组件 -->
|
||||
<harmonicSpectrum v-if="!realTimeFlag && sonTab == 2"></harmonicSpectrum>
|
||||
</div>
|
||||
<!-- 暂态事件 -->
|
||||
<div style="height: calc(100vh - 200px)" v-if="dataSet.indexOf('_event') != -1">
|
||||
@@ -175,19 +229,12 @@
|
||||
<Event></Event>
|
||||
</div>
|
||||
<div v-if="!tableData" style="height: 42px"></div>
|
||||
<!-- <el-tab-pane lazy label="趋势数据" name="0">
|
||||
<div style="height:calc(100vh - 330px);overflow: auto;border:1px solid red;"></div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane lazy label="实时数据" name="1">
|
||||
<div style="height:calc(100vh - 330px);overflow: auto;border:1px solid red;"></div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane lazy label="暂态事件" name="2">
|
||||
<div style="height:calc(100vh - 330px);overflow: auto;border:1px solid red;"></div>
|
||||
</el-tab-pane> -->
|
||||
</el-tabs>
|
||||
</div>
|
||||
<el-empty v-else description="请选择设备" class="device-control-right" />
|
||||
<Detail ref="detailRef" :detail="detail" @close="detail = null" v-if="detail"></Detail>
|
||||
<!-- 离线数据导入组件 -->
|
||||
<offLineDataImport ref="offLineDataImportRef"></offLineDataImport>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -196,17 +243,22 @@ import Detail from './detail.vue'
|
||||
import PointTree from '@/components/tree/govern/pointTree.vue'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import { queryByCode, queryByid, queryCsDictTree } from '@/api/system-boot/dictTree'
|
||||
import { getDeviceData } from '@/api/cs-device-boot/EquipmentDelivery'
|
||||
import { deviceHisData, deviceRtData } from '@/api/cs-device-boot/csGroup'
|
||||
import { getGroup } from '@/api/cs-device-boot/csGroup'
|
||||
import { ref, reactive, nextTick, onMounted } from 'vue'
|
||||
import { getDeviceData, getTabsDataByType } from '@/api/cs-device-boot/EquipmentDelivery'
|
||||
import { deviceHisData, deviceRtData, getGroup } from '@/api/cs-device-boot/csGroup'
|
||||
import { ref, reactive, nextTick, onMounted, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||
import Trend from './tabs/trend.vue'
|
||||
import RealTime from './tabs/realtime.vue'
|
||||
import Trend from './tabs/trend.vue' //趋势数据
|
||||
import realTime from './tabs/realtime.vue' //实时数据-主界面
|
||||
import realTrend from './tabs/components/realtrend.vue' //实时数据-实时趋势
|
||||
import harmonicSpectrum from './tabs/components/harmonicSpectrum.vue' //实时数据-谐波频谱子页面
|
||||
import recordWoves from './tabs/components/recordwoves.vue' //实时数据-实时录波子页面
|
||||
import offLineDataImport from './offLineDataImport/index.vue'
|
||||
import Event from './tabs/event.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { defineConfig, loadEnv } from 'vite'
|
||||
import type { UserConfig, ConfigEnv } from 'vite'
|
||||
import { Platform, TrendCharts, DataLine, ArrowLeft } from '@element-plus/icons-vue'
|
||||
defineOptions({
|
||||
name: 'govern/device/control'
|
||||
})
|
||||
@@ -238,6 +290,7 @@ const socket: any = ref(null)
|
||||
const url = 'wss://your-websocket-url'
|
||||
//连接websocket
|
||||
const connectWebSocket = () => {
|
||||
return
|
||||
socket.value = new WebSocket(url)
|
||||
socket.value.onopen = () => {
|
||||
console.log('WebSocket connected')
|
||||
@@ -269,7 +322,30 @@ const disconnectWebSocket = () => {
|
||||
socket.value.close()
|
||||
}
|
||||
}
|
||||
|
||||
//是否显示实时数据默认内容
|
||||
const realTimeFlag = ref(true)
|
||||
//实时数据子菜单
|
||||
const sonTab = ref()
|
||||
//实时录波
|
||||
const handleRecordWaves = () => {
|
||||
realTimeFlag.value = false
|
||||
sonTab.value = 0
|
||||
}
|
||||
//实时趋势
|
||||
const handleTrend = () => {
|
||||
realTimeFlag.value = false
|
||||
sonTab.value = 1
|
||||
}
|
||||
//谐波频谱
|
||||
const handleHarmonicSpectrum = () => {
|
||||
realTimeFlag.value = false
|
||||
sonTab.value = 2
|
||||
}
|
||||
//返回
|
||||
const handleReturn = () => {
|
||||
realTimeFlag.value = true
|
||||
sonTab.value = null
|
||||
}
|
||||
const getDeviceDataTrend = (e: any) => {
|
||||
detail.value = {
|
||||
lineId: formInline.lineId,
|
||||
@@ -285,18 +361,30 @@ const handleSizeChange = (val: number) => {
|
||||
formInline.pageSize = val
|
||||
handleClick()
|
||||
}
|
||||
const { push, options, currentRoute } = useRouter()
|
||||
//设备补招
|
||||
const handleaddDevice = () => {
|
||||
push({
|
||||
path: '/supplementaryRecruitment',
|
||||
query: {
|
||||
id: '1111'
|
||||
}
|
||||
})
|
||||
}
|
||||
//树节点点击事件
|
||||
const deviceId: any = ref('')
|
||||
const lineId: any = ref('')
|
||||
const nodeClick = async (e: anyObj) => {
|
||||
deviceId.value = e.pid
|
||||
lineId.value = e.id
|
||||
if (!e) {
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
console.log(e, '监测点请求的判断')
|
||||
if (e.level == 3) {
|
||||
loading.value = true
|
||||
formInline.lineId = e.id
|
||||
await getDeviceData(e.pid, 'history', e.id).then((res: any) => {
|
||||
console.log(res.data, '-------------')
|
||||
deviceData.value = res.data
|
||||
if (!res.data.dataSetList) {
|
||||
dataSet.value = ''
|
||||
@@ -330,40 +418,89 @@ const nodeClick = async (e: anyObj) => {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
const realTimeRef: any = ref()
|
||||
const intRealTime = (val: any) => {
|
||||
getTabsDataByType(val).then(res => {
|
||||
realTimeRef.value && realTimeRef.value.getRealTimeData(res.data)
|
||||
})
|
||||
}
|
||||
//tab点击事件
|
||||
const handleClick = async (tab?: any) => {
|
||||
tableLoading.value = true
|
||||
//初始化点击tab隐藏实时录波、实时趋势、谐波频谱按钮
|
||||
realTimeFlag.value = false
|
||||
//初始化点击tab隐藏子页面
|
||||
sonTab.value = null
|
||||
if (tab) {
|
||||
tableData.value = []
|
||||
formInline.pageNum = 1
|
||||
}
|
||||
// setTimeout(() => {
|
||||
//查询历史模块数据
|
||||
// setTimeout(async () => {
|
||||
//查询历史指标
|
||||
if (dataSet.value.indexOf('_history') != -1) {
|
||||
console.log('_history')
|
||||
formInline.startTime = datePickerRef.value.timeValue[0]
|
||||
formInline.endTime = datePickerRef.value.timeValue[1]
|
||||
formInline.id = dataSet.value.replace('_history', '')
|
||||
await deviceHisData(formInline).then((res: any) => {
|
||||
console.log(res)
|
||||
tableData.value = res.data.records
|
||||
formInline.total = res.data.total
|
||||
tableLoading.value = false
|
||||
})
|
||||
}
|
||||
//查询数据趋势数据
|
||||
console.log(dataSet.value.indexOf('_trenddata'), '-------')
|
||||
//查询趋势数据
|
||||
if (dataSet.value.indexOf('_trenddata') != -1) {
|
||||
console.log(deviceData.value.dataSetList, '8888888888838838838')
|
||||
console.log('_trenddata')
|
||||
let obj = {
|
||||
devId: deviceId.value, //e.id
|
||||
lineId: lineId.value, //e.pid
|
||||
type: 1,
|
||||
list: [
|
||||
{
|
||||
lineId: lineId.value,
|
||||
devId: dataSet.value.replace('_trenddata', '')
|
||||
}
|
||||
]
|
||||
}
|
||||
await getTabsDataByType(obj).then(res => {
|
||||
console.log(res, '0000000')
|
||||
})
|
||||
}
|
||||
//查询实时数据
|
||||
if (dataSet.value.indexOf('_realtimedata') != -1) {
|
||||
console.log('_realtimedata')
|
||||
//查询实时数据显示实时录波、实时趋势、谐波频谱
|
||||
realTimeFlag.value = true
|
||||
let obj = {
|
||||
type: 2,
|
||||
devId: deviceId.value, //e.id
|
||||
lineId: lineId.value //e.pid
|
||||
}
|
||||
intRealTime(obj)
|
||||
await setTimeout(() => {
|
||||
intRealTime(obj)
|
||||
}, 20000)
|
||||
}
|
||||
//查询暂态事件
|
||||
if (dataSet.value.indexOf('_event') != -1) {
|
||||
console.log('_event')
|
||||
} else {
|
||||
let obj = {
|
||||
devId: deviceId.value, //e.id
|
||||
lineId: lineId.value, //e.pid
|
||||
type: 3,
|
||||
list: [
|
||||
{
|
||||
lineId: lineId.value,
|
||||
devId: dataSet.value.replace('_event', '')
|
||||
}
|
||||
]
|
||||
}
|
||||
await getTabsDataByType(obj).then(res => {
|
||||
console.log(res, '0000000')
|
||||
})
|
||||
}
|
||||
//查询当前指标
|
||||
console.log(dataSet.value.indexOf('_'), '查询当前指标')
|
||||
if (dataSet.value.indexOf('_') == -1) {
|
||||
formInline.id = dataSet.value
|
||||
await deviceRtData(formInline).then((res: any) => {
|
||||
tableData.value = res.data.records
|
||||
@@ -373,6 +510,12 @@ const handleClick = async (tab?: any) => {
|
||||
}
|
||||
// }, 100)
|
||||
}
|
||||
|
||||
//离线数据导入
|
||||
const offLineDataImportRef = ref()
|
||||
const handleImport = () => {
|
||||
offLineDataImportRef.value && offLineDataImportRef.value.open()
|
||||
}
|
||||
queryByCode('Device_Type').then(res => {
|
||||
queryCsDictTree(res.data.id).then(res => {
|
||||
devTypeOptions.value = res.data.map((item: any) => {
|
||||
@@ -421,6 +564,14 @@ const openGroup = () => {
|
||||
})
|
||||
})
|
||||
}
|
||||
watch(
|
||||
() => dataSet.value,
|
||||
(val: any, oldVal: any) => {
|
||||
if (val) {
|
||||
handleClick()
|
||||
}
|
||||
}
|
||||
)
|
||||
onMounted(() => {
|
||||
connectWebSocket()
|
||||
})
|
||||
@@ -486,4 +637,12 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.view_top_btn {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
|
||||
231
src/views/govern/device/control/offLineDataImport/index.vue
Normal file
231
src/views/govern/device/control/offLineDataImport/index.vue
Normal file
@@ -0,0 +1,231 @@
|
||||
<!-- 离线数据导入 -->
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" title="文件列表" width="60%" draggable>
|
||||
<!-- 上传文件列表 -->
|
||||
<div class="offline_data">
|
||||
<div class="offline_data_btn">
|
||||
<el-button type="primary">开始上传</el-button>
|
||||
<el-button type="primary">清空文件</el-button>
|
||||
</div>
|
||||
<div class="offline_data_list">
|
||||
<!-- <el-upload
|
||||
ref="upload"
|
||||
accept=".zip,.rar,.7z"
|
||||
action="#"
|
||||
:auto-upload="false"
|
||||
:on-change="handleFileChange"
|
||||
> -->
|
||||
<!-- <el-button slot="trigger" size="small" type="primary">选择ZIP文件</el-button> -->
|
||||
<el-button
|
||||
:loading="loading"
|
||||
style="margin-left: 10px"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="submitUpload"
|
||||
>
|
||||
上传离线数据
|
||||
</el-button>
|
||||
<!-- </el-upload> -->
|
||||
<div v-if="zipFiles.length">
|
||||
<el-table :data="zipFiles" style="width: 100%" height="280">
|
||||
<el-table-column prop="name" label="文件名" align="left"></el-table-column>
|
||||
<el-table-column prop="status" label="状态" align="left"></el-table-column>
|
||||
<el-table-column label="操作" width="100" fixed="right" align="center">
|
||||
<template #default="{ row }">
|
||||
<!-- <el-button size="small" @click="previewFile(row)">预览</el-button> -->
|
||||
<el-button size="small" type="danger" text @click="removeFile(row)">移除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="close">取消</el-button>
|
||||
<!-- <el-button type="primary" @click="close">提交</el-button> -->
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import JSZip from 'jszip'
|
||||
import { saveAs } from 'file-saver'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
const dialogVisible = ref(false)
|
||||
const selectedFile = ref(null)
|
||||
|
||||
const loading = ref(false)
|
||||
const zipFiles: any = ref([])
|
||||
//上传zip
|
||||
const handleFileChange = (file: any, fileList: any) => {
|
||||
console.log(fileList, 'fileList555333222')
|
||||
loading.value = true
|
||||
JSZip.loadAsync(file.raw)
|
||||
.then(zip => {
|
||||
console.log(file.raw, '++++++++++++hahhahahabvggeiwtei哈哈')
|
||||
zipFiles.value = Object.keys(zip.files).map(name => ({ name }))
|
||||
// Object.keys(zip.files).map(entry => {
|
||||
// console.log(entry, 'entryentryentryentryentry')
|
||||
// // return zips.file(entry).then((blob: any) => {
|
||||
// // 创建File对象
|
||||
// return new File(['file'], entry)
|
||||
// // })
|
||||
// })
|
||||
// console.log(zip.files, 'zip.fileszip.fileszip.fileszip.files')
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('解压错误:', error)
|
||||
ElMessageBox.alert('解压错误: ' + error.message, '错误', { type: 'error' })
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
|
||||
const reader = new FileReader()
|
||||
|
||||
const zip = new JSZip()
|
||||
reader.onload = e => {
|
||||
console.log(e, '++++++++++++EEeeeEEEEEEEEE')
|
||||
// 加载压缩包内容
|
||||
zip.loadAsync(e.target.result).then(zip => {
|
||||
console.log(e.target.result, '??????????')
|
||||
// 获取压缩包内的文件
|
||||
const files = Object.values(zipFiles.value)
|
||||
.map((entry: any) => {
|
||||
if (!entry.dir && entry.name) {
|
||||
// 将压缩包内的文件转换为Blob对象
|
||||
return zip
|
||||
.file(entry.name)
|
||||
.async('blob')
|
||||
.then(blob => {
|
||||
// 创建File对象
|
||||
return new File([blob], entry.name)
|
||||
})
|
||||
}
|
||||
})
|
||||
.filter(Boolean) // 过滤掉文件夹和未定义的文件
|
||||
|
||||
Promise.all(files).then(allFiles => {
|
||||
// 这里你已经拿到了压缩包内所有文件的File对象数组
|
||||
console.log(allFiles)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 读取文件内容
|
||||
reader.readAsArrayBuffer(file.raw)
|
||||
}
|
||||
const uploadChange = e => {
|
||||
const formData = new FormData()
|
||||
const file = e.target['files']
|
||||
for (let i = 0; i < file.length; i++) {
|
||||
formData.append('files', file[i])
|
||||
console.log(file[i])
|
||||
console.log(file[i].webkitRelativePath)
|
||||
}
|
||||
console.log(formData.getAll('files'), '++++++++++++++++')
|
||||
}
|
||||
const upload = ref()
|
||||
const submitUpload = e => {
|
||||
e.preventDefault()
|
||||
// upload.value.submit()
|
||||
const input = document.createElement('input')
|
||||
// input["style"] = "background: rgba(255, 255, 255, 0);overflow: hidden;position: fixed;width: 1px;height: 1px;z-index: -1;opacity: 0;";
|
||||
input.type = 'file'
|
||||
input.setAttribute('allowdirs', 'true')
|
||||
input.setAttribute('directory', 'true')
|
||||
input.setAttribute('webkitdirectory', 'true')
|
||||
input.multiple = true
|
||||
document.querySelector('body').appendChild(input)
|
||||
// todo 这里增加了input标签,可以给它删掉
|
||||
|
||||
input.click()
|
||||
|
||||
// 覆盖原生的 alert 函数
|
||||
// window.alert = function (message) {
|
||||
// console.log(message) // 可以在这里处理消息或者什么都不做
|
||||
// }
|
||||
|
||||
// // 覆盖原生的 confirm 函数
|
||||
// window.confirm = function (message) {
|
||||
// console.log(message) // 可以在这里处理消息或者返回 true 或 false
|
||||
// return false // 始终返回 false 来模拟用户点击“取消”
|
||||
// }
|
||||
|
||||
// // 覆盖原生的 prompt 函数
|
||||
// window.prompt = function (message, defaultValue) {
|
||||
// console.log(message, defaultValue) // 可以在这里处理消息和默认值
|
||||
// return null // 始终返回 null 来模拟用户点击“取消”
|
||||
// }
|
||||
input.onclick = e => {
|
||||
e.preventDefault()
|
||||
}
|
||||
input.onchange = async function (e) {
|
||||
const formData = new FormData()
|
||||
e.preventDefault()
|
||||
const file = e.target['files']
|
||||
for (let i = 0; i < file.length; i++) {
|
||||
formData.append('files', file[i])
|
||||
console.log(file[i])
|
||||
console.log(file[i].webkitRelativePath)
|
||||
}
|
||||
console.log(formData.getAll('files'), '++++++++++++++++')
|
||||
}
|
||||
}
|
||||
|
||||
const previewFile = (file: any) => {
|
||||
// 这里可以实现文件预览逻辑,例如图片预览等
|
||||
console.log('预览文件:', file.name)
|
||||
}
|
||||
//移除文件
|
||||
const removeFile = async (file: any) => {
|
||||
console.log(file, '移除文件指令')
|
||||
const zip = new JSZip()
|
||||
// 假设有一个zip文件的ArrayBuffer数据
|
||||
const zipBuffer = file
|
||||
|
||||
// 加载ZIP文件
|
||||
// const jszip = await zip.loadAsync(zipBuffer)
|
||||
|
||||
// 删除指定文件
|
||||
// delete jszip.files[file.name]
|
||||
|
||||
// 生成新的ZIP文件
|
||||
const newZipContent = await zip.generateAsync({ type: 'arraybuffer', platform: 'DOS' })
|
||||
|
||||
// 处理新生成的ZIP文件,例如下载或者其他操作
|
||||
// ...
|
||||
// 使用FileSaver库保存新的ZIP文件
|
||||
saveAs(newZipContent, '5555.zip')
|
||||
}
|
||||
const open = () => {
|
||||
dialogVisible.value = true
|
||||
}
|
||||
const close = () => {
|
||||
dialogVisible.value = false
|
||||
}
|
||||
onMounted(() => {
|
||||
console.log()
|
||||
})
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.offline_data {
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
border: 2px solid red;
|
||||
.offline_data_btn {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.offline_data_list {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
23
src/views/govern/device/control/supplementaryRecruitment.vue
Normal file
23
src/views/govern/device/control/supplementaryRecruitment.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<el-tabs v-model="activeName" type="border-card">
|
||||
<el-tab-pane label="当前设备补招" name="0">
|
||||
<current v-if="activeName == '0'" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="历史设备补招" name="1">
|
||||
<history v-if="activeName == '1'" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
<script lang='ts' setup>
|
||||
import {ref,onMounted} from 'vue';
|
||||
import current from './supplementaryRecruitment/current.vue'
|
||||
import history from './supplementaryRecruitment/history.vue'
|
||||
const activeName=ref('0')
|
||||
onMounted(()=>{
|
||||
console.log()
|
||||
})
|
||||
</script>
|
||||
<style lang='scss' scoped>
|
||||
</style>
|
||||
@@ -0,0 +1,606 @@
|
||||
<!-- 当前设备补招 -->
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader>
|
||||
<template v-slot:select>
|
||||
<el-form-item label="设备类型">
|
||||
<!-- <el-input v-model="tableStore.table.params.searchValue" placeholder="请输入设备类型" /> -->
|
||||
<el-select
|
||||
v-model="tableStore.table.params.devType"
|
||||
clearable
|
||||
@change="devTypeChange"
|
||||
placeholder="请选择设备类型"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in devTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备型号">
|
||||
<el-select v-model="tableStore.table.params.devModel" clearable placeholder="请选择设备型号">
|
||||
<el-option
|
||||
v-for="item in devModelOptionsFilter"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="通讯协议">
|
||||
<el-select v-model="tableStore.table.params.devAccessMethod" clearable placeholder="请选择通讯协议">
|
||||
<el-option label="MQTT" value="mqtt"></el-option>
|
||||
<el-option label="CLD" value="cloud"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="tableStore.table.params.status" clearable placeholder="请选择状态">
|
||||
<el-option label="未注册" :value="1"></el-option>
|
||||
<el-option label="注册" :value="2"></el-option>
|
||||
<el-option label="接入" :value="3"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-slot:operation>
|
||||
<el-button type="primary" @click="downLoadFile" class="ml10" icon="el-icon-Download">
|
||||
模版下载
|
||||
</el-button>
|
||||
<el-upload
|
||||
style="display: inline-block"
|
||||
action=""
|
||||
accept=".xlsx"
|
||||
class="upload-demo"
|
||||
:show-file-list="false"
|
||||
:auto-upload="false"
|
||||
:on-change="bulkImport"
|
||||
>
|
||||
<el-button type="primary" class="ml10" icon="el-icon-Tickets">批量导入</el-button>
|
||||
</el-upload>
|
||||
<el-button type="primary" class="ml10" @click="add" icon="el-icon-Plus">新增设备</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef"></Table>
|
||||
|
||||
<el-dialog
|
||||
:title="dialogTitle"
|
||||
v-model="dialogFormVisible"
|
||||
:close-on-click-modal="false"
|
||||
:before-close="resetForm"
|
||||
draggable
|
||||
width="40%"
|
||||
>
|
||||
<el-form :model="form" label-width="120px" :rules="rules" ref="ruleFormRef">
|
||||
<el-form-item label="设备名称:" prop="name">
|
||||
<el-input
|
||||
v-model="form.name"
|
||||
autocomplete="off"
|
||||
clearable
|
||||
placeholder="请输入(项目名称+设备名称)"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="网络设备ID:" prop="ndid" class="top">
|
||||
<el-input v-model="form.ndid" autocomplete="off" placeholder="请输入"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备类型:" prop="devType" class="top">
|
||||
<el-select v-model="form.devType" placeholder="请选择" @change="formDevTypeChange" clearable>
|
||||
<el-option
|
||||
v-for="item in devTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备型号:" prop="devModel" class="top">
|
||||
<el-select v-model="form.devModel" placeholder="请选择" clearable>
|
||||
<el-option
|
||||
v-for="item in formDevModelOptionsFilter"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="通讯协议:" prop="devAccessMethod" class="top">
|
||||
<el-select v-model="form.devAccessMethod" placeholder="请选择" clearable>
|
||||
<el-option label="MQTT" value="MQTT"></el-option>
|
||||
<el-option label="CLD" value="cloud"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="合同号:" prop="cntractNo" class="top">
|
||||
<el-input v-model="form.cntractNo" autocomplete="off" placeholder="请输入"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="resetForm">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit">确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<div class="qrcode-label">
|
||||
<div class="qrcode-label-title">{{ deivce.mac }}</div>
|
||||
<img class="qrcode-label-img" alt="二维码加载失败" :src="deivce.qrPath" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide, computed, reactive, nextTick } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { queryByCode, queryByid, queryCsDictTree } from '@/api/system-boot/dictTree'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
addEquipmentDelivery,
|
||||
deleteEquipmentDelivery,
|
||||
editEquipmentDelivery,
|
||||
batchImportDevice,
|
||||
resetEquipmentDelivery,
|
||||
governDeviceRegister,
|
||||
portableDeviceRegister,
|
||||
portableDeviceAccess
|
||||
} from '@/api/cs-system-boot/device'
|
||||
import html2canvas from 'html2canvas'
|
||||
import { fullUrl } from '@/utils/common'
|
||||
|
||||
defineOptions({
|
||||
name: 'govern/log/debug'
|
||||
})
|
||||
|
||||
const devTypeOptions: any = ref([])
|
||||
const deivce: any = ref({})
|
||||
const ruleFormRef = ref()
|
||||
const form = reactive({
|
||||
cntractNo: '',
|
||||
devAccessMethod: 'mqtt',
|
||||
devModel: '',
|
||||
devType: '',
|
||||
name: '',
|
||||
ndid: ''
|
||||
})
|
||||
const rules = reactive({
|
||||
name: [{ required: true, message: '设备名不能为空', trigger: 'blur' }],
|
||||
ndid: [{ required: true, message: '网络设备id不能为空', trigger: 'blur' }],
|
||||
devType: [{ required: true, message: '设备类型不能为空', trigger: 'change' }],
|
||||
devModel: [{ required: true, message: '设备型号不能为空', trigger: 'change' }],
|
||||
devAccessMethod: [{ required: true, message: '接入方式不能为空', trigger: 'blur' }],
|
||||
cntractNo: [{ required: true, message: '合同号不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const dialogFormVisible = ref(false)
|
||||
const dialogTitle = ref('新增设备')
|
||||
|
||||
const devModelOptions: any = ref([])
|
||||
queryByCode('Device_Type').then(res => {
|
||||
queryCsDictTree(res.data.id).then(res => {
|
||||
devTypeOptions.value = res.data.map((item: any) => {
|
||||
return {
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
...item
|
||||
}
|
||||
})
|
||||
})
|
||||
queryByid(res.data.id).then(res => {
|
||||
devModelOptions.value = res.data.map((item: any) => {
|
||||
return {
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
...item
|
||||
}
|
||||
})
|
||||
})
|
||||
tableStore.index()
|
||||
})
|
||||
const devModelOptionsFilter = computed(() => {
|
||||
return devModelOptions.value.filter((item: any) => {
|
||||
if (tableStore.table.params.devType) {
|
||||
return item.pid == tableStore.table.params.devType
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
})
|
||||
})
|
||||
const formDevModelOptionsFilter = computed(() => {
|
||||
return devModelOptions.value.filter((item: any) => {
|
||||
if (form.devType) {
|
||||
return item.pid == form.devType
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
})
|
||||
})
|
||||
const tableStore = new TableStore({
|
||||
url: '/cs-device-boot/EquipmentDelivery/list',
|
||||
method: 'POST',
|
||||
column: [
|
||||
{ title: '序号', type: 'seq',width:60 },
|
||||
{ title: '设备名称', field: 'name' },
|
||||
{
|
||||
title: '设备类型',
|
||||
field: 'devType',
|
||||
formatter: row => {
|
||||
return devTypeOptions.value.filter((item: any) => item.value == row.cellValue)[0]?.label
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '设备型号',
|
||||
field: 'devModel',
|
||||
formatter: row => {
|
||||
return devModelOptions.value.filter((item: any) => item.value == row.cellValue)[0]?.label
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '通讯协议',
|
||||
field: 'devAccessMethod',
|
||||
formatter: row => {
|
||||
return row.cellValue === 'MQTT' ? 'MQTT' : row.cellValue === 'cloud' ? 'CLD' : row.cellValue
|
||||
}
|
||||
},
|
||||
{ title: '录入时间', field: 'createTime' },
|
||||
{ title: '网络设备ID', field: 'ndid' },
|
||||
{
|
||||
title: '状态',
|
||||
field: 'status',
|
||||
width: 100,
|
||||
render: 'tag',
|
||||
custom: {
|
||||
1: 'warning',
|
||||
2: 'success',
|
||||
3: 'primary',
|
||||
4: 'primary',
|
||||
5: 'warning'
|
||||
},
|
||||
replaceValue: {
|
||||
1: '未注册',
|
||||
2: '注册',
|
||||
3: '接入',
|
||||
4: '已取消',
|
||||
5: '未接入'
|
||||
}
|
||||
// formatter: row => {
|
||||
// return row.cellValue == 1 ? '未注册' : row.cellValue == 2 ? '注册' : '接入'
|
||||
// },
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
width: '180',
|
||||
render: 'buttons',
|
||||
buttons: [
|
||||
//直连装置注册
|
||||
{
|
||||
title: '注册',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-Grid',
|
||||
render: 'basicButton',
|
||||
disabled: row => {
|
||||
return (
|
||||
(row.devType == '8b45cf6b7f5266e777d07c166ad5fa77' &&
|
||||
row.devModel == 'a0d4da4b5c17b2172362a3f5a27bf217') ||
|
||||
row.status != '1'
|
||||
)
|
||||
},
|
||||
click: row => {
|
||||
// 直连设备注册
|
||||
ElMessageBox.confirm('确定注册该设备吗?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
governDeviceRegister({
|
||||
nDid: row.ndid,
|
||||
type: '4'
|
||||
}).then(res => {
|
||||
ElMessage.success(res.message)
|
||||
tableStore.onTableAction('search', {})
|
||||
})
|
||||
})
|
||||
.catch(e => {})
|
||||
}
|
||||
},
|
||||
//便携式设备注册
|
||||
{
|
||||
title: '注册',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-Grid',
|
||||
render: 'basicButton',
|
||||
disabled: row => {
|
||||
// return (
|
||||
// (row.devType != '8b45cf6b7f5266e777d07c166ad5fa77' &&
|
||||
// row.devModel != 'a0d4da4b5c17b2172362a3f5a27bf217') ||
|
||||
// row.status != '1'
|
||||
// )
|
||||
return true
|
||||
},
|
||||
click: row => {
|
||||
// 便携式设备注册
|
||||
ElMessageBox.confirm('确定注册该设备吗?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
portableDeviceRegister({
|
||||
nDid: row.ndid
|
||||
}).then(res => {
|
||||
console.log(res, '8888')
|
||||
ElMessage.success(res.message)
|
||||
tableStore.index()
|
||||
})
|
||||
})
|
||||
.catch(e => {})
|
||||
}
|
||||
},
|
||||
//直连设备接入
|
||||
{
|
||||
title: '接入',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-Grid',
|
||||
render: 'basicButton',
|
||||
disabled: row => {
|
||||
return (
|
||||
(row.devType == '8b45cf6b7f5266e777d07c166ad5fa77' &&
|
||||
row.devModel == 'a0d4da4b5c17b2172362a3f5a27bf217') ||
|
||||
row.status != '2'
|
||||
)
|
||||
},
|
||||
click: row => {
|
||||
// 直连设备接入
|
||||
ElMessageBox.confirm('确定接入该设备吗?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
governDeviceRegister({
|
||||
nDid: row.ndid,
|
||||
type: '4'
|
||||
}).then(res => {
|
||||
ElMessage.success(res.message)
|
||||
tableStore.onTableAction('search', {})
|
||||
})
|
||||
})
|
||||
.catch(e => {})
|
||||
}
|
||||
},
|
||||
//便携式设备接入
|
||||
{
|
||||
title: '接入',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-Grid',
|
||||
render: 'basicButton',
|
||||
disabled: row => {
|
||||
return (
|
||||
(row.devType != '8b45cf6b7f5266e777d07c166ad5fa77' &&
|
||||
row.devModel != 'a0d4da4b5c17b2172362a3f5a27bf217') ||
|
||||
row.status == '3'
|
||||
)
|
||||
},
|
||||
click: row => {
|
||||
// 便携式设备接入
|
||||
ElMessageBox.confirm('确定接入该设备吗?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
portableDeviceAccess({
|
||||
nDid: row.ndid
|
||||
}).then(res => {
|
||||
ElMessage.success(res.message)
|
||||
tableStore.index()
|
||||
})
|
||||
})
|
||||
.catch(e => {})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '二维码',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-Grid',
|
||||
render: 'basicButton',
|
||||
disabled: row => {
|
||||
return (
|
||||
row.devType == '8b45cf6b7f5266e777d07c166ad5fa77' &&
|
||||
row.devModel == 'a0d4da4b5c17b2172362a3f5a27bf217'
|
||||
)
|
||||
},
|
||||
click: row => {
|
||||
deivce.value = row
|
||||
deivce.value.qrPath = fullUrl(deivce.value.qrPath)
|
||||
setTimeout(() => {
|
||||
html2canvas(document.querySelector('.qrcode-label'), {
|
||||
useCORS: true
|
||||
}).then(canvas => {
|
||||
let url = canvas.toDataURL('image/png')
|
||||
// 下载图片
|
||||
let a = document.createElement('a')
|
||||
let event = new MouseEvent('click')
|
||||
a.href = url
|
||||
a.download = row.mac + '.png'
|
||||
a.dispatchEvent(event)
|
||||
})
|
||||
}, 0)
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
title: '编辑',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-EditPen',
|
||||
render: 'basicButton',
|
||||
|
||||
click: async row => {
|
||||
dialogFormVisible.value = true
|
||||
dialogTitle.value = '编辑设备'
|
||||
for (let key in form) {
|
||||
form[key] = row[key]
|
||||
}
|
||||
form.id = row.id
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'del',
|
||||
title: '删除',
|
||||
type: 'danger',
|
||||
icon: 'el-icon-Delete',
|
||||
render: 'basicButton',
|
||||
click: row => {
|
||||
ElMessageBox.confirm('确定删除该设备吗?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
deleteEquipmentDelivery(row.id).then(res => {
|
||||
ElMessage.success('删除成功!')
|
||||
tableStore.onTableAction('search', {})
|
||||
})
|
||||
})
|
||||
.catch(e => {})
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
beforeSearchFun: () => {
|
||||
for (let key in tableStore.table.params) {
|
||||
if (tableStore.table.params[key] === '') {
|
||||
delete tableStore.table.params[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
tableStore.table.params.orderBy = 'desc'
|
||||
|
||||
// 设备类型
|
||||
const devTypeChange = (e: any) => {
|
||||
if (!e) {
|
||||
return
|
||||
}
|
||||
tableStore.table.params.devModel = ''
|
||||
}
|
||||
// 下载模版
|
||||
const downLoadFile = () => {
|
||||
window.open(window.location.origin + '/api/cs-device-boot/EquipmentDelivery/getExcelTemplate')
|
||||
}
|
||||
|
||||
// 导入模版
|
||||
const bulkImport = (e: any) => {
|
||||
batchImportDevice(e.raw).then((res: any) => {
|
||||
if (res.type === 'application/json') {
|
||||
const reader = new FileReader()
|
||||
reader.readAsText(res)
|
||||
reader.onload = (e: any) => {
|
||||
let data = JSON.parse(e.target.result)
|
||||
if (data.code === 'A0000') {
|
||||
ElMessage.success(data.message)
|
||||
tableStore.onTableAction('search', {})
|
||||
} else {
|
||||
ElMessage.error(data.message)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ElMessage.error('导入失败!')
|
||||
let url = window.URL.createObjectURL(res)
|
||||
let link = document.createElement('a')
|
||||
link.style.display = 'none'
|
||||
link.href = url
|
||||
link.setAttribute('download', '导入失败.xlsx')
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
}
|
||||
})
|
||||
}
|
||||
// 新增
|
||||
const add = () => {
|
||||
dialogFormVisible.value = true
|
||||
dialogTitle.value = '新增设备'
|
||||
}
|
||||
|
||||
// 确认
|
||||
const onSubmit = () => {
|
||||
ruleFormRef.value.validate((valid: any) => {
|
||||
if (valid) {
|
||||
if (dialogTitle.value == '新增设备') {
|
||||
addEquipmentDelivery(form).then(res => {
|
||||
ElMessage.success('新增成功')
|
||||
resetForm()
|
||||
tableStore.onTableAction('search', {})
|
||||
})
|
||||
} else {
|
||||
editEquipmentDelivery(form).then(res => {
|
||||
ElMessage.success('修改成功')
|
||||
resetForm()
|
||||
tableStore.onTableAction('search', {})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// 清空表格
|
||||
const resetForm = () => {
|
||||
ruleFormRef.value.resetFields()
|
||||
dialogFormVisible.value = false
|
||||
nextTick(() => {
|
||||
// 模拟待编辑数据
|
||||
let user = {
|
||||
cntractNo: '',
|
||||
devAccessMethod: 'mqtt',
|
||||
devModel: '',
|
||||
devType: '',
|
||||
name: '',
|
||||
ndid: ''
|
||||
}
|
||||
Object.assign(form, user)
|
||||
})
|
||||
}
|
||||
|
||||
const formDevTypeChange = (e: any) => {
|
||||
if (!e) {
|
||||
return
|
||||
}
|
||||
form.devModel = ''
|
||||
}
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
// tableStore.index()
|
||||
}, 100)
|
||||
})
|
||||
|
||||
const addMenu = () => {}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.qrcode-label {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: -99;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
padding: 10px;
|
||||
background: #fff;
|
||||
flex-direction: column;
|
||||
|
||||
.qrcode-label-title {
|
||||
margin-bottom: 10px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.qrcode-label-img {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,606 @@
|
||||
<!-- 历史数据补招 -->
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<TableHeader>
|
||||
<template v-slot:select>
|
||||
<el-form-item label="设备类型">
|
||||
<!-- <el-input v-model="tableStore.table.params.searchValue" placeholder="请输入设备类型" /> -->
|
||||
<el-select
|
||||
v-model="tableStore.table.params.devType"
|
||||
clearable
|
||||
@change="devTypeChange"
|
||||
placeholder="请选择设备类型"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in devTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备型号">
|
||||
<el-select v-model="tableStore.table.params.devModel" clearable placeholder="请选择设备型号">
|
||||
<el-option
|
||||
v-for="item in devModelOptionsFilter"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="通讯协议">
|
||||
<el-select v-model="tableStore.table.params.devAccessMethod" clearable placeholder="请选择通讯协议">
|
||||
<el-option label="MQTT" value="mqtt"></el-option>
|
||||
<el-option label="CLD" value="cloud"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="tableStore.table.params.status" clearable placeholder="请选择状态">
|
||||
<el-option label="未注册" :value="1"></el-option>
|
||||
<el-option label="注册" :value="2"></el-option>
|
||||
<el-option label="接入" :value="3"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-slot:operation>
|
||||
<el-button type="primary" @click="downLoadFile" class="ml10" icon="el-icon-Download">
|
||||
模版下载
|
||||
</el-button>
|
||||
<el-upload
|
||||
style="display: inline-block"
|
||||
action=""
|
||||
accept=".xlsx"
|
||||
class="upload-demo"
|
||||
:show-file-list="false"
|
||||
:auto-upload="false"
|
||||
:on-change="bulkImport"
|
||||
>
|
||||
<el-button type="primary" class="ml10" icon="el-icon-Tickets">批量导入</el-button>
|
||||
</el-upload>
|
||||
<el-button type="primary" class="ml10" @click="add" icon="el-icon-Plus">新增设备</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef"></Table>
|
||||
|
||||
<el-dialog
|
||||
:title="dialogTitle"
|
||||
v-model="dialogFormVisible"
|
||||
:close-on-click-modal="false"
|
||||
:before-close="resetForm"
|
||||
draggable
|
||||
width="40%"
|
||||
>
|
||||
<el-form :model="form" label-width="120px" :rules="rules" ref="ruleFormRef">
|
||||
<el-form-item label="设备名称:" prop="name">
|
||||
<el-input
|
||||
v-model="form.name"
|
||||
autocomplete="off"
|
||||
clearable
|
||||
placeholder="请输入(项目名称+设备名称)"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="网络设备ID:" prop="ndid" class="top">
|
||||
<el-input v-model="form.ndid" autocomplete="off" placeholder="请输入"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备类型:" prop="devType" class="top">
|
||||
<el-select v-model="form.devType" placeholder="请选择" @change="formDevTypeChange" clearable>
|
||||
<el-option
|
||||
v-for="item in devTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备型号:" prop="devModel" class="top">
|
||||
<el-select v-model="form.devModel" placeholder="请选择" clearable>
|
||||
<el-option
|
||||
v-for="item in formDevModelOptionsFilter"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="通讯协议:" prop="devAccessMethod" class="top">
|
||||
<el-select v-model="form.devAccessMethod" placeholder="请选择" clearable>
|
||||
<el-option label="MQTT" value="MQTT"></el-option>
|
||||
<el-option label="CLD" value="cloud"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="合同号:" prop="cntractNo" class="top">
|
||||
<el-input v-model="form.cntractNo" autocomplete="off" placeholder="请输入"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="resetForm">取 消</el-button>
|
||||
<el-button type="primary" @click="onSubmit">确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<div class="qrcode-label">
|
||||
<div class="qrcode-label-title">{{ deivce.mac }}</div>
|
||||
<img class="qrcode-label-img" alt="二维码加载失败" :src="deivce.qrPath" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide, computed, reactive, nextTick } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { queryByCode, queryByid, queryCsDictTree } from '@/api/system-boot/dictTree'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
addEquipmentDelivery,
|
||||
deleteEquipmentDelivery,
|
||||
editEquipmentDelivery,
|
||||
batchImportDevice,
|
||||
resetEquipmentDelivery,
|
||||
governDeviceRegister,
|
||||
portableDeviceRegister,
|
||||
portableDeviceAccess
|
||||
} from '@/api/cs-system-boot/device'
|
||||
import html2canvas from 'html2canvas'
|
||||
import { fullUrl } from '@/utils/common'
|
||||
|
||||
defineOptions({
|
||||
name: 'govern/log/debug'
|
||||
})
|
||||
|
||||
const devTypeOptions: any = ref([])
|
||||
const deivce: any = ref({})
|
||||
const ruleFormRef = ref()
|
||||
const form = reactive({
|
||||
cntractNo: '',
|
||||
devAccessMethod: 'mqtt',
|
||||
devModel: '',
|
||||
devType: '',
|
||||
name: '',
|
||||
ndid: ''
|
||||
})
|
||||
const rules = reactive({
|
||||
name: [{ required: true, message: '设备名不能为空', trigger: 'blur' }],
|
||||
ndid: [{ required: true, message: '网络设备id不能为空', trigger: 'blur' }],
|
||||
devType: [{ required: true, message: '设备类型不能为空', trigger: 'change' }],
|
||||
devModel: [{ required: true, message: '设备型号不能为空', trigger: 'change' }],
|
||||
devAccessMethod: [{ required: true, message: '接入方式不能为空', trigger: 'blur' }],
|
||||
cntractNo: [{ required: true, message: '合同号不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const dialogFormVisible = ref(false)
|
||||
const dialogTitle = ref('新增设备')
|
||||
|
||||
const devModelOptions: any = ref([])
|
||||
queryByCode('Device_Type').then(res => {
|
||||
queryCsDictTree(res.data.id).then(res => {
|
||||
devTypeOptions.value = res.data.map((item: any) => {
|
||||
return {
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
...item
|
||||
}
|
||||
})
|
||||
})
|
||||
queryByid(res.data.id).then(res => {
|
||||
devModelOptions.value = res.data.map((item: any) => {
|
||||
return {
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
...item
|
||||
}
|
||||
})
|
||||
})
|
||||
tableStore.index()
|
||||
})
|
||||
const devModelOptionsFilter = computed(() => {
|
||||
return devModelOptions.value.filter((item: any) => {
|
||||
if (tableStore.table.params.devType) {
|
||||
return item.pid == tableStore.table.params.devType
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
})
|
||||
})
|
||||
const formDevModelOptionsFilter = computed(() => {
|
||||
return devModelOptions.value.filter((item: any) => {
|
||||
if (form.devType) {
|
||||
return item.pid == form.devType
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
})
|
||||
})
|
||||
const tableStore = new TableStore({
|
||||
url: '/cs-device-boot/EquipmentDelivery/list',
|
||||
method: 'POST',
|
||||
column: [
|
||||
{ title: '序号', type: 'seq',width:60 },
|
||||
{ title: '设备名称', field: 'name' },
|
||||
{
|
||||
title: '设备类型',
|
||||
field: 'devType',
|
||||
formatter: row => {
|
||||
return devTypeOptions.value.filter((item: any) => item.value == row.cellValue)[0]?.label
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '设备型号',
|
||||
field: 'devModel',
|
||||
formatter: row => {
|
||||
return devModelOptions.value.filter((item: any) => item.value == row.cellValue)[0]?.label
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '通讯协议',
|
||||
field: 'devAccessMethod',
|
||||
formatter: row => {
|
||||
return row.cellValue === 'MQTT' ? 'MQTT' : row.cellValue === 'cloud' ? 'CLD' : row.cellValue
|
||||
}
|
||||
},
|
||||
{ title: '录入时间', field: 'createTime' },
|
||||
{ title: '网络设备ID', field: 'ndid' },
|
||||
{
|
||||
title: '状态',
|
||||
field: 'status',
|
||||
width: 100,
|
||||
render: 'tag',
|
||||
custom: {
|
||||
1: 'warning',
|
||||
2: 'success',
|
||||
3: 'primary',
|
||||
4: 'primary',
|
||||
5: 'warning'
|
||||
},
|
||||
replaceValue: {
|
||||
1: '未注册',
|
||||
2: '注册',
|
||||
3: '接入',
|
||||
4: '已取消',
|
||||
5: '未接入'
|
||||
}
|
||||
// formatter: row => {
|
||||
// return row.cellValue == 1 ? '未注册' : row.cellValue == 2 ? '注册' : '接入'
|
||||
// },
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
width: '180',
|
||||
render: 'buttons',
|
||||
buttons: [
|
||||
//直连装置注册
|
||||
{
|
||||
title: '注册',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-Grid',
|
||||
render: 'basicButton',
|
||||
disabled: row => {
|
||||
return (
|
||||
(row.devType == '8b45cf6b7f5266e777d07c166ad5fa77' &&
|
||||
row.devModel == 'a0d4da4b5c17b2172362a3f5a27bf217') ||
|
||||
row.status != '1'
|
||||
)
|
||||
},
|
||||
click: row => {
|
||||
// 直连设备注册
|
||||
ElMessageBox.confirm('确定注册该设备吗?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
governDeviceRegister({
|
||||
nDid: row.ndid,
|
||||
type: '4'
|
||||
}).then(res => {
|
||||
ElMessage.success(res.message)
|
||||
tableStore.onTableAction('search', {})
|
||||
})
|
||||
})
|
||||
.catch(e => {})
|
||||
}
|
||||
},
|
||||
//便携式设备注册
|
||||
{
|
||||
title: '注册',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-Grid',
|
||||
render: 'basicButton',
|
||||
disabled: row => {
|
||||
// return (
|
||||
// (row.devType != '8b45cf6b7f5266e777d07c166ad5fa77' &&
|
||||
// row.devModel != 'a0d4da4b5c17b2172362a3f5a27bf217') ||
|
||||
// row.status != '1'
|
||||
// )
|
||||
return true
|
||||
},
|
||||
click: row => {
|
||||
// 便携式设备注册
|
||||
ElMessageBox.confirm('确定注册该设备吗?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
portableDeviceRegister({
|
||||
nDid: row.ndid
|
||||
}).then(res => {
|
||||
console.log(res, '8888')
|
||||
ElMessage.success(res.message)
|
||||
tableStore.index()
|
||||
})
|
||||
})
|
||||
.catch(e => {})
|
||||
}
|
||||
},
|
||||
//直连设备接入
|
||||
{
|
||||
title: '接入',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-Grid',
|
||||
render: 'basicButton',
|
||||
disabled: row => {
|
||||
return (
|
||||
(row.devType == '8b45cf6b7f5266e777d07c166ad5fa77' &&
|
||||
row.devModel == 'a0d4da4b5c17b2172362a3f5a27bf217') ||
|
||||
row.status != '2'
|
||||
)
|
||||
},
|
||||
click: row => {
|
||||
// 直连设备接入
|
||||
ElMessageBox.confirm('确定接入该设备吗?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
governDeviceRegister({
|
||||
nDid: row.ndid,
|
||||
type: '4'
|
||||
}).then(res => {
|
||||
ElMessage.success(res.message)
|
||||
tableStore.onTableAction('search', {})
|
||||
})
|
||||
})
|
||||
.catch(e => {})
|
||||
}
|
||||
},
|
||||
//便携式设备接入
|
||||
{
|
||||
title: '接入',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-Grid',
|
||||
render: 'basicButton',
|
||||
disabled: row => {
|
||||
return (
|
||||
(row.devType != '8b45cf6b7f5266e777d07c166ad5fa77' &&
|
||||
row.devModel != 'a0d4da4b5c17b2172362a3f5a27bf217') ||
|
||||
row.status == '3'
|
||||
)
|
||||
},
|
||||
click: row => {
|
||||
// 便携式设备接入
|
||||
ElMessageBox.confirm('确定接入该设备吗?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
portableDeviceAccess({
|
||||
nDid: row.ndid
|
||||
}).then(res => {
|
||||
ElMessage.success(res.message)
|
||||
tableStore.index()
|
||||
})
|
||||
})
|
||||
.catch(e => {})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '二维码',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-Grid',
|
||||
render: 'basicButton',
|
||||
disabled: row => {
|
||||
return (
|
||||
row.devType == '8b45cf6b7f5266e777d07c166ad5fa77' &&
|
||||
row.devModel == 'a0d4da4b5c17b2172362a3f5a27bf217'
|
||||
)
|
||||
},
|
||||
click: row => {
|
||||
deivce.value = row
|
||||
deivce.value.qrPath = fullUrl(deivce.value.qrPath)
|
||||
setTimeout(() => {
|
||||
html2canvas(document.querySelector('.qrcode-label'), {
|
||||
useCORS: true
|
||||
}).then(canvas => {
|
||||
let url = canvas.toDataURL('image/png')
|
||||
// 下载图片
|
||||
let a = document.createElement('a')
|
||||
let event = new MouseEvent('click')
|
||||
a.href = url
|
||||
a.download = row.mac + '.png'
|
||||
a.dispatchEvent(event)
|
||||
})
|
||||
}, 0)
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
title: '编辑',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-EditPen',
|
||||
render: 'basicButton',
|
||||
|
||||
click: async row => {
|
||||
dialogFormVisible.value = true
|
||||
dialogTitle.value = '编辑设备'
|
||||
for (let key in form) {
|
||||
form[key] = row[key]
|
||||
}
|
||||
form.id = row.id
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'del',
|
||||
title: '删除',
|
||||
type: 'danger',
|
||||
icon: 'el-icon-Delete',
|
||||
render: 'basicButton',
|
||||
click: row => {
|
||||
ElMessageBox.confirm('确定删除该设备吗?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
deleteEquipmentDelivery(row.id).then(res => {
|
||||
ElMessage.success('删除成功!')
|
||||
tableStore.onTableAction('search', {})
|
||||
})
|
||||
})
|
||||
.catch(e => {})
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
beforeSearchFun: () => {
|
||||
for (let key in tableStore.table.params) {
|
||||
if (tableStore.table.params[key] === '') {
|
||||
delete tableStore.table.params[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
tableStore.table.params.orderBy = 'desc'
|
||||
|
||||
// 设备类型
|
||||
const devTypeChange = (e: any) => {
|
||||
if (!e) {
|
||||
return
|
||||
}
|
||||
tableStore.table.params.devModel = ''
|
||||
}
|
||||
// 下载模版
|
||||
const downLoadFile = () => {
|
||||
window.open(window.location.origin + '/api/cs-device-boot/EquipmentDelivery/getExcelTemplate')
|
||||
}
|
||||
|
||||
// 导入模版
|
||||
const bulkImport = (e: any) => {
|
||||
batchImportDevice(e.raw).then((res: any) => {
|
||||
if (res.type === 'application/json') {
|
||||
const reader = new FileReader()
|
||||
reader.readAsText(res)
|
||||
reader.onload = (e: any) => {
|
||||
let data = JSON.parse(e.target.result)
|
||||
if (data.code === 'A0000') {
|
||||
ElMessage.success(data.message)
|
||||
tableStore.onTableAction('search', {})
|
||||
} else {
|
||||
ElMessage.error(data.message)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ElMessage.error('导入失败!')
|
||||
let url = window.URL.createObjectURL(res)
|
||||
let link = document.createElement('a')
|
||||
link.style.display = 'none'
|
||||
link.href = url
|
||||
link.setAttribute('download', '导入失败.xlsx')
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
}
|
||||
})
|
||||
}
|
||||
// 新增
|
||||
const add = () => {
|
||||
dialogFormVisible.value = true
|
||||
dialogTitle.value = '新增设备'
|
||||
}
|
||||
|
||||
// 确认
|
||||
const onSubmit = () => {
|
||||
ruleFormRef.value.validate((valid: any) => {
|
||||
if (valid) {
|
||||
if (dialogTitle.value == '新增设备') {
|
||||
addEquipmentDelivery(form).then(res => {
|
||||
ElMessage.success('新增成功')
|
||||
resetForm()
|
||||
tableStore.onTableAction('search', {})
|
||||
})
|
||||
} else {
|
||||
editEquipmentDelivery(form).then(res => {
|
||||
ElMessage.success('修改成功')
|
||||
resetForm()
|
||||
tableStore.onTableAction('search', {})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// 清空表格
|
||||
const resetForm = () => {
|
||||
ruleFormRef.value.resetFields()
|
||||
dialogFormVisible.value = false
|
||||
nextTick(() => {
|
||||
// 模拟待编辑数据
|
||||
let user = {
|
||||
cntractNo: '',
|
||||
devAccessMethod: 'mqtt',
|
||||
devModel: '',
|
||||
devType: '',
|
||||
name: '',
|
||||
ndid: ''
|
||||
}
|
||||
Object.assign(form, user)
|
||||
})
|
||||
}
|
||||
|
||||
const formDevTypeChange = (e: any) => {
|
||||
if (!e) {
|
||||
return
|
||||
}
|
||||
form.devModel = ''
|
||||
}
|
||||
provide('tableStore', tableStore)
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
// tableStore.index()
|
||||
}, 100)
|
||||
})
|
||||
|
||||
const addMenu = () => {}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.qrcode-label {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: -99;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
padding: 10px;
|
||||
background: #fff;
|
||||
flex-direction: column;
|
||||
|
||||
.qrcode-label-title {
|
||||
margin-bottom: 10px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.qrcode-label-img {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<div class="harmonic">
|
||||
谐波频谱
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
onMounted(() => {
|
||||
console.log()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.harmonic{
|
||||
width:100%;
|
||||
height:100%;
|
||||
border: 2px solid green;
|
||||
}
|
||||
</style>
|
||||
643
src/views/govern/device/control/tabs/components/realtrend.vue
Normal file
643
src/views/govern/device/control/tabs/components/realtrend.vue
Normal file
@@ -0,0 +1,643 @@
|
||||
<template>
|
||||
<div class="realtrend">
|
||||
<el-tabs type="border-card" v-model="activeName" @tab-click="handleClick">
|
||||
<el-tab-pane label="谐波电压含有率" name="0">
|
||||
<template #label>
|
||||
<span class="custom-tabs-label">
|
||||
<el-icon><TrendCharts /></el-icon>
|
||||
谐波电压含有率
|
||||
</span>
|
||||
</template>
|
||||
<div class="tab_info">
|
||||
<vxe-grid v-if="activeName == '0'" class="reverse-table" v-bind="gridOptions"></vxe-grid>
|
||||
<div class="charts">
|
||||
<MyEchart ref="barCharts1" :options="echartsData1"></MyEchart>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="间谐波电压含有率" name="1">
|
||||
<template #label>
|
||||
<span class="custom-tabs-label">
|
||||
<el-icon><TrendCharts /></el-icon>
|
||||
间谐波电压含有率
|
||||
</span>
|
||||
</template>
|
||||
<div class="tab_info">
|
||||
<vxe-grid v-if="activeName == '1'" class="reverse-table" v-bind="gridOptions"></vxe-grid>
|
||||
<div class="charts">
|
||||
<MyEchart ref="barCharts2" :options="echartsData2"></MyEchart>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="谐波电流幅值" name="2">
|
||||
<template #label>
|
||||
<span class="custom-tabs-label">
|
||||
<el-icon><DataLine /></el-icon>
|
||||
谐波电流幅值
|
||||
</span>
|
||||
</template>
|
||||
<div class="tab_info">
|
||||
<vxe-grid v-if="activeName == '2'" class="reverse-table" v-bind="gridOptions"></vxe-grid>
|
||||
<div class="charts">
|
||||
<MyEchart ref="barCharts3" :options="echartsData3"></MyEchart>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, reactive } from 'vue'
|
||||
import { VxeGridProps, VxeGridPropTypes } from 'vxe-table'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { Platform, TrendCharts, DataLine } from '@element-plus/icons-vue'
|
||||
const activeName = ref('0')
|
||||
const tableList = [
|
||||
{
|
||||
name: '2次',
|
||||
value: Math.floor(Math.random() * 101)
|
||||
},
|
||||
{
|
||||
name: '3次',
|
||||
value: Math.floor(Math.random() * 101)
|
||||
},
|
||||
{
|
||||
name: '4次',
|
||||
value: Math.floor(Math.random() * 101)
|
||||
},
|
||||
{
|
||||
name: '5次',
|
||||
value: Math.floor(Math.random() * 101)
|
||||
},
|
||||
{
|
||||
name: '6次',
|
||||
value: Math.floor(Math.random() * 101)
|
||||
},
|
||||
{
|
||||
name: '7次',
|
||||
value: Math.floor(Math.random() * 101)
|
||||
},
|
||||
{
|
||||
name: '8次',
|
||||
value: Math.floor(Math.random() * 101)
|
||||
},
|
||||
{
|
||||
name: '9次',
|
||||
value: Math.floor(Math.random() * 101)
|
||||
},
|
||||
{
|
||||
name: '10次',
|
||||
value: Math.floor(Math.random() * 101)
|
||||
},
|
||||
{
|
||||
name: '11次',
|
||||
value: Math.floor(Math.random() * 101)
|
||||
},
|
||||
{
|
||||
name: '12次',
|
||||
value: Math.floor(Math.random() * 101)
|
||||
},
|
||||
{
|
||||
name: '13次',
|
||||
value: Math.floor(Math.random() * 101)
|
||||
},
|
||||
{
|
||||
name: '14次',
|
||||
value: Math.floor(Math.random() * 101)
|
||||
},
|
||||
{
|
||||
name: '15次',
|
||||
value: Math.floor(Math.random() * 101)
|
||||
},
|
||||
{
|
||||
name: '16次',
|
||||
value: Math.floor(Math.random() * 101)
|
||||
}
|
||||
]
|
||||
interface RowVO {
|
||||
[key: string]: any
|
||||
}
|
||||
//谐波电压含有率
|
||||
const gridOptions = ref<VxeGridProps<RowVO>>({
|
||||
border: true,
|
||||
showOverflow: true,
|
||||
showHeader: false,
|
||||
columns: [],
|
||||
data: [],
|
||||
columnConfig: {
|
||||
resizable: true
|
||||
},
|
||||
align: 'center'
|
||||
})
|
||||
gridOptions.value = { ...defaultAttribute, ...gridOptions.value }
|
||||
const myColumns = ref([
|
||||
{ field: 'name', title: '次数' },
|
||||
{ field: 'value', title: '谐波电压含有率(%)' }
|
||||
])
|
||||
const yAxisUnit: any = ref('')
|
||||
myColumns.value.map(item => {
|
||||
if (item.field == 'value') {
|
||||
item.title =
|
||||
activeName.value == '0'
|
||||
? '谐波电压含有率(%)'
|
||||
: activeName.value == '1'
|
||||
? '间谐波电压含有率(%)'
|
||||
: activeName.value == '2'
|
||||
? '谐波电流幅值(A)'
|
||||
: ''
|
||||
yAxisUnit.value = item.title.split('(')[0]
|
||||
}
|
||||
})
|
||||
|
||||
const myData = tableList
|
||||
|
||||
//反转表格
|
||||
const reverseTable = () => {
|
||||
const buildData = myColumns.value.map(column => {
|
||||
const item: any = { col0: column.title }
|
||||
myData.forEach((row, index) => {
|
||||
item[`col${index + 1}`] = row[column.field]
|
||||
})
|
||||
return item
|
||||
})
|
||||
const buildColumns: VxeGridPropTypes.Columns = [
|
||||
{
|
||||
field: 'col0',
|
||||
fixed: 'left',
|
||||
width: 200
|
||||
}
|
||||
]
|
||||
myData.forEach((item, index) => {
|
||||
buildColumns.push({
|
||||
field: `col${index + 1}`,
|
||||
minWidth: 120
|
||||
})
|
||||
})
|
||||
gridOptions.value.data = buildData
|
||||
gridOptions.value.columns = buildColumns
|
||||
}
|
||||
|
||||
reverseTable()
|
||||
|
||||
const echartsData1: any = ref([]),
|
||||
echartsData2: any = ref([]),
|
||||
echartsData3: any = ref([]),
|
||||
barCharts1 = ref(),
|
||||
barCharts2 = ref(),
|
||||
barCharts3 = ref()
|
||||
//加载echarts
|
||||
const init = () => {
|
||||
const xDataList: any = [],
|
||||
yDataList1: any = [],
|
||||
yDataList2: any = []
|
||||
tableList.map((item: any) => {
|
||||
xDataList.push(item.name)
|
||||
yDataList1.push(item.value)
|
||||
yDataList2.push(Math.floor(Math.random() * 101) + Math.floor(Math.random() * 101))
|
||||
yDataList2.push(Math.floor(Math.random() * 101) + Math.floor(Math.random() * 101))
|
||||
})
|
||||
if (activeName.value == '0') {
|
||||
echartsData1.value = {
|
||||
options: {
|
||||
// backgroundColor: '#0f375f',
|
||||
grid: {
|
||||
top: '22%',
|
||||
bottom: '15%', //也可设置left和right设置距离来控制图表的大小
|
||||
left: '3%',
|
||||
right: '5%'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'cross',
|
||||
label: {
|
||||
show: false
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: ['国标限值', yAxisUnit.value],
|
||||
top: '2%',
|
||||
right: '2%'
|
||||
// icon: 'icon'
|
||||
// icon: "circle", //icon 长方形 circle 圆形 arrow箭头型 diamond菱形
|
||||
// itemWidth: 14,
|
||||
// itemHeight: 14,
|
||||
// textStyle: {
|
||||
// inside: true,
|
||||
// color: '#000',
|
||||
// padding: [11, 0, 10, 0],
|
||||
// align: 'left',
|
||||
// verticalAlign: 'center',
|
||||
// fontSize: 14,
|
||||
// rich: {}
|
||||
// }
|
||||
},
|
||||
xAxis: {
|
||||
name: '次数',
|
||||
data: xDataList,
|
||||
axisLine: {
|
||||
show: true, //隐藏X轴轴线
|
||||
lineStyle: {
|
||||
color: '#000'
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: true //隐藏X轴刻度
|
||||
},
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
},
|
||||
axisLabel: {
|
||||
show: true,
|
||||
textStyle: {
|
||||
color: '#000' //X轴文字颜色
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
name: '单位(' + '%' + ')',
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
axisTick: {
|
||||
show: true
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#000'
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: '国标限值',
|
||||
type: 'bar',
|
||||
barMaxWidth: 24, //使用的 y 轴的 index,在单个图表实例中存在多个 y轴的时候有用
|
||||
itemStyle: {
|
||||
// normal: {
|
||||
barBorderRadius: [3, 3, 0, 0],
|
||||
color: '#00CC99'
|
||||
// }e
|
||||
},
|
||||
data: yDataList1
|
||||
},
|
||||
{
|
||||
name: yAxisUnit.value,
|
||||
type: 'bar',
|
||||
barMaxWidth: 24,
|
||||
itemStyle: {
|
||||
// normal: {
|
||||
barBorderRadius: [3, 3, 0, 0],
|
||||
|
||||
color: '#FF9900'
|
||||
// }
|
||||
},
|
||||
data: yDataList2
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
barCharts1.value.initChart()
|
||||
} else if (activeName.value == '1') {
|
||||
echartsData2.value = {
|
||||
options: {
|
||||
// backgroundColor: '#0f375f',
|
||||
grid: {
|
||||
top: '22%',
|
||||
bottom: '15%', //也可设置left和right设置距离来控制图表的大小
|
||||
left: '3%',
|
||||
right: '5%'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'cross',
|
||||
label: {
|
||||
show: false
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: ['国标限值', yAxisUnit.value],
|
||||
top: '2%',
|
||||
right: '2%'
|
||||
// icon: 'icon'
|
||||
// icon: "circle", //icon 长方形 circle 圆形 arrow箭头型 diamond菱形
|
||||
// itemWidth: 14,
|
||||
// itemHeight: 14,
|
||||
// textStyle: {
|
||||
// inside: true,
|
||||
// color: '#000',
|
||||
// padding: [11, 0, 10, 0],
|
||||
// align: 'left',
|
||||
// verticalAlign: 'center',
|
||||
// fontSize: 14,
|
||||
// rich: {}
|
||||
// }
|
||||
},
|
||||
xAxis: {
|
||||
name: '次数',
|
||||
data: xDataList,
|
||||
axisLine: {
|
||||
show: true, //隐藏X轴轴线
|
||||
lineStyle: {
|
||||
color: '#000'
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: true //隐藏X轴刻度
|
||||
},
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
},
|
||||
axisLabel: {
|
||||
show: true,
|
||||
textStyle: {
|
||||
color: '#000' //X轴文字颜色
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
name: '单位(' + '%' + ')',
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
axisTick: {
|
||||
show: true
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#000'
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: '国标限值',
|
||||
type: 'bar',
|
||||
barMaxWidth: 24, //使用的 y 轴的 index,在单个图表实例中存在多个 y轴的时候有用
|
||||
itemStyle: {
|
||||
// normal: {
|
||||
barBorderRadius: [3, 3, 0, 0],
|
||||
color: '#00CC99'
|
||||
// }e
|
||||
},
|
||||
data: yDataList1
|
||||
},
|
||||
{
|
||||
name: yAxisUnit.value,
|
||||
type: 'bar',
|
||||
barMaxWidth: 24,
|
||||
itemStyle: {
|
||||
// normal: {
|
||||
barBorderRadius: [3, 3, 0, 0],
|
||||
color: '#FF9900'
|
||||
// }
|
||||
},
|
||||
data: yDataList2
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
barCharts2.value.initChart()
|
||||
} else if (activeName.value == '2') {
|
||||
echartsData3.value = {
|
||||
options: {
|
||||
// backgroundColor: '#0f375f',
|
||||
grid: {
|
||||
top: '22%',
|
||||
bottom: '15%', //也可设置left和right设置距离来控制图表的大小
|
||||
left: '3%',
|
||||
right: '5%'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'cross',
|
||||
label: {
|
||||
show: false
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: ['国标限值', yAxisUnit.value],
|
||||
top: '2%',
|
||||
right: '2%'
|
||||
// icon: 'icon'
|
||||
// icon: "circle", //icon 长方形 circle 圆形 arrow箭头型 diamond菱形
|
||||
// itemWidth: 14,
|
||||
// itemHeight: 14,
|
||||
// textStyle: {
|
||||
// inside: true,
|
||||
// color: '#000',
|
||||
// padding: [11, 0, 10, 0],
|
||||
// align: 'left',
|
||||
// verticalAlign: 'center',
|
||||
// fontSize: 14,
|
||||
// rich: {}
|
||||
// }
|
||||
},
|
||||
xAxis: {
|
||||
name: '次数',
|
||||
data: xDataList,
|
||||
axisLine: {
|
||||
show: true, //隐藏X轴轴线
|
||||
lineStyle: {
|
||||
color: '#000'
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: true //隐藏X轴刻度
|
||||
},
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
},
|
||||
axisLabel: {
|
||||
show: true,
|
||||
textStyle: {
|
||||
color: '#000' //X轴文字颜色
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
name: '单位(' + '%' + ')',
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
axisTick: {
|
||||
show: true
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#000'
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: '国标限值',
|
||||
type: 'bar',
|
||||
barMaxWidth: 24, //使用的 y 轴的 index,在单个图表实例中存在多个 y轴的时候有用
|
||||
itemStyle: {
|
||||
// normal: {
|
||||
barBorderRadius: [3, 3, 0, 0],
|
||||
color: '#00CC99'
|
||||
// }e
|
||||
},
|
||||
data: yDataList1
|
||||
},
|
||||
{
|
||||
name: yAxisUnit.value,
|
||||
type: 'bar',
|
||||
barMaxWidth: 24,
|
||||
itemStyle: {
|
||||
// normal: {
|
||||
barBorderRadius: [3, 3, 0, 0],
|
||||
|
||||
color: '#FF9900'
|
||||
// }
|
||||
},
|
||||
data: yDataList2
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
barCharts3.value.initChart()
|
||||
}
|
||||
}
|
||||
|
||||
const handleClick = (tab: any, event: any) => {
|
||||
activeName.value = tab.index
|
||||
myColumns.value.map(item => {
|
||||
if (item.field == 'value') {
|
||||
item.title =
|
||||
activeName.value == '0'
|
||||
? '谐波电压含有率(%)'
|
||||
: activeName.value == '1'
|
||||
? '间谐波电压含有率(%)'
|
||||
: activeName.value == '2'
|
||||
? '谐波电流幅值(A)'
|
||||
: ''
|
||||
yAxisUnit.value = item.title.split('(')[0]
|
||||
}
|
||||
})
|
||||
reverseTable()
|
||||
init()
|
||||
}
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.realtrend {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.table_info {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
overflow-x: auto;
|
||||
.table {
|
||||
width: auto;
|
||||
height: auto;
|
||||
border: 2px solid #eee;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.thead {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
border-bottom: 2px solid #eee;
|
||||
.thead_left {
|
||||
width: 200px !important;
|
||||
height: 100%;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
}
|
||||
.thead_right {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
.thead_right_item {
|
||||
flex: none;
|
||||
width: 100px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
border-left: 1px solid #eee;
|
||||
}
|
||||
}
|
||||
}
|
||||
.tbody {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
.tbody_left {
|
||||
width: 200px !important;
|
||||
height: 100%;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
}
|
||||
.tbody_right {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
.tbody_right_item {
|
||||
flex: none;
|
||||
width: 100px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
border-left: 1px solid #eee;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.reverse-table {
|
||||
// max-height:120px !important;
|
||||
}
|
||||
.reverse-table .vxe-body--row .vxe-body--column:first-child {
|
||||
background-color: #f8f8f9;
|
||||
}
|
||||
::v-deep .vxe-table--render-wrapper {
|
||||
height: 90px !important;
|
||||
max-height: 90px !important;
|
||||
overflow-x: auto !important;
|
||||
min-height: 0 !important;
|
||||
}
|
||||
::v-deep .body--wrapper {
|
||||
height: 90px !important;
|
||||
max-height: 90px !important;
|
||||
min-height: 0 !important;
|
||||
}
|
||||
.tab_info {
|
||||
width: 100%;
|
||||
height: calc(100vh - 450px);
|
||||
// overflow: auto;
|
||||
// padding-bottom: 20px;
|
||||
.charts {
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
height: calc(100vh - 550px);
|
||||
}
|
||||
}
|
||||
.custom-tabs-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<div class="record">
|
||||
实时录波
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
onMounted(() => {
|
||||
console.log()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.record{
|
||||
width:100%;
|
||||
height:100%;
|
||||
border: 2px solid red;
|
||||
}
|
||||
</style>
|
||||
@@ -1,140 +1,62 @@
|
||||
<template>
|
||||
<div>
|
||||
<vxe-table
|
||||
border
|
||||
show-footer
|
||||
ref="tableRef"
|
||||
v-bind="defaultAttribute"
|
||||
height="70"
|
||||
align="center"
|
||||
stripe
|
||||
:loading="loading"
|
||||
:print-config="{}"
|
||||
:column-config="{ resizable: false, width: 90 }"
|
||||
:data="tableData"
|
||||
style="width: 100%; margin-top: 10px"
|
||||
>
|
||||
<div v-if="tableIndex == 0">
|
||||
<vxe-colgroup title="电压有效值(kV)">
|
||||
<vxe-column field="a" title="AB相"></vxe-column>
|
||||
<vxe-column field="b" title="BC相"></vxe-column>
|
||||
<vxe-column field="c" title="CA相"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
<vxe-colgroup title="电流有效值(A)">
|
||||
<vxe-column field="a" title="A相"></vxe-column>
|
||||
<vxe-column field="b" title="B相"></vxe-column>
|
||||
<vxe-column field="c" title="C相"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
<vxe-colgroup title="基波电压幅值(kV)">
|
||||
<vxe-column field="a" title="A相"></vxe-column>
|
||||
<vxe-column field="b" title="B相"></vxe-column>
|
||||
<vxe-column field="c" title="C相"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
<vxe-colgroup title="基波电压相位(°)">
|
||||
<vxe-column field="a" title="A相"></vxe-column>
|
||||
<vxe-column field="b" title="B相"></vxe-column>
|
||||
<vxe-column field="c" title="C相"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
<vxe-colgroup title="基波电流幅值(A)">
|
||||
<vxe-column field="a" title="A相"></vxe-column>
|
||||
<vxe-column field="b" title="B相"></vxe-column>
|
||||
<vxe-column field="c" title="C相"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
<vxe-colgroup title="基波电流相位(°)">
|
||||
<vxe-column field="a" title="A相"></vxe-column>
|
||||
<vxe-column field="b" title="B相"></vxe-column>
|
||||
<vxe-column field="c" title="C相"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
<div v-if="tableData.length != 0">
|
||||
<!-- div设计table -->
|
||||
<div class="table" v-for="(item, index) in columnsData" :key="index">
|
||||
<!-- 单层表头 -->
|
||||
<div class="thead">
|
||||
<div class="thead_top">
|
||||
{{ item[0].showName ? item[0].showName : '' }}({{ item[0].unit }})
|
||||
</div>
|
||||
<div class="thead_bot">
|
||||
<div class="thead_bot_cell" v-for="(vv, key) in item" :key="key">
|
||||
{{ vv.phase + '相 ' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="tableIndex == 1">
|
||||
<vxe-colgroup title="电压偏差(%)">
|
||||
<vxe-column field="a" title="AB相"></vxe-column>
|
||||
<vxe-column field="b" title="BC相"></vxe-column>
|
||||
<vxe-column field="c" title="CA相"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
<vxe-colgroup title="电压总谐波畸变率(%)">
|
||||
<vxe-column field="a" title="A相"></vxe-column>
|
||||
<vxe-column field="b" title="BC相"></vxe-column>
|
||||
<vxe-column field="c" title="CA相"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
<vxe-colgroup title="电流总谐波畸变率(%)">
|
||||
<vxe-column field="a" title="A相"></vxe-column>
|
||||
<vxe-column field="b" title="BC相"></vxe-column>
|
||||
<vxe-column field="c" title="CA相"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
<vxe-colgroup title="电压不平衡度(%)">
|
||||
<vxe-column field="a" title="A相"></vxe-column>
|
||||
<vxe-column field="b" title="BC相"></vxe-column>
|
||||
<vxe-column field="c" title="CA相"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
<vxe-column field="a" width="170" title="电流不平衡度(%)"></vxe-column>
|
||||
<vxe-column field="b" width="170" title="频率(Hz)"></vxe-column>
|
||||
<vxe-column field="c" width="170" title="基波电流相位(°)"></vxe-column>
|
||||
<!-- 有合并表头的数据 -->
|
||||
<div class="tbody">
|
||||
<div class="tbody_cell" v-for="(vv, key) in item" :key="key">
|
||||
{{
|
||||
tableData.find(item => {
|
||||
return item.anotherName == vv.showName && item.phase == vv.phase
|
||||
})?.statisticalData
|
||||
? tableData.find(item => {
|
||||
return item.anotherName == vv.showName && item.phase == vv.phase
|
||||
})?.statisticalData
|
||||
: '/'
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="tableIndex == 2">
|
||||
<vxe-colgroup title="有功功率(kV)">
|
||||
<vxe-column field="a" title="A相"></vxe-column>
|
||||
<vxe-column field="b" title="B相"></vxe-column>
|
||||
<vxe-column field="c" title="C相"></vxe-column>
|
||||
<vxe-column field="c" title="总有功功率"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
<vxe-colgroup title="无功功率(kV)">
|
||||
<vxe-column field="a" title="A相"></vxe-column>
|
||||
<vxe-column field="b" title="B相"></vxe-column>
|
||||
<vxe-column field="c" title="C相"></vxe-column>
|
||||
<vxe-column field="c" title="总无功功率"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
<vxe-colgroup title="视在功率(kV)">
|
||||
<vxe-column field="a" title="A相"></vxe-column>
|
||||
<vxe-column field="b" title="B相"></vxe-column>
|
||||
<vxe-column field="c" title="C相"></vxe-column>
|
||||
<vxe-column field="c" title="总视在功率"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
<vxe-colgroup title="功率因数">
|
||||
<vxe-column field="a" title="A相"></vxe-column>
|
||||
<vxe-column field="b" title="B相"></vxe-column>
|
||||
<vxe-column field="c" title="C相"></vxe-column>
|
||||
<vxe-column field="c" title="总功率因数"></vxe-column>
|
||||
</vxe-colgroup>
|
||||
</div>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, nextTick, onMounted } from 'vue'
|
||||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||
import { VxeTablePropTypes, VxeTableInstance, VxeToolbarInstance } from 'vxe-table'
|
||||
|
||||
interface RowVO {
|
||||
a: string
|
||||
b: string
|
||||
c: string
|
||||
}
|
||||
|
||||
import { getRealTimeTableList } from '@/api/cs-device-boot/EquipmentDelivery'
|
||||
const loading = ref(false)
|
||||
const tableData = ref<RowVO[]>([])
|
||||
|
||||
const tableRef = ref<VxeTableInstance<RowVO>>()
|
||||
const toolbarRef = ref<VxeToolbarInstance>()
|
||||
|
||||
const tableData: any = ref([])
|
||||
loading.value = true
|
||||
|
||||
nextTick(() => {
|
||||
// 将表格和工具栏进行关联
|
||||
const $table = tableRef.value
|
||||
const $toolbar = toolbarRef.value
|
||||
if ($table && $toolbar) {
|
||||
$table.connect($toolbar)
|
||||
}
|
||||
})
|
||||
const columnsData: any = ref([])
|
||||
const getColumns = () => {
|
||||
getRealTimeTableList().then(res => {
|
||||
columnsData.value = res.data
|
||||
})
|
||||
}
|
||||
nextTick(() => {})
|
||||
onMounted(() => {
|
||||
getColumns()
|
||||
loading.value = false
|
||||
})
|
||||
const tableIndex: any = ref(null)
|
||||
const getTableData = (val: any, list: any) => {
|
||||
tableIndex.value = val
|
||||
const getTableData = (list: any) => {
|
||||
tableData.value = list
|
||||
loading.value = false
|
||||
columnsData.value.map((item: any) => {
|
||||
item.map((vv: any) => {
|
||||
vv.statisticalData = list.find((kk: any) => {
|
||||
return kk.anotherName == vv.showName && kk.phase == vv.phase
|
||||
})?.statisticalData
|
||||
})
|
||||
})
|
||||
}
|
||||
defineExpose({ getTableData })
|
||||
</script>
|
||||
@@ -143,4 +65,58 @@ defineExpose({ getTableData })
|
||||
// ::v-deep .vxe-table--empty-content{
|
||||
// display: none !important;
|
||||
// }
|
||||
.table {
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
border: 1px solid #eee;
|
||||
border-bottom: 2px solid #eee;
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.thead {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
background: #f4f6f9;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.thead_top {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
border: 1px solid #eee;
|
||||
color: #111;
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
}
|
||||
.thead_bot {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
display: flex;
|
||||
color: #111;
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
.thead_bot_cell {
|
||||
flex: 1;
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
}
|
||||
}
|
||||
.tbody {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
.tbody_cell {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
border: 1px solid #eee;
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
.tbody:hover {
|
||||
background: #f4f6f9;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,29 +3,57 @@
|
||||
<div class="view_top">
|
||||
<!-- 左侧仪表盘 -->
|
||||
<div class="view_top_left">
|
||||
<div class="left_charts"><MyEchart ref="pieChartRef" :options="echartsData"></MyEchart></div>
|
||||
<div class="left_charts"><MyEchart ref="pieChartRef" :options="echartsData"></MyEchart></div>
|
||||
<div class="left_charts"><MyEchart ref="pieChartRef" :options="echartsData"></MyEchart></div>
|
||||
<div class="left_charts_title">电压有效值</div>
|
||||
<div class="left_charts"><MyEchart ref="pieChart1" :options="echartsDataV1"></MyEchart></div>
|
||||
<div class="left_charts"><MyEchart ref="pieChart2" :options="echartsDataV2"></MyEchart></div>
|
||||
<div class="left_charts"><MyEchart ref="pieChart3" :options="echartsDataV3"></MyEchart></div>
|
||||
</div>
|
||||
<div class="view_top_mid">
|
||||
<div class="mid_charts"><MyEchart ref="pieChartRef" :options="echartsData1"></MyEchart></div>
|
||||
<div class="mid_charts_title">基波电压/电流幅值(相位)</div>
|
||||
<div class="mid_charts"><MyEchart :options="echartsData1"></MyEchart></div>
|
||||
</div>
|
||||
<!-- 右侧仪表盘 -->
|
||||
<div class="view_top_right">
|
||||
<div class="right_charts"><MyEchart ref="pieChartRef" :options="echartsData"></MyEchart></div>
|
||||
<div class="right_charts"><MyEchart ref="pieChartRef" :options="echartsData"></MyEchart></div>
|
||||
<div class="right_charts"><MyEchart ref="pieChartRef" :options="echartsData"></MyEchart></div>
|
||||
<div class="right_chartsitle">电流有效值</div>
|
||||
<div class="right_charts"><MyEchart ref="pieChart4" :options="echartsDataA1"></MyEchart></div>
|
||||
<div class="right_charts"><MyEchart ref="pieChart5" :options="echartsDataA2"></MyEchart></div>
|
||||
<div class="right_charts"><MyEchart ref="pieChart6" :options="echartsDataA3"></MyEchart></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="view_bot">
|
||||
<div class="view_bot_tables">
|
||||
<tableInfo ref="tableInfoRef1" />
|
||||
</div>
|
||||
<div class="view_bot_tables">
|
||||
<tableInfo ref="tableInfoRef2" />
|
||||
</div>
|
||||
<div class="view_bot_tables">
|
||||
<tableInfo ref="tableInfoRef3" />
|
||||
<!-- <tableInfo ref="tableInfoRef" /> -->
|
||||
<!-- 表格数据 -->
|
||||
<div v-if="tableData.length != 0">
|
||||
<!-- div设计table -->
|
||||
<div class="table" v-for="(item, index) in columnsData" :key="index">
|
||||
<!-- 单层表头 -->
|
||||
<div class="thead">
|
||||
<div class="thead_top">
|
||||
{{ item[0].showName ? item[0].showName : '' }}({{ item[0].unit }})
|
||||
</div>
|
||||
<div class="thead_bot">
|
||||
<div class="thead_bot_cell" v-for="(vv, key) in item" :key="key">
|
||||
{{ vv.phase + '相 ' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 有合并表头的数据 -->
|
||||
<div class="tbody">
|
||||
<div class="tbody_cell" v-for="(vv, key) in item" :key="key">
|
||||
{{
|
||||
tableData.find(item => {
|
||||
return item.anotherName == vv.showName && item.phase == vv.phase
|
||||
})?.statisticalData
|
||||
? tableData.find(item => {
|
||||
return item.anotherName == vv.showName && item.phase == vv.phase
|
||||
})?.statisticalData
|
||||
: '/'
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -33,12 +61,27 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import MyEchart from '@/components/echarts/MyEchart.vue'
|
||||
import { getRealTimeTableList } from '@/api/cs-device-boot/EquipmentDelivery'
|
||||
import tableInfo from './components/tableInfo.vue'
|
||||
import * as echarts from 'echarts'
|
||||
import { split } from 'lodash-es'
|
||||
const pieChartRef: any = ref()
|
||||
const pieChart1: any = ref()
|
||||
const pieChart2: any = ref()
|
||||
const pieChart3: any = ref()
|
||||
const pieChart4: any = ref()
|
||||
const pieChart5: any = ref()
|
||||
const pieChart6: any = ref()
|
||||
const echartsData: any = ref({})
|
||||
const echartsData1: any = ref({})
|
||||
//电压有效值
|
||||
const echartsDataV1: any = ref({})
|
||||
const echartsDataV2: any = ref({})
|
||||
const echartsDataV3: any = ref({})
|
||||
//电流有效值
|
||||
const echartsDataA1: any = ref({})
|
||||
const echartsDataA2: any = ref({})
|
||||
const echartsDataA3: any = ref({})
|
||||
//渲染echarts
|
||||
const init = () => {
|
||||
echartsData.value = {
|
||||
@@ -87,251 +130,22 @@ const init = () => {
|
||||
data: [
|
||||
{
|
||||
value: 15,
|
||||
name: '违规率'
|
||||
name: 'A相'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
echartsDataV1.value = echartsData.value
|
||||
echartsDataV2.value = echartsData.value
|
||||
echartsDataV3.value = echartsData.value
|
||||
echartsDataA1.value = echartsData.value
|
||||
echartsDataA2.value = echartsData.value
|
||||
echartsDataA3.value = echartsData.value
|
||||
|
||||
//中间指针图
|
||||
echartsData1.value = {
|
||||
// options: {
|
||||
// // backgroundColor: '#001533',
|
||||
// tooltip: {
|
||||
// format: function (params) {
|
||||
// console.log(params)
|
||||
// }
|
||||
// },
|
||||
// series: [
|
||||
// //外圈
|
||||
// {
|
||||
// radius: '100%',
|
||||
// min: -150,
|
||||
// max: 180,
|
||||
// startAngle: -90,
|
||||
// endAngle: 270,
|
||||
// pointer: {
|
||||
// show: true,
|
||||
// length: '80%',
|
||||
// radius: '20%',
|
||||
// width: 6 //指针粗细
|
||||
// },
|
||||
// itemStyle: {
|
||||
// normal: {
|
||||
// color: 'rgb(0,191,255)'
|
||||
// }
|
||||
// },
|
||||
// // axisLine: {
|
||||
// // show: true,
|
||||
// // fontSize: 20,
|
||||
// // lineStyle: {
|
||||
// // width: 0,
|
||||
// // color: [[1, '#01b4e0']]
|
||||
// // }
|
||||
// // },
|
||||
|
||||
// axisLine: {
|
||||
// show: true,
|
||||
// // 坐标轴线
|
||||
// lineStyle: {
|
||||
// color: [[1, '#F42E47']], // 属性lineStyle控制线条样式
|
||||
// width: 2
|
||||
// },
|
||||
// interval: 0
|
||||
// },
|
||||
// splitLine: {
|
||||
// length: 10,
|
||||
// lineStyle: {
|
||||
// width: 2,
|
||||
// color: '#01b4e0',
|
||||
// distance: 5
|
||||
// }, //刻度节点线
|
||||
// splitNumber: 5
|
||||
// },
|
||||
// splitNumber: 11,
|
||||
// axisTick: {
|
||||
// show: false
|
||||
// },
|
||||
// axisLabel: {
|
||||
// show: true,
|
||||
// fontSize: 14,
|
||||
// color: '#000',
|
||||
// formatter: function (v: any) {
|
||||
// console.log(v, '00000000000')
|
||||
// switch (v + '') {
|
||||
// case '-122.5':
|
||||
// return '-120'
|
||||
// case '-95':
|
||||
// return '-90'
|
||||
// case '-60':
|
||||
// return '-60'
|
||||
// case '-67.5':
|
||||
// return '-60'
|
||||
// case '-40':
|
||||
// return '-30'
|
||||
// case '-12.5':
|
||||
// return '0'
|
||||
// case '42.5':
|
||||
// return '30'
|
||||
// case '70':
|
||||
// return '60'
|
||||
// case '97.5':
|
||||
// return '90'
|
||||
// case '125':
|
||||
// return '120'
|
||||
// case '152.5':
|
||||
// return '150'
|
||||
// case '-180':
|
||||
// return ''
|
||||
// case '180':
|
||||
// return '180'
|
||||
// default:
|
||||
// return v
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// detail: {
|
||||
// show: false,
|
||||
// textStyle: {
|
||||
// fontSize: 30,
|
||||
// fontWeight: '700',
|
||||
// color: '#67d9fe'
|
||||
// }
|
||||
// },
|
||||
// data: [
|
||||
// {
|
||||
// name: '',
|
||||
// value: 150,
|
||||
// itemStyle: {
|
||||
// color: 'red'
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// name: '',
|
||||
// value: 60,
|
||||
// itemStyle: {
|
||||
// color: '#DAA521'
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// name: '',
|
||||
// value: 90,
|
||||
// itemStyle: {
|
||||
// color: 'green'
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// //内圈
|
||||
// {
|
||||
// radius: '50%',
|
||||
// splitNumber: 11,
|
||||
// startAngle: 0,
|
||||
// endAngle: 360,
|
||||
// min: -150,
|
||||
// max: 180,
|
||||
// axisLine: {
|
||||
// show: true,
|
||||
// // 坐标轴线
|
||||
// lineStyle: {
|
||||
// color: [[1, '#1C9EE9']], // 属性lineStyle控制线条样式
|
||||
// width: 2,
|
||||
// type: 'dashed'
|
||||
// }
|
||||
// },
|
||||
// pointer: {
|
||||
// show: true,
|
||||
// length: '80%',
|
||||
// radius: '20%',
|
||||
// width: 8 //指针粗细
|
||||
// },
|
||||
// itemStyle: {
|
||||
// // show: false,
|
||||
// normal: {
|
||||
// color: 'rgb(0,191,255)'
|
||||
// }
|
||||
// },
|
||||
// splitLine: {
|
||||
// length: 5,
|
||||
// interval: 30,
|
||||
// lineStyle: {
|
||||
// width: 2,
|
||||
// color: 'green',
|
||||
// distance: -20
|
||||
// } //刻度节点线
|
||||
// },
|
||||
// axisTick: {
|
||||
// show: false
|
||||
// },
|
||||
// axisLabel: {
|
||||
// show: true,
|
||||
// itemStyle: {
|
||||
// interval: 0
|
||||
// },
|
||||
// formatter: function (v: any) {
|
||||
// console.log(v, '00000000000')
|
||||
// switch (v + '') {
|
||||
// case '-122.5':
|
||||
// return '-120'
|
||||
// case '-95':
|
||||
// return '-90'
|
||||
// case '-60':
|
||||
// return '-60'
|
||||
// case '-67.5':
|
||||
// return '-60'
|
||||
// case '-40':
|
||||
// return '-30'
|
||||
// case '-12.5':
|
||||
// return '0'
|
||||
// case '42.5':
|
||||
// return '30'
|
||||
// case '70':
|
||||
// return '60'
|
||||
// case '97.5':
|
||||
// return '90'
|
||||
// case '125':
|
||||
// return '120'
|
||||
// case '152.5':
|
||||
// return '150'
|
||||
// case '-180':
|
||||
// return ''
|
||||
// case '180':
|
||||
// return '180'
|
||||
// default:
|
||||
// return v
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// detail: {
|
||||
// show: false
|
||||
// },
|
||||
// data: [
|
||||
// {
|
||||
// name: '',
|
||||
// value: 110,
|
||||
// itemStyle: {
|
||||
// color: 'red'
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// name: '',
|
||||
// value: 70,
|
||||
// itemStyle: {
|
||||
// color: '#DAA521'
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// name: '',
|
||||
// value: 20,
|
||||
// itemStyle: {
|
||||
// color: 'green'
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
options: {
|
||||
grid: {
|
||||
top: 230
|
||||
@@ -1102,7 +916,7 @@ const init = () => {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: [
|
||||
[0.25, '#9D322D'],
|
||||
[0.25, '#9D322D'],
|
||||
[0.5, '#9D322D'],
|
||||
[0.75, '#9D322D'],
|
||||
[1, '#9D322D']
|
||||
@@ -1186,32 +1000,125 @@ const init = () => {
|
||||
echartsData1.value.options.series[i].startAngle = 90
|
||||
echartsData1.value.options.series[i].endAngle = -270
|
||||
echartsData1.value.options.series[i].center = ['50%', '50%']
|
||||
// option.series[i].axisTick = {show: false};
|
||||
// option.series[i].axisLabel = {show: false};
|
||||
// optionThree.series[i].pointer = {show: false};
|
||||
// optionThree.series[i].detail = {show: false};
|
||||
}
|
||||
}
|
||||
//渲染table表头
|
||||
const tableInfoRef1: any = ref(null)
|
||||
const tableInfoRef2: any = ref(null)
|
||||
const tableInfoRef3: any = ref(null)
|
||||
const initTableHead = () => {
|
||||
const list: any = []
|
||||
for (let index = 0; index < 1; index++) {
|
||||
list.push({
|
||||
a: Math.floor(Math.random() * (100 + 1)),
|
||||
b: Math.floor(Math.random() * (100 + 1)),
|
||||
c: Math.floor(Math.random() * (100 + 1))
|
||||
//接收父组件传递的table数据
|
||||
const tableInfoRef: any = ref(null)
|
||||
const dataList: any = ref([])
|
||||
const listV: any = ref([])
|
||||
const listA: any = ref([])
|
||||
const loading = ref(false)
|
||||
//定义表格所需要的数据
|
||||
const tableData: any = ref([])
|
||||
loading.value = true
|
||||
const columnsData: any = ref([])
|
||||
const getColumns = () => {
|
||||
getRealTimeTableList().then(res => {
|
||||
columnsData.value = res.data
|
||||
})
|
||||
}
|
||||
//处理表格数据
|
||||
const getTableData = (list: any) => {
|
||||
tableData.value = list
|
||||
loading.value = false
|
||||
columnsData.value.map((item: any) => {
|
||||
item.map((vv: any) => {
|
||||
vv.statisticalData = list.find((kk: any) => {
|
||||
return kk.anotherName == vv.showName && kk.phase == vv.phase
|
||||
})?.statisticalData
|
||||
})
|
||||
}
|
||||
tableInfoRef1.value.getTableData(0, list)
|
||||
tableInfoRef2.value.getTableData(1, list)
|
||||
tableInfoRef3.value.getTableData(2, list)
|
||||
})
|
||||
}
|
||||
//获取实时数据
|
||||
const getRealTimeData = (val: any) => {
|
||||
dataList.value = val
|
||||
dataList.value.map((item: any, index: any) => {
|
||||
if (item.anotherName == '相电压总有效值') {
|
||||
listV.value.push(item)
|
||||
}
|
||||
if (item.anotherName == '线电压总有效值') {
|
||||
listA.value.push(item)
|
||||
}
|
||||
})
|
||||
|
||||
echartsDataV1.value.options.series[0].data = [
|
||||
{
|
||||
name:
|
||||
listV.value.find((item: any) => {
|
||||
return item.phase == 'A'
|
||||
})?.phase + '相',
|
||||
value: listV.value.find((item: any) => {
|
||||
return item.phase == 'A'
|
||||
})?.statisticalData
|
||||
}
|
||||
]
|
||||
pieChart1.value.initChart()
|
||||
echartsDataV2.value.options.series[0].data = [
|
||||
{
|
||||
name:
|
||||
listV.value.find((item: any) => {
|
||||
return item.phase == 'B'
|
||||
})?.phase + '相',
|
||||
value: listV.value.find((item: any) => {
|
||||
return item.phase == 'B'
|
||||
})?.statisticalData
|
||||
}
|
||||
]
|
||||
pieChart2.value.initChart()
|
||||
echartsDataV3.value.options.series[0].data = [
|
||||
{
|
||||
name:
|
||||
listV.value.find((item: any) => {
|
||||
return item.phase == 'C'
|
||||
})?.phase + '相',
|
||||
value: listV.value.find((item: any) => {
|
||||
return item.phase == 'C'
|
||||
})?.statisticalData
|
||||
}
|
||||
]
|
||||
pieChart3.value.initChart()
|
||||
echartsDataA1.value.options.series[0].data = [
|
||||
{
|
||||
name:
|
||||
listA.value.find((item: any) => {
|
||||
return item.phase == 'AB'
|
||||
})?.phase + '相',
|
||||
value: listA.value.find((item: any) => {
|
||||
return item.phase == 'AB'
|
||||
})?.statisticalData
|
||||
}
|
||||
]
|
||||
pieChart4.value.initChart()
|
||||
echartsDataA2.value.options.series[0].data = [
|
||||
{
|
||||
name:
|
||||
listA.value.find((item: any) => {
|
||||
return item.phase == 'BC'
|
||||
})?.phase + '相',
|
||||
value: listA.value.find((item: any) => {
|
||||
return item.phase == 'BC'
|
||||
})?.statisticalData
|
||||
}
|
||||
]
|
||||
pieChart5.value.initChart()
|
||||
echartsDataA3.value.options.series[0].data = [
|
||||
{
|
||||
name:
|
||||
listA.value.find((item: any) => {
|
||||
return item.phase == 'CA'
|
||||
})?.phase + '相',
|
||||
value: listA.value.find((item: any) => {
|
||||
return item.phase == 'CA'
|
||||
})?.statisticalData
|
||||
}
|
||||
]
|
||||
pieChart6.value.initChart()
|
||||
getColumns()
|
||||
getTableData(val)
|
||||
}
|
||||
defineExpose({ getRealTimeData })
|
||||
onMounted(() => {
|
||||
init()
|
||||
initTableHead()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@@ -1232,16 +1139,18 @@ onMounted(() => {
|
||||
.view_top_right {
|
||||
width: 30%;
|
||||
height: 100%;
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
border: 1px solid #eee;
|
||||
.left_charts,
|
||||
.right_charts {
|
||||
flex: none;
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
border: 1px solid #eee;
|
||||
margin-bottom: 10px;
|
||||
|
||||
margin-bottom: 16px;
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
@@ -1250,11 +1159,23 @@ onMounted(() => {
|
||||
border: 1px solid #eee;
|
||||
margin: 0 10px;
|
||||
padding: 10px;
|
||||
height: 450px;
|
||||
.mid_charts {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.left_charts_title,
|
||||
.mid_charts_title,
|
||||
.right_charts_title {
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
text-align: left;
|
||||
font-weight: 800;
|
||||
font-weight: 16px;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
.view_bot {
|
||||
min-height: 300px;
|
||||
@@ -1268,4 +1189,58 @@ onMounted(() => {
|
||||
.view::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
.table {
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
border: 1px solid #eee;
|
||||
border-bottom: 2px solid #eee;
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.thead {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
background: #f4f6f9;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.thead_top {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
border: 1px solid #eee;
|
||||
color: #111;
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
}
|
||||
.thead_bot {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
display: flex;
|
||||
color: #111;
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
.thead_bot_cell {
|
||||
flex: 1;
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
}
|
||||
}
|
||||
.tbody {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
.tbody_cell {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
border: 1px solid #eee;
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
.tbody:hover {
|
||||
background: #f4f6f9;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -429,12 +429,12 @@ const open = async (val: any, id: any) => {
|
||||
//0未绑定数据 1 已绑定数据
|
||||
//获取未绑定树形数据
|
||||
getDeviceList({ id: id, isTrueFlag: 0 }).then(res => {
|
||||
deviceInfoTreeRef1.value.getTreeList(res.data)
|
||||
// deviceInfoTreeRef1.value.getTreeList(res.data)
|
||||
unBindList.value = res.data
|
||||
})
|
||||
//获取已绑定树形数据
|
||||
getDeviceList({ id: id, isTrueFlag: 1 }).then(res => {
|
||||
deviceInfoTreeRef2.value.getTreeList(res.data)
|
||||
// deviceInfoTreeRef2.value.getTreeList(res.data)
|
||||
bindList.value = res.data
|
||||
})
|
||||
activeName.value = 0
|
||||
|
||||
176192
src/views/govern/reportCore/statistics/123.json
Normal file
176192
src/views/govern/reportCore/statistics/123.json
Normal file
File diff suppressed because it is too large
Load Diff
169
src/views/govern/reportCore/statistics/index.vue
Normal file
169
src/views/govern/reportCore/statistics/index.vue
Normal file
@@ -0,0 +1,169 @@
|
||||
<template>
|
||||
<div class="default-main" :style="height">
|
||||
<splitpanes style="height: 100%; background: #fff" class="default-theme" id="navigation-splitpanes">
|
||||
<pane :size="size">
|
||||
<PointTree
|
||||
:default-expand-all="false"
|
||||
@node-click="handleNodeClick"
|
||||
@init="handleNodeClick"
|
||||
></PointTree>
|
||||
</pane>
|
||||
<pane style="background: #fff" :style="height">
|
||||
<div class="default-main">
|
||||
<TableHeader ref="TableHeaderRef" datePicker>
|
||||
<template v-slot:select>
|
||||
<el-form-item label="模板策略">
|
||||
<el-select
|
||||
v-model="Template"
|
||||
@change="changetype"
|
||||
placeholder="请选择模版"
|
||||
value-key="id"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in templatePolicy"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="报表类型:">
|
||||
<el-select
|
||||
:disabled="true"
|
||||
v-model="reportForm"
|
||||
:popper-append-to-body="false"
|
||||
placeholder="请选择报表类型"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in reportFormList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template #operation>
|
||||
<el-button icon="el-icon-Download" type="primary" @click="exportEvent">导出excel</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<div class="box">
|
||||
<div id="luckysheet" :style="`height: calc(${tableStore.table.height} + 45px)`"></div>
|
||||
</div>
|
||||
</div>
|
||||
</pane>
|
||||
</splitpanes>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, provide } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import PointTree from '@/components/tree/govern/pointTree.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import { getTemplateByDept } from '@/api/harmonic-boot/luckyexcel'
|
||||
import { exportExcel } from '@/views/system/reportForms/export.js'
|
||||
import 'splitpanes/dist/splitpanes.css'
|
||||
import { Splitpanes, Pane } from 'splitpanes'
|
||||
import data from './123.json'
|
||||
defineOptions({
|
||||
name: 'reportCore/statistics'
|
||||
})
|
||||
const height = mainHeight(20)
|
||||
const size = ref(0)
|
||||
const dictData = useDictData()
|
||||
const TableHeaderRef = ref()
|
||||
const dotList: any = ref({})
|
||||
const Template: any = ref({})
|
||||
const reportForm: any = ref('')
|
||||
|
||||
const templatePolicy: any = ref([])
|
||||
const reportFormList: any = ref([
|
||||
{
|
||||
value: '1',
|
||||
label: '分析报表'
|
||||
},
|
||||
{
|
||||
value: '2',
|
||||
label: '统计报表'
|
||||
},
|
||||
{
|
||||
value: '3',
|
||||
label: '自定义报表'
|
||||
}
|
||||
])
|
||||
const tableStore = new TableStore({
|
||||
// url: '/harmonic-boot/customReport/getCustomReport',
|
||||
method: 'POST',
|
||||
column: [],
|
||||
beforeSearchFun: () => {
|
||||
tableStore.table.params.tempId = Template.value.id
|
||||
tableStore.table.params.lineId = dotList.value.id
|
||||
},
|
||||
loadCallback: () => {
|
||||
console.log(tableStore.table.data)
|
||||
tableStore.table.data.forEach((item: any) => {
|
||||
item.celldata.forEach((k: any) => {
|
||||
item.data[k.r][k.c].v = k.v
|
||||
})
|
||||
})
|
||||
luckysheet.create({
|
||||
container: 'luckysheet',
|
||||
title: '', // 表 头名
|
||||
lang: 'zh', // 中文
|
||||
showtoolbar: false, // 是否显示工具栏
|
||||
showinfobar: false, // 是否显示顶部信息栏
|
||||
showsheetbar: true, // 是否显示底部sheet按钮
|
||||
data: data
|
||||
// tableStore.table.data
|
||||
})
|
||||
}
|
||||
})
|
||||
provide('tableStore', tableStore)
|
||||
onMounted(() => {
|
||||
const dom = document.getElementById('navigation-splitpanes')
|
||||
if (dom) {
|
||||
size.value = Math.round((180 / dom.offsetHeight) * 100)
|
||||
}
|
||||
|
||||
luckysheet.create({
|
||||
container: 'luckysheet',
|
||||
title: '', // 表 头名
|
||||
lang: 'zh', // 中文
|
||||
showtoolbar: false, // 是否显示工具栏
|
||||
showinfobar: false, // 是否显示顶部信息栏
|
||||
showsheetbar: true, // 是否显示底部sheet按钮
|
||||
data: data
|
||||
// tableStore.table.data
|
||||
})
|
||||
})
|
||||
// getTemplateByDept({ id: dictData.state.area[0].id }).then((res: any) => {
|
||||
// templatePolicy.value = res.data
|
||||
// Template.value = res.data[0]
|
||||
// reportForm.value = res.data[0]?.reportForm
|
||||
// })
|
||||
const changetype = (val: any) => {
|
||||
reportForm.value = val.reportForm
|
||||
}
|
||||
|
||||
const handleNodeClick = (data: any, node: any) => {
|
||||
if (data.level == 6) {
|
||||
dotList.value = data
|
||||
tableStore.index()
|
||||
}
|
||||
}
|
||||
|
||||
const exportEvent = () => {
|
||||
exportExcel(luckysheet.getAllSheets(), '统计报表下载')
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.splitpanes.default-theme .splitpanes__pane {
|
||||
background: #eaeef1;
|
||||
}
|
||||
|
||||
.box {
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
108
src/views/system/reportForms/bind.vue
Normal file
108
src/views/system/reportForms/bind.vue
Normal file
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<el-tabs v-model="activeName" class="demo-tabs">
|
||||
<el-tab-pane label="数据单位" name="0">
|
||||
绑定数据单位:
|
||||
<el-cascader
|
||||
:popper-append-to-body="false"
|
||||
ref="cascaderUnit"
|
||||
placeholder="请选择数据单位"
|
||||
v-model="value"
|
||||
:options="options1"
|
||||
filterable
|
||||
@change="handleChange"
|
||||
:props="{
|
||||
value: 'code',
|
||||
label: 'name'
|
||||
}"
|
||||
></el-cascader>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="数据指标" name="1">
|
||||
绑定数据指标:
|
||||
<el-cascader
|
||||
:popper-append-to-body="false"
|
||||
ref="cascaderUnit"
|
||||
placeholder="请选择数据指标"
|
||||
v-model="value"
|
||||
:options="options2"
|
||||
filterable
|
||||
@change="handleChange"
|
||||
:props="{
|
||||
value: 'name',
|
||||
label: 'showName'
|
||||
}"
|
||||
></el-cascader>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="合格率判定" name="2">
|
||||
绑定合格率判定:
|
||||
<el-cascader
|
||||
:popper-append-to-body="false"
|
||||
ref="cascaderhgl"
|
||||
placeholder="请选择数据合格率"
|
||||
v-model="value"
|
||||
:options="options3"
|
||||
filterable
|
||||
@change="handleChange"
|
||||
:props="{
|
||||
value: 'name',
|
||||
label: 'showName'
|
||||
}"
|
||||
></el-cascader>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="监测点台账指标" name="3">
|
||||
绑定数据指标:
|
||||
<el-cascader
|
||||
:popper-append-to-body="false"
|
||||
ref="cascaderjcd"
|
||||
placeholder="请选择监测点台账"
|
||||
v-model="value"
|
||||
:options="options4"
|
||||
filterable
|
||||
@change="handleChange"
|
||||
:props="{
|
||||
value: 'name',
|
||||
label: 'showName'
|
||||
}"
|
||||
></el-cascader>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { codeDicTree } from '@/api/system-boot/dictTree'
|
||||
import { targetLimitChooseTree, getIndex, terminalChooseTree } from '@/api/harmonic-boot/luckyexcel'
|
||||
const emit = defineEmits(['setValue'])
|
||||
|
||||
const activeName = ref('0')
|
||||
const value = ref([])
|
||||
|
||||
const options1 = ref([])
|
||||
const options2 = ref([])
|
||||
const options3 = ref([])
|
||||
const options4: any = ref([])
|
||||
|
||||
const handleChange = (e: any) => {
|
||||
value.value = []
|
||||
|
||||
emit('setValue', e)
|
||||
}
|
||||
|
||||
codeDicTree({ code: 'Device_Unit' }).then(res => {
|
||||
options1.value = res.data
|
||||
})
|
||||
getIndex().then(res => {
|
||||
options2.value = res.data
|
||||
})
|
||||
targetLimitChooseTree().then(res => {
|
||||
options3.value = res.data
|
||||
})
|
||||
terminalChooseTree().then(res => {
|
||||
options4.value = res.data
|
||||
})
|
||||
|
||||
onMounted(() => {})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-tab-pane) {
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
102
src/views/system/reportForms/department.vue
Normal file
102
src/views/system/reportForms/department.vue
Normal file
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<el-dialog draggable v-model="dialogVisible" title="模板绑定" width="500px" :before-close="handleClose">
|
||||
<el-tree
|
||||
default-expand-all
|
||||
show-checkbox
|
||||
node-key="id"
|
||||
:data="dataTree"
|
||||
:expand-on-click-node="false"
|
||||
ref="tree"
|
||||
style="height: 440px; overflow-y: auto"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<span class="custom-tree-node">
|
||||
<span>{{ data.name }}</span>
|
||||
<span>
|
||||
<el-switch
|
||||
v-model="data.activation"
|
||||
active-value="1"
|
||||
inactive-value="0"
|
||||
:active-text="data.activation == 1 ? '激活 ' : '未激活'"
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
</el-tree>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="bind">绑定</el-button>
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import { getDataByTempId, updateBindTemplate } from '@/api/harmonic-boot/luckyexcel'
|
||||
const emit = defineEmits(['shutDown'])
|
||||
const dictData = useDictData()
|
||||
const dialogVisible = ref(false)
|
||||
const keyarr: any = ref([])
|
||||
const idarr: any = ref([])
|
||||
const dataTree: any = ref([])
|
||||
const area = ref(dictData.state.area)
|
||||
|
||||
const handleClose = () => {
|
||||
dialogVisible.value = false
|
||||
// emit('handleClose')
|
||||
}
|
||||
const open = (row: any) => {
|
||||
dialogVisible.value = true
|
||||
getDataByTempId({ id: row.id }).then(res => {
|
||||
res.data.forEach(item => {
|
||||
keyarr.value.push({
|
||||
name: item.deptName,
|
||||
id: item.deptId,
|
||||
activation: item.activation
|
||||
})
|
||||
idarr.value.push({ id: item.deptId })
|
||||
})
|
||||
gettreeData(area.value, keyarr.value)
|
||||
dataTree.value = area.value
|
||||
})
|
||||
}
|
||||
//过滤数据
|
||||
const gettreeData = (mdata, ids) => {
|
||||
mdata.forEach(m => {
|
||||
ids.forEach(n => {
|
||||
if (m.id == n.id && n.activation == 1) {
|
||||
m.activation = 1
|
||||
} else {
|
||||
m.activation = 0
|
||||
}
|
||||
})
|
||||
if (m.children != null || m.children.length > 0) {
|
||||
gettreeData(m.children, ids)
|
||||
} else {
|
||||
m.children = null
|
||||
}
|
||||
})
|
||||
}
|
||||
// 绑定
|
||||
const bind = () => {
|
||||
updateBindTemplate().then(res => {
|
||||
// ElMessage.success('绑定成功')
|
||||
})
|
||||
}
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.custom-tree-node {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 14px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
</style>
|
||||
349
src/views/system/reportForms/export.js
Normal file
349
src/views/system/reportForms/export.js
Normal file
@@ -0,0 +1,349 @@
|
||||
// import { createCellPos } from './translateNumToLetter'
|
||||
import Excel from 'exceljs'
|
||||
|
||||
import FileSaver from 'file-saver'
|
||||
|
||||
const exportExcel = function(luckysheet, value) {
|
||||
// 参数为luckysheet.getluckysheetfile()获取的对象
|
||||
// 1.创建工作簿,可以为工作簿添加属性
|
||||
const workbook = new Excel.Workbook()
|
||||
// 2.创建表格,第二个参数可以配置创建什么样的工作表
|
||||
if (Object.prototype.toString.call(luckysheet) === '[object Object]') {
|
||||
luckysheet = [luckysheet]
|
||||
}
|
||||
luckysheet.forEach(function(table) {
|
||||
if (table.data.length === 0) return true
|
||||
// ws.getCell('B2').fill = fills.
|
||||
const worksheet = workbook.addWorksheet(table.name)
|
||||
const merge = (table.config && table.config.merge) || {}
|
||||
const borderInfo = (table.config && table.config.borderInfo) || {}
|
||||
// 3.设置单元格合并,设置单元格边框,设置单元格样式,设置值
|
||||
setStyleAndValue(table.data, worksheet)
|
||||
setMerge(merge, worksheet)
|
||||
setBorder(borderInfo, worksheet)
|
||||
return true
|
||||
})
|
||||
|
||||
// return
|
||||
// 4.写入 buffer
|
||||
const buffer = workbook.xlsx.writeBuffer().then(data => {
|
||||
// console.log('data', data)
|
||||
const blob = new Blob([data], {
|
||||
type: 'application/vnd.ms-excel;charset=utf-8'
|
||||
})
|
||||
console.log("导出成功!")
|
||||
FileSaver.saveAs(blob, `${value}.xlsx`)
|
||||
})
|
||||
return buffer
|
||||
}
|
||||
|
||||
var setMerge = function(luckyMerge = {}, worksheet) {
|
||||
const mergearr = Object.values(luckyMerge)
|
||||
mergearr.forEach(function(elem) {
|
||||
// elem格式:{r: 0, c: 0, rs: 1, cs: 2}
|
||||
// 按开始行,开始列,结束行,结束列合并(相当于 K10:M12)
|
||||
worksheet.mergeCells(
|
||||
elem.r + 1,
|
||||
elem.c + 1,
|
||||
elem.r + elem.rs,
|
||||
elem.c + elem.cs
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
var setBorder = function(luckyBorderInfo, worksheet) {
|
||||
if (!Array.isArray(luckyBorderInfo)) return
|
||||
// console.log('luckyBorderInfo', luckyBorderInfo)
|
||||
luckyBorderInfo.forEach(function(elem) {
|
||||
// 现在只兼容到borderType 为range的情况
|
||||
// console.log('ele', elem)
|
||||
if (elem.rangeType === 'range') {
|
||||
let border = borderConvert(elem.borderType, elem.style, elem.color)
|
||||
let rang = elem.range[0]
|
||||
// console.log('range', rang)
|
||||
let row = rang.row
|
||||
let column = rang.column
|
||||
for (let i = row[0] + 1; i < row[1] + 2; i++) {
|
||||
for (let y = column[0] + 1; y < column[1] + 2; y++) {
|
||||
worksheet.getCell(i, y).border = border
|
||||
}
|
||||
}
|
||||
}
|
||||
if (elem.rangeType === 'cell') {
|
||||
// col_index: 2
|
||||
// row_index: 1
|
||||
// b: {
|
||||
// color: '#d0d4e3'
|
||||
// style: 1
|
||||
// }
|
||||
const { col_index, row_index } = elem.value
|
||||
const borderData = Object.assign({}, elem.value)
|
||||
delete borderData.col_index
|
||||
delete borderData.row_index
|
||||
let border = addborderToCell(borderData, row_index, col_index)
|
||||
// console.log('bordre', border, borderData)
|
||||
worksheet.getCell(row_index + 1, col_index + 1).border = border
|
||||
}
|
||||
// console.log(rang.column_focus + 1, rang.row_focus + 1)
|
||||
// worksheet.getCell(rang.row_focus + 1, rang.column_focus + 1).border = border
|
||||
})
|
||||
}
|
||||
var setStyleAndValue = function(cellArr, worksheet) {
|
||||
if (!Array.isArray(cellArr)) return
|
||||
cellArr.forEach(function(row, rowid) {
|
||||
row.every(function(cell, columnid) {
|
||||
if (!cell) return true
|
||||
let fill = fillConvert(cell.bg)
|
||||
|
||||
let font = fontConvert(
|
||||
cell.ff,
|
||||
cell.fc,
|
||||
cell.bl,
|
||||
cell.it,
|
||||
cell.fs,
|
||||
cell.cl,
|
||||
cell.ul
|
||||
)
|
||||
let alignment = alignmentConvert(cell.vt, cell.ht, cell.tb, cell.tr)
|
||||
let value = ''
|
||||
|
||||
if (cell.f) {
|
||||
value = { formula: cell.f, result: cell.v }
|
||||
} else if (!cell.v && cell.ct && cell.ct.s) {
|
||||
// xls转为xlsx之后,内部存在不同的格式,都会进到富文本里,即值不存在与cell.v,而是存在于cell.ct.s之后
|
||||
// value = cell.ct.s[0].v
|
||||
cell.ct.s.forEach(arr => {
|
||||
value += arr.v
|
||||
})
|
||||
} else {
|
||||
value = cell.v
|
||||
}
|
||||
// style 填入到_value中可以实现填充色
|
||||
let letter = createCellPos(columnid)
|
||||
let target = worksheet.getCell(letter + (rowid + 1))
|
||||
// console.log('1233', letter + (rowid + 1))
|
||||
for (const key in fill) {
|
||||
target.fill = fill
|
||||
break
|
||||
}
|
||||
target.font = font
|
||||
target.alignment = alignment
|
||||
target.value = value
|
||||
|
||||
return true
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
var fillConvert = function(bg) {
|
||||
if (!bg) {
|
||||
return {}
|
||||
}
|
||||
// const bgc = bg.replace('#', '')
|
||||
let fill = {
|
||||
type: 'pattern',
|
||||
pattern: 'solid',
|
||||
fgColor: { argb: bg.replace('#', '') }
|
||||
}
|
||||
return fill
|
||||
}
|
||||
|
||||
var fontConvert = function(
|
||||
ff = 0,
|
||||
fc = '#000000',
|
||||
bl = 0,
|
||||
it = 0,
|
||||
fs = 10,
|
||||
cl = 0,
|
||||
ul = 0
|
||||
) {
|
||||
// luckysheet:ff(样式), fc(颜色), bl(粗体), it(斜体), fs(大小), cl(删除线), ul(下划线)
|
||||
const luckyToExcel = {
|
||||
0: '微软雅黑',
|
||||
1: '宋体(Song)',
|
||||
2: '黑体(ST Heiti)',
|
||||
3: '楷体(ST Kaiti)',
|
||||
4: '仿宋(ST FangSong)',
|
||||
5: '新宋体(ST Song)',
|
||||
6: '华文新魏',
|
||||
7: '华文行楷',
|
||||
8: '华文隶书',
|
||||
9: 'Arial',
|
||||
10: 'Times New Roman ',
|
||||
11: 'Tahoma ',
|
||||
12: 'Verdana',
|
||||
num2bl: function(num) {
|
||||
return num === 0 ? false : true
|
||||
}
|
||||
}
|
||||
// 出现Bug,导入的时候ff为luckyToExcel的val
|
||||
|
||||
let font = {
|
||||
name: typeof ff === 'number' ? luckyToExcel[ff] : ff,
|
||||
family: 1,
|
||||
size: fs,
|
||||
color: { argb: fc.replace('#', '') },
|
||||
bold: luckyToExcel.num2bl(bl),
|
||||
italic: luckyToExcel.num2bl(it),
|
||||
underline: luckyToExcel.num2bl(ul),
|
||||
strike: luckyToExcel.num2bl(cl)
|
||||
}
|
||||
|
||||
return font
|
||||
}
|
||||
|
||||
var alignmentConvert = function(
|
||||
vt = 'default',
|
||||
ht = 'default',
|
||||
tb = 'default',
|
||||
tr = 'default'
|
||||
) {
|
||||
// luckysheet:vt(垂直), ht(水平), tb(换行), tr(旋转)
|
||||
const luckyToExcel = {
|
||||
vertical: {
|
||||
0: 'middle',
|
||||
1: 'top',
|
||||
2: 'bottom',
|
||||
default: 'top'
|
||||
},
|
||||
horizontal: {
|
||||
0: 'center',
|
||||
1: 'left',
|
||||
2: 'right',
|
||||
default: 'left'
|
||||
},
|
||||
wrapText: {
|
||||
0: false,
|
||||
1: false,
|
||||
2: true,
|
||||
default: false
|
||||
},
|
||||
textRotation: {
|
||||
0: 0,
|
||||
1: 45,
|
||||
2: -45,
|
||||
3: 'vertical',
|
||||
4: 90,
|
||||
5: -90,
|
||||
default: 0
|
||||
}
|
||||
}
|
||||
|
||||
let alignment = {
|
||||
vertical: luckyToExcel.vertical[vt],
|
||||
horizontal: luckyToExcel.horizontal[ht],
|
||||
wrapText: luckyToExcel.wrapText[tb],
|
||||
textRotation: luckyToExcel.textRotation[tr]
|
||||
}
|
||||
return alignment
|
||||
}
|
||||
|
||||
var borderConvert = function(borderType, style = 1, color = '#000') {
|
||||
// 对应luckysheet的config中borderinfo的的参数
|
||||
if (!borderType) {
|
||||
return {}
|
||||
}
|
||||
const luckyToExcel = {
|
||||
type: {
|
||||
'border-all': 'all',
|
||||
'border-top': 'top',
|
||||
'border-right': 'right',
|
||||
'border-bottom': 'bottom',
|
||||
'border-left': 'left'
|
||||
},
|
||||
style: {
|
||||
0: 'none',
|
||||
1: 'thin',
|
||||
2: 'hair',
|
||||
3: 'dotted',
|
||||
4: 'dashDot', // 'Dashed',
|
||||
5: 'dashDot',
|
||||
6: 'dashDotDot',
|
||||
7: 'double',
|
||||
8: 'medium',
|
||||
9: 'mediumDashed',
|
||||
10: 'mediumDashDot',
|
||||
11: 'mediumDashDotDot',
|
||||
12: 'slantDashDot',
|
||||
13: 'thick'
|
||||
}
|
||||
}
|
||||
let template = {
|
||||
style: luckyToExcel.style[style],
|
||||
color: { argb: color.replace('#', '') }
|
||||
}
|
||||
let border = {}
|
||||
if (luckyToExcel.type[borderType] === 'all') {
|
||||
border['top'] = template
|
||||
border['right'] = template
|
||||
border['bottom'] = template
|
||||
border['left'] = template
|
||||
} else {
|
||||
border[luckyToExcel.type[borderType]] = template
|
||||
}
|
||||
// console.log('border', border)
|
||||
return border
|
||||
}
|
||||
|
||||
function addborderToCell(borders, row_index, col_index) {
|
||||
let border = {}
|
||||
const luckyExcel = {
|
||||
type: {
|
||||
l: 'left',
|
||||
r: 'right',
|
||||
b: 'bottom',
|
||||
t: 'top'
|
||||
},
|
||||
style: {
|
||||
0: 'none',
|
||||
1: 'thin',
|
||||
2: 'hair',
|
||||
3: 'dotted',
|
||||
4: 'dashDot', // 'Dashed',
|
||||
5: 'dashDot',
|
||||
6: 'dashDotDot',
|
||||
7: 'double',
|
||||
8: 'medium',
|
||||
9: 'mediumDashed',
|
||||
10: 'mediumDashDot',
|
||||
11: 'mediumDashDotDot',
|
||||
12: 'slantDashDot',
|
||||
13: 'thick'
|
||||
}
|
||||
}
|
||||
// console.log('borders', borders)
|
||||
for (const bor in borders) {
|
||||
// console.log(bor)
|
||||
if (borders[bor].color.indexOf('rgb') === -1) {
|
||||
border[luckyExcel.type[bor]] = {
|
||||
style: luckyExcel.style[borders[bor].style],
|
||||
color: { argb: borders[bor].color.replace('#', '') }
|
||||
}
|
||||
} else {
|
||||
border[luckyExcel.type[bor]] = {
|
||||
style: luckyExcel.style[borders[bor].style],
|
||||
color: { argb: borders[bor].color }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return border
|
||||
}
|
||||
|
||||
function createCellPos(n) {
|
||||
let ordA = 'A'.charCodeAt(0)
|
||||
|
||||
let ordZ = 'Z'.charCodeAt(0)
|
||||
let len = ordZ - ordA + 1
|
||||
let s = ''
|
||||
while (n >= 0) {
|
||||
s = String.fromCharCode((n % len) + ordA) + s
|
||||
|
||||
n = Math.floor(n / len) - 1
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
export {
|
||||
exportExcel
|
||||
}
|
||||
115
src/views/system/reportForms/form.vue
Normal file
115
src/views/system/reportForms/form.vue
Normal file
@@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<el-dialog draggable :title="title" v-model="formVisible" width="30%" :before-close="closeDialog">
|
||||
<el-form :model="formdata" label-width="100px" :rules="rules" ref="ruleForm">
|
||||
<el-form-item label="模板名称:" prop="name">
|
||||
<el-input placeholder="模板名称" v-model="formdata.name" style="width: 100%"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="部门:" prop="deptId">
|
||||
<Area
|
||||
v-model="formdata.deptId"
|
||||
style="width: 100%"
|
||||
collapse-tags
|
||||
:props="{ multiple: true, label: 'name', value: 'id', emitPath: false }"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="模板类型:" prop="reportType">
|
||||
<el-select style="width: 100%" v-model="formdata.reportType" placeholder="请选择模板类型">
|
||||
<el-option
|
||||
v-for="item in classificationData"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.id"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="报表类型:" prop="reportForm">
|
||||
<el-select style="width: 100%" v-model="formdata.reportForm" placeholder="请选择报表类型">
|
||||
<el-option
|
||||
v-for="item in reportFormList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="closeDialog">取 消</el-button>
|
||||
<el-button type="primary" @click="preservation">确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import Area from '@/components/form/area/index.vue'
|
||||
import { getCustomReportTemplateById } from '@/api/harmonic-boot/luckyexcel'
|
||||
import { ref, reactive } from 'vue'
|
||||
const emit = defineEmits(['submitForm'])
|
||||
const title = ref('')
|
||||
const list = ref({})
|
||||
const ruleForm = ref()
|
||||
const formVisible = ref(false)
|
||||
const classificationData = [
|
||||
{
|
||||
label: '电能质量报表类型',
|
||||
id: '1'
|
||||
},
|
||||
{
|
||||
label: '用能报表类型',
|
||||
id: '2'
|
||||
}
|
||||
]
|
||||
const reportFormList = [
|
||||
{
|
||||
value: '1',
|
||||
label: '分析报表'
|
||||
},
|
||||
{
|
||||
value: '2',
|
||||
label: '统计报表'
|
||||
},
|
||||
{
|
||||
value: '3',
|
||||
label: '自定义报表'
|
||||
}
|
||||
]
|
||||
const rules = {
|
||||
name: [{ required: true, message: '请输入模板名称', trigger: 'blur' }],
|
||||
deptId: [{ required: true, message: '请选择部门', trigger: 'change' }],
|
||||
reportType: [{ required: true, message: '请选择模板类型', trigger: 'change' }],
|
||||
reportForm: [{ required: true, message: '请选择报表类型', trigger: 'change' }]
|
||||
}
|
||||
const formdata = ref({
|
||||
name: '',
|
||||
deptId: [],
|
||||
reportType: '',
|
||||
reportForm: ''
|
||||
})
|
||||
// 确定
|
||||
const preservation = () => {
|
||||
ruleForm.value.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
emit('submitForm', formdata.value, title.value)
|
||||
formVisible.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 关闭
|
||||
const closeDialog = () => {
|
||||
formVisible.value = false
|
||||
}
|
||||
const open = (text: string, row?: any) => {
|
||||
title.value = text
|
||||
if (row.id) {
|
||||
getCustomReportTemplateById({ id: row.id }).then(res => {
|
||||
formdata.value = res.data
|
||||
formdata.value.deptId = res.data.valueTitle.split(',')
|
||||
})
|
||||
}
|
||||
|
||||
formVisible.value = true
|
||||
}
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
133
src/views/system/reportForms/index.vue
Normal file
133
src/views/system/reportForms/index.vue
Normal file
@@ -0,0 +1,133 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<div v-show="show && lookShow">
|
||||
<TableHeader ref="TableHeaderRef">
|
||||
<template #operation>
|
||||
<el-button icon="el-icon-Plus" type="primary" @click="add">新增</el-button>
|
||||
</template>
|
||||
</TableHeader>
|
||||
<Table ref="tableRef" />
|
||||
</div>
|
||||
<luckysheet ref="luckysheetRef" v-if="!show" @shutDown="shutDown" />
|
||||
<!-- 查看 -->
|
||||
<look ref="lookRef" v-if="!lookShow" @shutDown="shutDown" />
|
||||
<!-- 绑定 -->
|
||||
<department ref="departmentRef" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide, nextTick } from 'vue'
|
||||
import TableStore from '@/utils/tableStore'
|
||||
import Table from '@/components/table/index.vue'
|
||||
import TableHeader from '@/components/table/header/index.vue'
|
||||
import { delTemplate } from '@/api/harmonic-boot/luckyexcel'
|
||||
import { useDictData } from '@/stores/dictData'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import luckysheet from './luckysheet.vue'
|
||||
import look from './look.vue'
|
||||
import department from './department.vue'
|
||||
defineOptions({
|
||||
name: 'Distributedphotovoltaic/templateConfiguration'
|
||||
})
|
||||
const luckysheetRef = ref()
|
||||
const lookRef = ref()
|
||||
const departmentRef = ref()
|
||||
const show = ref(true)
|
||||
const lookShow = ref(true)
|
||||
const tableStore: any = new TableStore({
|
||||
url: '/harmonic-boot/customReport/getTemplateList',
|
||||
method: 'POST',
|
||||
isWebPaging: true,
|
||||
column: [
|
||||
{ field: 'name', title: '模板名称' },
|
||||
{ field: 'createBy', title: '创建用户' },
|
||||
{ field: 'updateBy', title: '更新用户' },
|
||||
{ field: 'createTime', title: '创建时间' },
|
||||
{ field: 'updateTime', title: '更新时间' },
|
||||
{
|
||||
title: '操作',
|
||||
width: '220',
|
||||
render: 'buttons',
|
||||
buttons: [
|
||||
{
|
||||
name: 'edit',
|
||||
title: '查看 ',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-Plus',
|
||||
render: 'basicButton',
|
||||
click: row => {
|
||||
lookShow.value = false
|
||||
setTimeout(() => {
|
||||
lookRef.value.open(row)
|
||||
}, 10)
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
title: '编辑',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-Plus',
|
||||
render: 'basicButton',
|
||||
click: row => {
|
||||
show.value = false
|
||||
setTimeout(() => {
|
||||
luckysheetRef.value.open('编辑报表模板', row)
|
||||
}, 10)
|
||||
}
|
||||
},
|
||||
// {
|
||||
// name: 'edit',
|
||||
// title: '绑定',
|
||||
// type: 'primary',
|
||||
// icon: 'el-icon-Plus',
|
||||
// render: 'basicButton',
|
||||
// click: row => {
|
||||
// departmentRef.value.open(row)
|
||||
// }
|
||||
// },
|
||||
{
|
||||
name: 'del',
|
||||
text: '删除',
|
||||
type: 'danger',
|
||||
icon: 'el-icon-Delete',
|
||||
render: 'confirmButton',
|
||||
popconfirm: {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
confirmButtonType: 'danger',
|
||||
title: '确定删除?'
|
||||
},
|
||||
click: row => {
|
||||
delTemplate({ tempId: row.id, deptId: row.deptId }).then(res => {
|
||||
ElMessage.success('删除成功')
|
||||
tableStore.index()
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
loadCallback: () => {}
|
||||
})
|
||||
tableStore.table.params = {}
|
||||
tableStore.table.params.pageSize = 20
|
||||
tableStore.table.params.pageNum = 1
|
||||
|
||||
provide('tableStore', tableStore)
|
||||
// 关闭
|
||||
const shutDown = () => {
|
||||
show.value = true
|
||||
lookShow.value = true
|
||||
tableStore.index()
|
||||
}
|
||||
const add = () => {
|
||||
show.value = false
|
||||
setTimeout(() => {
|
||||
luckysheetRef.value.open('新增报表模板')
|
||||
}, 10)
|
||||
}
|
||||
onMounted(() => {
|
||||
tableStore.index()
|
||||
})
|
||||
</script>
|
||||
105
src/views/system/reportForms/look.vue
Normal file
105
src/views/system/reportForms/look.vue
Normal file
@@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<div class="mb10" style="display: flex; justify-content: flex-end">
|
||||
<el-upload
|
||||
ref="upload"
|
||||
action=""
|
||||
:auto-upload="false"
|
||||
:show-file-list="false"
|
||||
:limit="1"
|
||||
:on-change="beforeUpload"
|
||||
>
|
||||
<el-button icon="el-icon-Upload" type="primary" class="mr10">导入excel</el-button>
|
||||
</el-upload>
|
||||
<el-button @click="downloadExcel" class="" type="primary" icon="el-icon-Download">导出excel</el-button>
|
||||
<el-button type="primary" icon="el-icon-ArrowLeftBold" @click="emit('shutDown')">返回</el-button>
|
||||
</div>
|
||||
|
||||
<div style="display: flex">
|
||||
<div id="luckysheet" :style="{ height: height, flex: 1 }"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { exportExcel } from './export.js'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import LuckyExcel from 'luckyexcel'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { viewCustomReportTemplateById } from '@/api/harmonic-boot/luckyexcel'
|
||||
const emit = defineEmits(['shutDown'])
|
||||
|
||||
const height = mainHeight(65).height
|
||||
const options: any = ref({
|
||||
container: 'luckysheet',
|
||||
title: '', // 表 头名
|
||||
lang: 'zh', // 中文
|
||||
showtoolbar: false, // 是否显示工具栏
|
||||
showinfobar: false, // 是否显示顶部信息栏
|
||||
showsheetbar: true, // 是否显示底部sheet按钮
|
||||
data: [
|
||||
{
|
||||
name: 'Cell',
|
||||
index: 0,
|
||||
defaultRowHeight: 27,
|
||||
defaultColWidth: 105,
|
||||
chart: [] //图表配置
|
||||
}
|
||||
]
|
||||
})
|
||||
// 加载luckysheet
|
||||
const info = () => {
|
||||
luckysheet.create(options.value)
|
||||
}
|
||||
//绑定value
|
||||
const setValue = (e: any) => {
|
||||
let data = luckysheet.getRange()
|
||||
luckysheet.setCellValue(
|
||||
data[0].row[0],
|
||||
data[0].column[0],
|
||||
{
|
||||
v: e[e.length - 1],
|
||||
tr: e
|
||||
}
|
||||
// checkedNodes[0].data.label
|
||||
)
|
||||
}
|
||||
// 下载表格
|
||||
const downloadExcel = () => {
|
||||
exportExcel(luckysheet.getAllSheets(), '报表模板')
|
||||
}
|
||||
// 导入
|
||||
const beforeUpload = (file: any) => {
|
||||
LuckyExcel.transformExcelToLucky(file.raw, function (exportJson: any) {
|
||||
if (exportJson.sheets == null || exportJson.sheets.length == 0) {
|
||||
ElMessage.warning('读取excel文件内容失败,目前只能上传xlsx文件!')
|
||||
return
|
||||
}
|
||||
luckysheet.destroy()
|
||||
options.value.title = exportJson.info.name
|
||||
options.value.data = exportJson.sheets
|
||||
luckysheet.create(options.value)
|
||||
})
|
||||
}
|
||||
|
||||
const open = async (row: any) => {
|
||||
|
||||
await viewCustomReportTemplateById({ id: row.id }).then((Response:any) => {
|
||||
Response.forEach((item: any) => {
|
||||
item.celldata.forEach((k: any) => {
|
||||
item.data[k.r][k.c].v = k.v
|
||||
})
|
||||
})
|
||||
options.value.data = Response
|
||||
})
|
||||
|
||||
info()
|
||||
}
|
||||
defineExpose({ open })
|
||||
onMounted(() => {})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-tab-pane) {
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
144
src/views/system/reportForms/luckysheet.vue
Normal file
144
src/views/system/reportForms/luckysheet.vue
Normal file
@@ -0,0 +1,144 @@
|
||||
<template>
|
||||
<div class="default-main">
|
||||
<div class="mb10" style="display: flex; justify-content: flex-end">
|
||||
<el-upload
|
||||
ref="upload"
|
||||
action=""
|
||||
:auto-upload="false"
|
||||
:show-file-list="false"
|
||||
:limit="1"
|
||||
:on-change="beforeUpload"
|
||||
>
|
||||
<el-button icon="el-icon-Upload" type="primary" class="mr10">导入excel</el-button>
|
||||
</el-upload>
|
||||
<el-button @click="downloadExcel" class="" type="primary" icon="el-icon-Download">导出excel</el-button>
|
||||
<el-button type="primary" icon="el-icon-Check" @click="preservation">保存</el-button>
|
||||
<el-button type="primary" icon="el-icon-ArrowLeftBold" @click="emit('shutDown')">返回</el-button>
|
||||
</div>
|
||||
|
||||
<div style="display: flex">
|
||||
<div id="luckysheet" :style="{ height: height, flex: 1 }"></div>
|
||||
<bind style="width: 500px" class="ml10" @setValue="setValue" />
|
||||
</div>
|
||||
<!-- 信息框 -->
|
||||
<addForm ref="formFer" @submitForm="submitForm" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { exportExcel } from './export.js'
|
||||
import { mainHeight } from '@/utils/layout'
|
||||
import LuckyExcel from 'luckyexcel'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { addTemplate, dateTemplateup, viewCustomReportTemplateById } from '@/api/harmonic-boot/luckyexcel'
|
||||
import bind from './bind.vue'
|
||||
import addForm from './form.vue'
|
||||
const emit = defineEmits(['shutDown'])
|
||||
const formFer = ref()
|
||||
const title = ref('')
|
||||
const list = ref({})
|
||||
const height = mainHeight(65).height
|
||||
const options: any = ref({
|
||||
container: 'luckysheet',
|
||||
title: '', // 表 头名
|
||||
lang: 'zh', // 中文
|
||||
showtoolbar: true, // 是否显示工具栏
|
||||
showinfobar: false, // 是否显示顶部信息栏
|
||||
showsheetbar: true, // 是否显示底部sheet按钮
|
||||
data: [
|
||||
{
|
||||
name: 'Cell',
|
||||
index: 0,
|
||||
defaultRowHeight: 27,
|
||||
defaultColWidth: 105,
|
||||
chart: [] //图表配置
|
||||
}
|
||||
]
|
||||
})
|
||||
// 加载luckysheet
|
||||
const info = () => {
|
||||
luckysheet.create(options.value)
|
||||
}
|
||||
//绑定value
|
||||
const setValue = (e: any) => {
|
||||
let data = luckysheet.getRange()
|
||||
luckysheet.setCellValue(
|
||||
data[0].row[0],
|
||||
data[0].column[0],
|
||||
{
|
||||
v: e[e.length - 1],
|
||||
tr: e
|
||||
}
|
||||
// checkedNodes[0].data.label
|
||||
)
|
||||
}
|
||||
// 下载表格
|
||||
const downloadExcel = () => {
|
||||
exportExcel(luckysheet.getAllSheets(), '报表模板')
|
||||
}
|
||||
// 导入
|
||||
const beforeUpload = (file: any) => {
|
||||
LuckyExcel.transformExcelToLucky(file.raw, function (exportJson: any) {
|
||||
if (exportJson.sheets == null || exportJson.sheets.length == 0) {
|
||||
ElMessage.warning('读取excel文件内容失败,目前只能上传xlsx文件!')
|
||||
return
|
||||
}
|
||||
luckysheet.destroy()
|
||||
options.value.title = exportJson.info.name
|
||||
options.value.data = exportJson.sheets
|
||||
luckysheet.create(options.value)
|
||||
})
|
||||
}
|
||||
// 保存
|
||||
const preservation = () => {
|
||||
formFer.value.open(title.value, list.value)
|
||||
}
|
||||
// 新增
|
||||
const submitForm = (formdata: any, text: string) => {
|
||||
console.log('🚀 ~ submitForm ~ text:', text)
|
||||
let userStr = JSON.stringify(luckysheet.getAllSheets())
|
||||
let blob = new Blob([userStr], {
|
||||
type: 'application/json;charset=UTF-8'
|
||||
})
|
||||
let files = new window.File([blob], 'content.json', {
|
||||
type: 'application/json;charset=UTF-8'
|
||||
})
|
||||
let params = new FormData()
|
||||
|
||||
params.append('fileContent', files)
|
||||
params.append('deptId', formdata.deptId)
|
||||
params.append('valueTitle', formdata.deptId)
|
||||
params.append('name', formdata.name)
|
||||
params.append('reportType', formdata.reportType)
|
||||
params.append('reportForm', formdata.reportForm)
|
||||
if (text == '新增报表模板') {
|
||||
addTemplate(params).then(res => {
|
||||
ElMessage.success('新增成功!')
|
||||
emit('shutDown')
|
||||
})
|
||||
} else if (text == '编辑报表模板') {
|
||||
params.append('id', list.value.id)
|
||||
dateTemplateup(params).then(res => {
|
||||
ElMessage.success('编辑成功!')
|
||||
emit('shutDown')
|
||||
})
|
||||
}
|
||||
}
|
||||
const open = async (text: string, row?: any) => {
|
||||
title.value = text
|
||||
if (row) {
|
||||
list.value = row
|
||||
await viewCustomReportTemplateById({ id: row.id }).then(Response => {
|
||||
options.value.data = Response
|
||||
})
|
||||
}
|
||||
info()
|
||||
}
|
||||
defineExpose({ open })
|
||||
onMounted(() => {})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-tab-pane) {
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user