Showing
7 changed files
with
953 additions
and
0 deletions
1 | +<template> | ||
2 | + <div> | ||
3 | + <BasicModal | ||
4 | + v-bind="$attrs" | ||
5 | + width="55rem" | ||
6 | + :height="heightNum" | ||
7 | + @register="register" | ||
8 | + title="执行设备及属性" | ||
9 | + @cancel="handleCancel" | ||
10 | + :showOkBtn="false" | ||
11 | + > | ||
12 | + <div> | ||
13 | + <BasicTable @register="registerTable" :dataSource="tableData" /> | ||
14 | + </div> | ||
15 | + </BasicModal> | ||
16 | + </div> | ||
17 | +</template> | ||
18 | +<script setup lang="ts"> | ||
19 | + import { ref, nextTick } from 'vue'; | ||
20 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | ||
21 | + import { BasicTable, useTable } from '/@/components/Table'; | ||
22 | + import { viewDeviceColumn } from './config.data'; | ||
23 | + | ||
24 | + const heightNum = ref(800); | ||
25 | + const tableData: any = ref([]); | ||
26 | + const [registerTable] = useTable({ | ||
27 | + title: '执行设备及属性', | ||
28 | + columns: viewDeviceColumn, | ||
29 | + showIndexColumn: false, | ||
30 | + clickToRowSelect: false, | ||
31 | + showTableSetting: false, | ||
32 | + bordered: true, | ||
33 | + }); | ||
34 | + const [register] = useModalInner((data) => { | ||
35 | + console.log(data); | ||
36 | + const getTableData = () => { | ||
37 | + for (let i = 0; i < 100; i++) { | ||
38 | + tableData.value.push({ | ||
39 | + tdDevice: `设备${i}`, | ||
40 | + attr: `CO${i}、Temp${i}`, | ||
41 | + }); | ||
42 | + } | ||
43 | + }; | ||
44 | + nextTick(() => { | ||
45 | + getTableData(); | ||
46 | + }); | ||
47 | + }); | ||
48 | + const handleCancel = () => {}; | ||
49 | +</script> | ||
50 | +<style></style> |
1 | +<template> | ||
2 | + <BasicDrawer | ||
3 | + v-bind="$attrs" | ||
4 | + @register="registerDrawer" | ||
5 | + showFooter | ||
6 | + :title="getTitle" | ||
7 | + width="30%" | ||
8 | + @ok="handleSubmit" | ||
9 | + > | ||
10 | + <BasicForm @register="registerForm" /> | ||
11 | + </BasicDrawer> | ||
12 | +</template> | ||
13 | +<script lang="ts" setup> | ||
14 | + import { ref, computed, unref, nextTick } from 'vue'; | ||
15 | + import { BasicForm, useForm } from '/@/components/Form'; | ||
16 | + import { formSchema } from './config.data'; | ||
17 | + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | ||
18 | + import { createOrEditCameraManage } from '/@/api/camera/cameraManager'; | ||
19 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
20 | + | ||
21 | + const emit = defineEmits(['success', 'register']); | ||
22 | + const isUpdate = ref(true); | ||
23 | + const editId = ref(''); | ||
24 | + const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({ | ||
25 | + labelWidth: 120, | ||
26 | + schemas: formSchema, | ||
27 | + showActionButtonGroup: false, | ||
28 | + }); | ||
29 | + | ||
30 | + const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => { | ||
31 | + await resetFields(); | ||
32 | + setDrawerProps({ confirmLoading: false }); | ||
33 | + isUpdate.value = !!data?.isUpdate; | ||
34 | + if (unref(isUpdate)) { | ||
35 | + await nextTick(); | ||
36 | + editId.value = data.record.id; | ||
37 | + await setFieldsValue(data.record); | ||
38 | + } else { | ||
39 | + editId.value = ''; | ||
40 | + } | ||
41 | + }); | ||
42 | + | ||
43 | + const getTitle = computed(() => (!unref(isUpdate) ? '新增报表配置' : '编辑报表配置')); | ||
44 | + | ||
45 | + async function handleSubmit() { | ||
46 | + setDrawerProps({ confirmLoading: true }); | ||
47 | + try { | ||
48 | + const { createMessage } = useMessage(); | ||
49 | + const values = await validate(); | ||
50 | + if (!values) return; | ||
51 | + let saveMessage = '添加成功'; | ||
52 | + let updateMessage = '修改成功'; | ||
53 | + await createOrEditCameraManage(values); | ||
54 | + closeDrawer(); | ||
55 | + emit('success'); | ||
56 | + createMessage.success(unref(isUpdate) ? updateMessage : saveMessage); | ||
57 | + } finally { | ||
58 | + setTimeout(() => { | ||
59 | + setDrawerProps({ confirmLoading: false }); | ||
60 | + }, 300); | ||
61 | + } | ||
62 | + } | ||
63 | +</script> |
src/views/report/config/config.data.ts
0 → 100644
1 | +import { BasicColumn, FormSchema } from '/@/components/Table'; | ||
2 | +import type { FormSchema as QFormSchema } from '/@/components/Form/index'; | ||
3 | +import moment from 'moment'; | ||
4 | +import { getOrganizationList } from '/@/api/system/system'; | ||
5 | +import { copyTransFun } from '/@/utils/fnUtils'; | ||
6 | +import { screenLinkPageByDeptIdGetDevice } from '/@/api/ruleengine/ruleengineApi'; | ||
7 | +import { getAttribute } from '/@/api/ruleengine/ruleengineApi'; | ||
8 | + | ||
9 | +export enum TypeEnum { | ||
10 | + IS_TIMING = 'TIMING', | ||
11 | + IS_WEEK = 'week', | ||
12 | + IS_MONTH = 'month', | ||
13 | +} | ||
14 | +export const isTiming = (type: string) => { | ||
15 | + return type === TypeEnum.IS_TIMING; | ||
16 | +}; | ||
17 | +export const isWeek = (type: string) => { | ||
18 | + return type === TypeEnum.IS_WEEK; | ||
19 | +}; | ||
20 | + | ||
21 | +export const isMonth = (type: string) => { | ||
22 | + return type === TypeEnum.IS_MONTH; | ||
23 | +}; | ||
24 | + | ||
25 | + | ||
26 | +export enum AggregateDataEnum { | ||
27 | + MIN = 'MIN', | ||
28 | + MAX = 'MAX', | ||
29 | + AVG = 'AVG', | ||
30 | + SUM = 'SUM', | ||
31 | + COUNT = 'COUNT', | ||
32 | + NONE = 'NONE', | ||
33 | +} | ||
34 | + | ||
35 | +// 表格配置 | ||
36 | +export const columns: BasicColumn[] = [ | ||
37 | + { | ||
38 | + title: '配置名称', | ||
39 | + dataIndex: '1', | ||
40 | + width: 80, | ||
41 | + }, | ||
42 | + { | ||
43 | + title: '所属组织', | ||
44 | + dataIndex: '2', | ||
45 | + width: 120, | ||
46 | + }, | ||
47 | + { | ||
48 | + title: '数据类型', | ||
49 | + dataIndex: '3', | ||
50 | + width: 120, | ||
51 | + }, | ||
52 | + { | ||
53 | + title: '配置状态', | ||
54 | + dataIndex: '4', | ||
55 | + width: 120, | ||
56 | + }, | ||
57 | + { | ||
58 | + title: '执行方式', | ||
59 | + dataIndex: '5', | ||
60 | + width: 160, | ||
61 | + }, | ||
62 | + { | ||
63 | + title: '执行设备', | ||
64 | + dataIndex: '6', | ||
65 | + width: 160, | ||
66 | + slots: { customRender: 'doDeviceSlot' }, | ||
67 | + }, | ||
68 | + { | ||
69 | + title: '创建人', | ||
70 | + dataIndex: '7', | ||
71 | + width: 180, | ||
72 | + }, | ||
73 | + { | ||
74 | + title: '创建日期', | ||
75 | + dataIndex: '8', | ||
76 | + width: 180, | ||
77 | + }, | ||
78 | +]; | ||
79 | +export const viewDeviceColumn: BasicColumn[] = [ | ||
80 | + { | ||
81 | + title: '设备', | ||
82 | + dataIndex: 'tdDevice', | ||
83 | + width: 80, | ||
84 | + }, | ||
85 | + { | ||
86 | + title: '属性', | ||
87 | + dataIndex: 'attr', | ||
88 | + width: 120, | ||
89 | + }, | ||
90 | +]; | ||
91 | + | ||
92 | +// 查询配置 | ||
93 | +export const searchFormSchema: FormSchema[] = [ | ||
94 | + { | ||
95 | + field: '1', | ||
96 | + label: '配置名称', | ||
97 | + component: 'Input', | ||
98 | + colProps: { span: 6 }, | ||
99 | + componentProps: { | ||
100 | + maxLength: 36, | ||
101 | + placeholder: '请输入配置名称', | ||
102 | + }, | ||
103 | + }, | ||
104 | + { | ||
105 | + field: '2', | ||
106 | + label: '配置状态', | ||
107 | + component: 'Select', | ||
108 | + colProps: { span: 6 }, | ||
109 | + componentProps: { | ||
110 | + options: [ | ||
111 | + { | ||
112 | + label: '启用', | ||
113 | + value: 1, | ||
114 | + }, | ||
115 | + { | ||
116 | + label: '禁用', | ||
117 | + value: 0, | ||
118 | + }, | ||
119 | + ], | ||
120 | + placeholder: '请选择配置状态', | ||
121 | + }, | ||
122 | + }, | ||
123 | + { | ||
124 | + field: '3', | ||
125 | + label: '创建时间', | ||
126 | + component: 'RangePicker', | ||
127 | + componentProps: { | ||
128 | + showTime: { | ||
129 | + defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')], | ||
130 | + }, | ||
131 | + }, | ||
132 | + colProps: { span: 6 }, | ||
133 | + }, | ||
134 | +]; | ||
135 | + | ||
136 | +// 新增编辑配置 | ||
137 | +export const formSchema: QFormSchema[] = [ | ||
138 | + { | ||
139 | + field: '1', | ||
140 | + label: '报表名称', | ||
141 | + colProps: { span: 24 }, | ||
142 | + helpMessage: ['报表配置', '只对拥有数值型属性', '的设备才能配置'], | ||
143 | + required: true, | ||
144 | + component: 'Input', | ||
145 | + componentProps: { | ||
146 | + maxLength: 255, | ||
147 | + placeholder: '请输入报表名称', | ||
148 | + }, | ||
149 | + }, | ||
150 | + { | ||
151 | + field: 'organizationId', | ||
152 | + label: '所属组织', | ||
153 | + colProps: { span: 24 }, | ||
154 | + component: 'ApiTreeSelect', | ||
155 | + required: true, | ||
156 | + componentProps: ({ formActionType }) => { | ||
157 | + const { updateSchema } = formActionType; | ||
158 | + return { | ||
159 | + async onChange(e) { | ||
160 | + if (e) { | ||
161 | + //获取该组织下的设备 | ||
162 | + const { items } = await screenLinkPageByDeptIdGetDevice({ | ||
163 | + organizationId: e, | ||
164 | + }); | ||
165 | + const options = items.map((item) => { | ||
166 | + return { | ||
167 | + label: item.name, | ||
168 | + value: item.tbDeviceId, | ||
169 | + }; | ||
170 | + }); | ||
171 | + updateSchema({ | ||
172 | + field: 'entityId', | ||
173 | + componentProps: { | ||
174 | + options, | ||
175 | + async onChange(e1) { | ||
176 | + if (e1) { | ||
177 | + const res = await getAttribute(e, e1.join(',')); | ||
178 | + const attr = res.map((item) => { | ||
179 | + return { | ||
180 | + label: item, | ||
181 | + value: item, | ||
182 | + }; | ||
183 | + }); | ||
184 | + updateSchema({ | ||
185 | + field: 'attr', | ||
186 | + componentProps: { | ||
187 | + options: attr, | ||
188 | + }, | ||
189 | + }); | ||
190 | + } | ||
191 | + }, | ||
192 | + }, | ||
193 | + }); | ||
194 | + } | ||
195 | + }, | ||
196 | + maxLength: 250, | ||
197 | + placeholder: '请选择所属组织', | ||
198 | + api: async () => { | ||
199 | + const data = await getOrganizationList(); | ||
200 | + copyTransFun(data as any as any[]); | ||
201 | + return data; | ||
202 | + }, | ||
203 | + }; | ||
204 | + }, | ||
205 | + }, | ||
206 | + { | ||
207 | + field: '3', | ||
208 | + label: '描述', | ||
209 | + colProps: { span: 24 }, | ||
210 | + component: 'InputTextArea', | ||
211 | + componentProps: { | ||
212 | + maxLength: 255, | ||
213 | + placeholder: '请输入描述', | ||
214 | + }, | ||
215 | + }, | ||
216 | + { | ||
217 | + field: 'actionS', | ||
218 | + component: 'RadioGroup', | ||
219 | + label: '执行方式', | ||
220 | + colProps: { | ||
221 | + span: 24, | ||
222 | + }, | ||
223 | + defaultValue: '1', | ||
224 | + componentProps: { | ||
225 | + placeholder: '请选择执行方式', | ||
226 | + options: [ | ||
227 | + { | ||
228 | + label: '立即执行', | ||
229 | + value: '1', | ||
230 | + }, | ||
231 | + { | ||
232 | + label: '定时执行', | ||
233 | + value: 'TIMING', | ||
234 | + }, | ||
235 | + ], | ||
236 | + }, | ||
237 | + }, | ||
238 | + { | ||
239 | + field: 'timeWeek', | ||
240 | + component: 'Select', | ||
241 | + label: '周期', | ||
242 | + required: true, | ||
243 | + colProps: { span: 24 }, | ||
244 | + defaultValue: '1', | ||
245 | + componentProps: { | ||
246 | + placeholder: '请选择周期', | ||
247 | + options: [ | ||
248 | + { label: '每日', value: 'day' }, | ||
249 | + { label: '每周', value: 'week' }, | ||
250 | + { label: '每月', value: 'month' }, | ||
251 | + ], | ||
252 | + }, | ||
253 | + ifShow: ({ values }) => isTiming(values.actionS), | ||
254 | + }, | ||
255 | + { | ||
256 | + field: '5', | ||
257 | + component: 'Select', | ||
258 | + label: '每周', | ||
259 | + required: true, | ||
260 | + colProps: { span: 24 }, | ||
261 | + defaultValue: '1', | ||
262 | + componentProps: { | ||
263 | + placeholder: '请选择周期', | ||
264 | + options: [ | ||
265 | + { label: '星期一', value: '1' }, | ||
266 | + { label: '星期二', value: '2' }, | ||
267 | + { label: '星期三', value: '3' }, | ||
268 | + { label: '星期四', value: '3' }, | ||
269 | + { label: '星期五', value: '3' }, | ||
270 | + ], | ||
271 | + }, | ||
272 | + ifShow: ({ values }) => isWeek(values.timeWeek), | ||
273 | + }, | ||
274 | + { | ||
275 | + field: '5', | ||
276 | + component: 'Select', | ||
277 | + label: '每月', | ||
278 | + required: true, | ||
279 | + colProps: { span: 24 }, | ||
280 | + defaultValue: '1', | ||
281 | + componentProps: { | ||
282 | + placeholder: '请选择周期', | ||
283 | + options: [ | ||
284 | + { label: '1日', value: '1' }, | ||
285 | + { label: '2日', value: '7' }, | ||
286 | + { label: '3日', value: '30' }, | ||
287 | + ], | ||
288 | + }, | ||
289 | + ifShow: ({ values }) => isMonth(values.timeWeek), | ||
290 | + }, | ||
291 | + { | ||
292 | + field: '6', | ||
293 | + component: 'Select', | ||
294 | + label: '时间', | ||
295 | + required: true, | ||
296 | + colProps: { span: 24 }, | ||
297 | + defaultValue: '1', | ||
298 | + componentProps: { | ||
299 | + placeholder: '请选择时间', | ||
300 | + options: [ | ||
301 | + { label: '00点', value: '1' }, | ||
302 | + { label: '01点', value: '2' }, | ||
303 | + { label: '02点', value: '3' }, | ||
304 | + ], | ||
305 | + }, | ||
306 | + ifShow: ({ values }) => isTiming(values.actionS), | ||
307 | + }, | ||
308 | + { | ||
309 | + field: 'entityId', | ||
310 | + label: '设备', | ||
311 | + required: true, | ||
312 | + component: 'Select', | ||
313 | + componentProps: { | ||
314 | + placeholder: '请选择设备', | ||
315 | + mode: 'multiple', | ||
316 | + }, | ||
317 | + colProps: { span: 24 }, | ||
318 | + }, | ||
319 | + { | ||
320 | + field: '7', | ||
321 | + component: 'RadioGroup', | ||
322 | + label: '属性性质', | ||
323 | + required: true, | ||
324 | + colProps: { | ||
325 | + span: 24, | ||
326 | + }, | ||
327 | + defaultValue: '1', | ||
328 | + componentProps: { | ||
329 | + placeholder: '请选择属性性质', | ||
330 | + options: [ | ||
331 | + { | ||
332 | + label: '共有', | ||
333 | + value: '1', | ||
334 | + }, | ||
335 | + { | ||
336 | + label: '全部', | ||
337 | + value: '2', | ||
338 | + }, | ||
339 | + ], | ||
340 | + }, | ||
341 | + }, | ||
342 | + { | ||
343 | + field: 'attr', | ||
344 | + label: '设备属性', | ||
345 | + required: true, | ||
346 | + component: 'Select', | ||
347 | + componentProps: { | ||
348 | + placeholder: '请选择设备属性', | ||
349 | + }, | ||
350 | + colProps: { span: 24 }, | ||
351 | + }, | ||
352 | + { | ||
353 | + field: '9', | ||
354 | + label: '数据类型', | ||
355 | + required: true, | ||
356 | + component: 'Select', | ||
357 | + componentProps: { | ||
358 | + placeholder: '请选择数据类型', | ||
359 | + options: [ | ||
360 | + { label: '历史数据', value: '1' }, | ||
361 | + { label: '同比', value: '2' }, | ||
362 | + { label: '环比', value: '2' }, | ||
363 | + ], | ||
364 | + }, | ||
365 | + colProps: { span: 24 }, | ||
366 | + }, | ||
367 | + { | ||
368 | + field: '10', | ||
369 | + label: '聚合条件', | ||
370 | + required: true, | ||
371 | + component: 'Select', | ||
372 | + componentProps: { | ||
373 | + placeholder: '请选择聚合条件', | ||
374 | + options: [ | ||
375 | + { | ||
376 | + label: '平均值', | ||
377 | + value: AggregateDataEnum.AVG, | ||
378 | + }, | ||
379 | + { | ||
380 | + label: '总和', | ||
381 | + value: AggregateDataEnum.SUM, | ||
382 | + }, | ||
383 | + { | ||
384 | + label: '最大值', | ||
385 | + value: AggregateDataEnum.MAX, | ||
386 | + }, | ||
387 | + { | ||
388 | + label: '最小值', | ||
389 | + value: AggregateDataEnum.MIN, | ||
390 | + }, | ||
391 | + ], | ||
392 | + }, | ||
393 | + colProps: { span: 24 }, | ||
394 | + }, | ||
395 | + { | ||
396 | + field: '9', | ||
397 | + label: '查询周期', | ||
398 | + required: true, | ||
399 | + component: 'Select', | ||
400 | + componentProps: { | ||
401 | + placeholder: '请选择查询周期', | ||
402 | + options: [ | ||
403 | + { label: '1分钟', value: '60000' }, | ||
404 | + { label: '2分钟', value: '120000' }, | ||
405 | + { label: '3分钟', value: '180000' }, | ||
406 | + ], | ||
407 | + }, | ||
408 | + colProps: { span: 24 }, | ||
409 | + }, | ||
410 | + { | ||
411 | + field: '10', | ||
412 | + label: '间隔时间', | ||
413 | + required: true, | ||
414 | + component: 'Select', | ||
415 | + componentProps: { | ||
416 | + placeholder: '请选择间隔时间', | ||
417 | + options: [ | ||
418 | + { label: '1秒', value: '1000' }, | ||
419 | + { label: '5秒', value: '5000' }, | ||
420 | + { label: '10秒', value: '10000' }, | ||
421 | + { label: '15秒', value: '150000' }, | ||
422 | + ], | ||
423 | + }, | ||
424 | + colProps: { span: 24 }, | ||
425 | + }, | ||
426 | +]; |
src/views/report/config/index.vue
0 → 100644
1 | +<template> | ||
2 | + <div> | ||
3 | + <BasicTable :clickToRowSelect="false" @register="registerTable" :searchInfo="searchInfo"> | ||
4 | + <template #toolbar> | ||
5 | + <Authority value="api:yt:report:post"> | ||
6 | + <a-button type="primary" @click="handleCreateOrEdit(null)"> 新增报表 </a-button> | ||
7 | + </Authority> | ||
8 | + <Authority value="api:yt:report:get"> | ||
9 | + <a-button type="primary" @click="go('/report/export')"> 下载报表 </a-button> | ||
10 | + </Authority> | ||
11 | + <Authority value="api:yt:report:delete"> | ||
12 | + <Popconfirm | ||
13 | + title="您确定要批量删除数据" | ||
14 | + ok-text="确定" | ||
15 | + cancel-text="取消" | ||
16 | + @confirm="handleDeleteOrBatchDelete(null)" | ||
17 | + > | ||
18 | + <a-button type="primary" color="error" :disabled="hasBatchDelete"> 批量删除 </a-button> | ||
19 | + </Popconfirm> | ||
20 | + </Authority> | ||
21 | + </template> | ||
22 | + <template #doDeviceSlot="{ record }"> | ||
23 | + <a-button type="text" @click="handleDeviceView(record)"> | ||
24 | + <span style="color: #377dff">查看设备</span> | ||
25 | + </a-button> | ||
26 | + </template> | ||
27 | + <template #action="{ record }"> | ||
28 | + <TableAction | ||
29 | + :actions="[ | ||
30 | + { | ||
31 | + label: '编辑', | ||
32 | + icon: 'clarity:note-edit-line', | ||
33 | + auth: 'api:yt:report:update', | ||
34 | + onClick: handleCreateOrEdit.bind(null, record), | ||
35 | + }, | ||
36 | + { | ||
37 | + label: '删除', | ||
38 | + icon: 'ant-design:delete-outlined', | ||
39 | + auth: 'api:yt:report:delete', | ||
40 | + color: 'error', | ||
41 | + popConfirm: { | ||
42 | + title: '是否确认删除', | ||
43 | + confirm: handleDeleteOrBatchDelete.bind(null, record), | ||
44 | + }, | ||
45 | + }, | ||
46 | + ]" | ||
47 | + /> | ||
48 | + </template> | ||
49 | + </BasicTable> | ||
50 | + <ReportConfigDrawer @register="registerDrawer" @success="handleSuccess" /> | ||
51 | + <DevicePreviewModal @register="registerModal" /> | ||
52 | + </div> | ||
53 | +</template> | ||
54 | + | ||
55 | +<script lang="ts" setup> | ||
56 | + import { reactive, nextTick } from 'vue'; | ||
57 | + import { BasicTable, useTable, TableAction } from '/@/components/Table'; | ||
58 | + import { useDrawer } from '/@/components/Drawer'; | ||
59 | + import ReportConfigDrawer from './ReportConfigDrawer.vue'; | ||
60 | + import DevicePreviewModal from './DevicePreviewModal.vue'; | ||
61 | + import { cameraPage, deleteCameraManage } from '/@/api/camera/cameraManager'; | ||
62 | + import { searchFormSchema, columns } from './config.data'; | ||
63 | + import { Authority } from '/@/components/Authority'; | ||
64 | + import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; | ||
65 | + import { Popconfirm } from 'ant-design-vue'; | ||
66 | + import { useModal } from '/@/components/Modal'; | ||
67 | + import { useGo } from '/@/hooks/web/usePage'; | ||
68 | + | ||
69 | + const searchInfo = reactive<Recordable>({}); | ||
70 | + | ||
71 | + const [registerTable, { reload, setProps }] = useTable({ | ||
72 | + title: '报表列表', | ||
73 | + api: cameraPage, | ||
74 | + columns, | ||
75 | + showIndexColumn: false, | ||
76 | + clickToRowSelect: false, | ||
77 | + formConfig: { | ||
78 | + labelWidth: 120, | ||
79 | + schemas: searchFormSchema, | ||
80 | + }, | ||
81 | + useSearchForm: true, | ||
82 | + showTableSetting: true, | ||
83 | + bordered: true, | ||
84 | + rowKey: 'id', | ||
85 | + actionColumn: { | ||
86 | + width: 200, | ||
87 | + title: '操作', | ||
88 | + dataIndex: 'action', | ||
89 | + slots: { customRender: 'action' }, | ||
90 | + fixed: 'right', | ||
91 | + }, | ||
92 | + }); | ||
93 | + | ||
94 | + // 弹框 | ||
95 | + const [registerDrawer, { openDrawer }] = useDrawer(); | ||
96 | + | ||
97 | + // 刷新 | ||
98 | + const handleSuccess = () => { | ||
99 | + reload(); | ||
100 | + }; | ||
101 | + | ||
102 | + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete( | ||
103 | + deleteCameraManage, | ||
104 | + handleSuccess, | ||
105 | + setProps | ||
106 | + ); | ||
107 | + | ||
108 | + nextTick(() => { | ||
109 | + setProps(selectionOptions); | ||
110 | + }); | ||
111 | + | ||
112 | + // 新增或编辑 | ||
113 | + const handleCreateOrEdit = (record: Recordable | null) => { | ||
114 | + if (record) { | ||
115 | + openDrawer(true, { | ||
116 | + isUpdate: true, | ||
117 | + record, | ||
118 | + }); | ||
119 | + } else { | ||
120 | + openDrawer(true, { | ||
121 | + isUpdate: false, | ||
122 | + }); | ||
123 | + } | ||
124 | + }; | ||
125 | + | ||
126 | + //查看设备 | ||
127 | + const [registerModal, { openModal }] = useModal(); | ||
128 | + const handleDeviceView = (record) => { | ||
129 | + openModal(true, { | ||
130 | + isUpdate: true, | ||
131 | + record, | ||
132 | + }); | ||
133 | + }; | ||
134 | + const go = useGo(); | ||
135 | +</script> |
1 | +<template> | ||
2 | + <div> | ||
3 | + <BasicModal | ||
4 | + v-bind="$attrs" | ||
5 | + width="55rem" | ||
6 | + :height="heightNum" | ||
7 | + @register="register" | ||
8 | + title="报表趋势图" | ||
9 | + @cancel="handleCancel" | ||
10 | + :showOkBtn="false" | ||
11 | + > | ||
12 | + <div ref="chartRef" :style="{ height, width }"></div> | ||
13 | + </BasicModal> | ||
14 | + </div> | ||
15 | +</template> | ||
16 | +<script setup lang="ts"> | ||
17 | + import { ref, PropType, Ref, nextTick } from 'vue'; | ||
18 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | ||
19 | + import { useECharts } from '/@/hooks/web/useECharts'; | ||
20 | + | ||
21 | + defineProps({ | ||
22 | + width: { | ||
23 | + type: String as PropType<string>, | ||
24 | + default: '100%', | ||
25 | + }, | ||
26 | + height: { | ||
27 | + type: String as PropType<string>, | ||
28 | + default: 'calc(100vh - 378px)', | ||
29 | + }, | ||
30 | + }); | ||
31 | + defineEmits(['register']); | ||
32 | + const heightNum = ref(800); | ||
33 | + const chartRef = ref<HTMLDivElement | null>(null); | ||
34 | + const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); | ||
35 | + const [register] = useModalInner((data) => { | ||
36 | + console.log(data); | ||
37 | + nextTick(() => { | ||
38 | + setOptions({ | ||
39 | + title: { | ||
40 | + text: '报表趋势图', | ||
41 | + }, | ||
42 | + tooltip: { | ||
43 | + trigger: 'axis', | ||
44 | + }, | ||
45 | + legend: { | ||
46 | + data: ['CO', 'CO2'], | ||
47 | + }, | ||
48 | + toolbox: {}, | ||
49 | + grid: { | ||
50 | + left: '3%', | ||
51 | + right: '4%', | ||
52 | + bottom: '3%', | ||
53 | + containLabel: true, | ||
54 | + }, | ||
55 | + xAxis: { | ||
56 | + type: 'category', | ||
57 | + data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], | ||
58 | + boundaryGap: false, | ||
59 | + }, | ||
60 | + yAxis: { | ||
61 | + type: 'value', | ||
62 | + boundaryGap: false, | ||
63 | + }, | ||
64 | + series: [ | ||
65 | + { | ||
66 | + name: 'CO', | ||
67 | + type: 'line', | ||
68 | + stack: 'Total', | ||
69 | + data: [150, 230, 224, 218, 135, 147, 260], | ||
70 | + }, | ||
71 | + { | ||
72 | + name: 'CO2', | ||
73 | + type: 'line', | ||
74 | + stack: 'Total', | ||
75 | + data: [15, 23, 22, 28, 15, 17, 20], | ||
76 | + }, | ||
77 | + ], | ||
78 | + }); | ||
79 | + }); | ||
80 | + }); | ||
81 | + | ||
82 | + const handleCancel = () => {}; | ||
83 | +</script> | ||
84 | +<style> | ||
85 | + .video-sty { | ||
86 | + width: 100%; | ||
87 | + display: flex; | ||
88 | + align-items: center; | ||
89 | + justify-content: center; | ||
90 | + } | ||
91 | +</style> |
src/views/report/export/config.data.ts
0 → 100644
1 | +import { BasicColumn, FormSchema } from '/@/components/Table'; | ||
2 | +import moment from 'moment'; | ||
3 | + | ||
4 | +// 表格配置 | ||
5 | +export const columns: BasicColumn[] = [ | ||
6 | + { | ||
7 | + title: '配置名称', | ||
8 | + dataIndex: '1', | ||
9 | + width: 80, | ||
10 | + }, | ||
11 | + { | ||
12 | + title: '所属组织', | ||
13 | + dataIndex: '2', | ||
14 | + width: 120, | ||
15 | + }, | ||
16 | + { | ||
17 | + title: '数据类型', | ||
18 | + dataIndex: '3', | ||
19 | + width: 120, | ||
20 | + }, | ||
21 | + { | ||
22 | + title: '执行状态', | ||
23 | + dataIndex: '4', | ||
24 | + width: 120, | ||
25 | + }, | ||
26 | + { | ||
27 | + title: '执行日期', | ||
28 | + dataIndex: '8', | ||
29 | + width: 180, | ||
30 | + }, | ||
31 | +]; | ||
32 | + | ||
33 | +// 查询配置 | ||
34 | +export const searchFormSchema: FormSchema[] = [ | ||
35 | + { | ||
36 | + field: '1', | ||
37 | + label: '配置名称', | ||
38 | + component: 'Input', | ||
39 | + colProps: { span: 6 }, | ||
40 | + componentProps: { | ||
41 | + maxLength: 36, | ||
42 | + placeholder: '请输入配置名称', | ||
43 | + }, | ||
44 | + }, | ||
45 | + { | ||
46 | + field: '2', | ||
47 | + label: '执行状态', | ||
48 | + component: 'Select', | ||
49 | + colProps: { span: 6 }, | ||
50 | + componentProps: { | ||
51 | + options: [ | ||
52 | + { | ||
53 | + label: '进行中', | ||
54 | + value: 1, | ||
55 | + }, | ||
56 | + { | ||
57 | + label: '成功', | ||
58 | + value: 0, | ||
59 | + }, | ||
60 | + { | ||
61 | + label: '失败', | ||
62 | + value: 0, | ||
63 | + }, | ||
64 | + ], | ||
65 | + placeholder: '请选择执行状态', | ||
66 | + }, | ||
67 | + }, | ||
68 | + { | ||
69 | + field: '3', | ||
70 | + label: '执行时间', | ||
71 | + component: 'RangePicker', | ||
72 | + componentProps: { | ||
73 | + showTime: { | ||
74 | + defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')], | ||
75 | + }, | ||
76 | + }, | ||
77 | + colProps: { span: 6 }, | ||
78 | + }, | ||
79 | +]; |
src/views/report/export/index.vue
0 → 100644
1 | +<template> | ||
2 | + <div> | ||
3 | + <BasicTable :clickToRowSelect="false" @register="registerTable" :searchInfo="searchInfo"> | ||
4 | + <template #toolbar> | ||
5 | + <Authority value="api:yt:reportExport:export"> | ||
6 | + <a-button type="primary" @click="exportCharts"> 导出报表 </a-button> | ||
7 | + </Authority> | ||
8 | + <Authority value="api:yt:reportExport:delete"> | ||
9 | + <Popconfirm | ||
10 | + title="您确定要批量删除数据" | ||
11 | + ok-text="确定" | ||
12 | + cancel-text="取消" | ||
13 | + @confirm="handleDeleteOrBatchDelete(null)" | ||
14 | + > | ||
15 | + <a-button type="primary" color="error" :disabled="hasBatchDelete"> 批量删除 </a-button> | ||
16 | + </Popconfirm> | ||
17 | + </Authority> | ||
18 | + </template> | ||
19 | + <template #action="{ record }"> | ||
20 | + <TableAction | ||
21 | + :actions="[ | ||
22 | + { | ||
23 | + label: '查看', | ||
24 | + icon: 'clarity:note-edit-line', | ||
25 | + auth: 'api:yt:reportExport:get', | ||
26 | + onClick: handleView.bind(null, record), | ||
27 | + }, | ||
28 | + { | ||
29 | + label: '导出报表', | ||
30 | + icon: 'clarity:note-edit-line', | ||
31 | + auth: 'api:yt:reportExport:export', | ||
32 | + }, | ||
33 | + { | ||
34 | + label: '删除', | ||
35 | + icon: 'ant-design:delete-outlined', | ||
36 | + auth: 'api:yt:reportExport:delete', | ||
37 | + color: 'error', | ||
38 | + popConfirm: { | ||
39 | + title: '是否确认删除', | ||
40 | + confirm: handleDeleteOrBatchDelete.bind(null, record), | ||
41 | + }, | ||
42 | + }, | ||
43 | + ]" | ||
44 | + /> | ||
45 | + </template> | ||
46 | + </BasicTable> | ||
47 | + <ReportPreviewModal @register="registerModal" /> | ||
48 | + </div> | ||
49 | +</template> | ||
50 | + | ||
51 | +<script lang="ts" setup> | ||
52 | + import { reactive, nextTick } from 'vue'; | ||
53 | + import { BasicTable, useTable, TableAction } from '/@/components/Table'; | ||
54 | + import { cameraPage, deleteCameraManage } from '/@/api/camera/cameraManager'; | ||
55 | + import { searchFormSchema, columns } from './config.data'; | ||
56 | + import { Authority } from '/@/components/Authority'; | ||
57 | + import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; | ||
58 | + import { Popconfirm } from 'ant-design-vue'; | ||
59 | + import { useModal } from '/@/components/Modal'; | ||
60 | + import ReportPreviewModal from './ReportPreviewModal.vue'; | ||
61 | + | ||
62 | + const searchInfo = reactive<Recordable>({}); | ||
63 | + | ||
64 | + const [registerTable, { reload, setProps }] = useTable({ | ||
65 | + title: '报表导出列表', | ||
66 | + api: cameraPage, | ||
67 | + columns, | ||
68 | + showIndexColumn: false, | ||
69 | + clickToRowSelect: false, | ||
70 | + formConfig: { | ||
71 | + labelWidth: 120, | ||
72 | + schemas: searchFormSchema, | ||
73 | + }, | ||
74 | + useSearchForm: true, | ||
75 | + showTableSetting: true, | ||
76 | + bordered: true, | ||
77 | + rowKey: 'id', | ||
78 | + actionColumn: { | ||
79 | + width: 200, | ||
80 | + title: '操作', | ||
81 | + dataIndex: 'action', | ||
82 | + slots: { customRender: 'action' }, | ||
83 | + fixed: 'right', | ||
84 | + }, | ||
85 | + }); | ||
86 | + | ||
87 | + const handleSuccess = () => { | ||
88 | + reload(); | ||
89 | + }; | ||
90 | + | ||
91 | + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete( | ||
92 | + deleteCameraManage, | ||
93 | + handleSuccess, | ||
94 | + setProps | ||
95 | + ); | ||
96 | + | ||
97 | + nextTick(() => { | ||
98 | + setProps(selectionOptions); | ||
99 | + }); | ||
100 | + | ||
101 | + const [registerModal, { openModal }] = useModal(); | ||
102 | + const handleView = (_, record) => { | ||
103 | + openModal(true, { | ||
104 | + isUpdate: true, | ||
105 | + record, | ||
106 | + }); | ||
107 | + }; | ||
108 | + const exportCharts = () => {}; | ||
109 | +</script> |