Commit 95403b74f74061acfee77997164af33afc9dfb7a

Authored by loveumiko
2 parents 0203a98c a4341e8d

Merge branch 'main_dev' of http://git.yunteng.com/yunteng/thingskit-front into f…

…ix/board-style-issues
@@ -28,6 +28,8 @@ enum DeviceManagerApi { @@ -28,6 +28,8 @@ enum DeviceManagerApi {
28 28
29 DEVICE_ALARM_URL = '/alarm', 29 DEVICE_ALARM_URL = '/alarm',
30 30
  31 + ALARM_BATCH_ACK = '/alarm/batch/ack',
  32 +
31 DEVICE_CREDENTIALS = '/device/credentials', 33 DEVICE_CREDENTIALS = '/device/credentials',
32 34
33 COMMAND_ISSUANCE = '/rpc', 35 COMMAND_ISSUANCE = '/rpc',
@@ -346,3 +348,13 @@ export const getDevicesByDeviceIds = (ids: string[]) => { @@ -346,3 +348,13 @@ export const getDevicesByDeviceIds = (ids: string[]) => {
346 data: ids, 348 data: ids,
347 }); 349 });
348 }; 350 };
  351 +
  352 +export const doBatchAckAlarm = (ids: string[]) => {
  353 + return defHttp.post(
  354 + {
  355 + url: DeviceManagerApi.ALARM_BATCH_ACK,
  356 + data: { alarmIds: ids },
  357 + },
  358 + { joinPrefix: false }
  359 + );
  360 +};
@@ -18,6 +18,9 @@ @@ -18,6 +18,9 @@
18 查看告警详情 18 查看告警详情
19 </a-button> 19 </a-button>
20 </template> 20 </template>
  21 + <template #toolbar>
  22 + <Button @click="handleBatchAck" type="primary">批量处理</Button>
  23 + </template>
21 </BasicTable> 24 </BasicTable>
22 <AlarmDetailDrawer @register="registerDetailDrawer" @success="handleSuccess" /> 25 <AlarmDetailDrawer @register="registerDetailDrawer" @success="handleSuccess" />
23 </div> 26 </div>
@@ -26,10 +29,10 @@ @@ -26,10 +29,10 @@
26 import { defineComponent, nextTick, h } from 'vue'; 29 import { defineComponent, nextTick, h } from 'vue';
27 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 30 import { BasicTable, useTable, TableAction } from '/@/components/Table';
28 import { alarmColumns, alarmSearchSchemas } from './config/detail.config'; 31 import { alarmColumns, alarmSearchSchemas } from './config/detail.config';
29 - import { getDeviceAlarm } from '/@/api/device/deviceManager'; 32 + import { doBatchAckAlarm, getDeviceAlarm } from '/@/api/device/deviceManager';
30 import { useDrawer } from '/@/components/Drawer'; 33 import { useDrawer } from '/@/components/Drawer';
31 import AlarmDetailDrawer from './cpns/AlarmDetailDrawer.vue'; 34 import AlarmDetailDrawer from './cpns/AlarmDetailDrawer.vue';
32 - import { Modal } from 'ant-design-vue'; 35 + import { Modal, Button } from 'ant-design-vue';
33 import { JsonPreview } from '/@/components/CodeEditor'; 36 import { JsonPreview } from '/@/components/CodeEditor';
34 import { getDeviceDetail } from '/@/api/device/deviceManager'; 37 import { getDeviceDetail } from '/@/api/device/deviceManager';
35 import { getAttribute } from '/@/api/ruleengine/ruleengineApi'; 38 import { getAttribute } from '/@/api/ruleengine/ruleengineApi';
@@ -38,17 +41,21 @@ @@ -38,17 +41,21 @@
38 operationString, 41 operationString,
39 operationBoolean, 42 operationBoolean,
40 } from '/@/views/rule/linkedge/config/formatData'; 43 } from '/@/views/rule/linkedge/config/formatData';
  44 + import { AlarmLogItem } from '/@/api/device/model/deviceConfigModel';
  45 + import { AlarmStatus } from '/@/enums/alarmEnum';
  46 + import { useMessage } from '/@/hooks/web/useMessage';
41 47
42 export default defineComponent({ 48 export default defineComponent({
43 name: 'AlarmCenter', 49 name: 'AlarmCenter',
44 components: { 50 components: {
  51 + Button,
45 BasicTable, 52 BasicTable,
46 TableAction, 53 TableAction,
47 AlarmDetailDrawer, 54 AlarmDetailDrawer,
48 }, 55 },
49 56
50 setup() { 57 setup() {
51 - const [registerTable, { reload }] = useTable({ 58 + const [registerTable, { reload, getSelectRows, clearSelectedRowKeys }] = useTable({
52 title: '告警记录列表', 59 title: '告警记录列表',
53 api: getDeviceAlarm, 60 api: getDeviceAlarm,
54 columns: alarmColumns, 61 columns: alarmColumns,
@@ -61,6 +68,14 @@ @@ -61,6 +68,14 @@
61 bordered: true, 68 bordered: true,
62 showIndexColumn: false, 69 showIndexColumn: false,
63 showTableSetting: true, 70 showTableSetting: true,
  71 + rowSelection: {
  72 + type: 'checkbox',
  73 + getCheckboxProps: (record: AlarmLogItem) => {
  74 + return {
  75 + disabled: record.status === AlarmStatus.CLEARED_ACK,
  76 + };
  77 + },
  78 + },
64 actionColumn: { 79 actionColumn: {
65 width: 200, 80 width: 200,
66 title: '操作', 81 title: '操作',
@@ -148,12 +163,24 @@ @@ -148,12 +163,24 @@
148 attribute, 163 attribute,
149 }; 164 };
150 }; 165 };
  166 +
  167 + const { createMessage } = useMessage();
  168 + const handleBatchAck = async () => {
  169 + const ids = getSelectRows<AlarmLogItem>().map((item) => item.id);
  170 +
  171 + await doBatchAckAlarm(ids);
  172 + createMessage.success('操作成功');
  173 + clearSelectedRowKeys();
  174 + reload();
  175 + };
  176 +
151 return { 177 return {
152 registerTable, 178 registerTable,
153 registerDetailDrawer, 179 registerDetailDrawer,
154 handleDetail, 180 handleDetail,
155 handleSuccess, 181 handleSuccess,
156 handleViewAlarmDetails, 182 handleViewAlarmDetails,
  183 + handleBatchAck,
157 }; 184 };
158 }, 185 },
159 }); 186 });
@@ -91,7 +91,7 @@ export const formSchema: FormSchema[] = [ @@ -91,7 +91,7 @@ export const formSchema: FormSchema[] = [
91 valueField: 'fileList', 91 valueField: 'fileList',
92 componentProps: () => { 92 componentProps: () => {
93 return { 93 return {
94 - // listType: 'picture-card', 94 + listType: 'picture-card',
95 maxFileLimit: 1, 95 maxFileLimit: 1,
96 api: async (file: File) => { 96 api: async (file: File) => {
97 try { 97 try {
@@ -110,10 +110,10 @@ export const formSchema: FormSchema[] = [ @@ -110,10 +110,10 @@ export const formSchema: FormSchema[] = [
110 onPreview: (fileList: FileItem) => { 110 onPreview: (fileList: FileItem) => {
111 createImgPreview({ imageList: [fileList.url!] }); 111 createImgPreview({ imageList: [fileList.url!] });
112 }, 112 },
113 - showUploadList: {  
114 - showDownloadIcon: true,  
115 - showRemoveIcon: true,  
116 - }, 113 + // showUploadList: {
  114 + // showDownloadIcon: true,
  115 + // showRemoveIcon: true,
  116 + // },
117 }; 117 };
118 }, 118 },
119 }, 119 },
@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 watch( 22 watch(
23 () => props.customerList, 23 () => props.customerList,
24 (newValue) => { 24 (newValue) => {
25 - const transferResult = newValue.map((item) => [item.ts, item.value]); 25 + const transferResult = newValue.map((item) => [item.date, item.value]);
26 26
27 setOptions({ 27 setOptions({
28 tooltip: { 28 tooltip: {
@@ -35,7 +35,7 @@ @@ -35,7 +35,7 @@
35 }, 35 },
36 }, 36 },
37 xAxis: { 37 xAxis: {
38 - type: 'time', 38 + type: 'category',
39 splitLine: { 39 splitLine: {
40 show: true, 40 show: true,
41 lineStyle: { 41 lineStyle: {
@@ -90,7 +90,7 @@ @@ -90,7 +90,7 @@
90 trend: props.type, 90 trend: props.type,
91 }); 91 });
92 92
93 - const transferResult = res.map((item) => [item.ts, item.value]); 93 + const transferResult = res.map((item) => [item.date, item.value]);
94 setOptions({ 94 setOptions({
95 tooltip: { 95 tooltip: {
96 trigger: 'axis', 96 trigger: 'axis',
@@ -31,7 +31,7 @@ @@ -31,7 +31,7 @@
31 }, 31 },
32 }, 32 },
33 xAxis: { 33 xAxis: {
34 - type: 'time', 34 + type: 'category',
35 splitLine: { 35 splitLine: {
36 show: true, 36 show: true,
37 lineStyle: { 37 lineStyle: {
@@ -79,11 +79,11 @@ @@ -79,11 +79,11 @@
79 const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); 79 const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
80 onMounted(async () => { 80 onMounted(async () => {
81 const res = await getTrendData({ 81 const res = await getTrendData({
82 - ...getDateByShortcutQueryKey(ShortcutQueryKeyEnum.LATEST_30_DAY), 82 + ...getDateByShortcutQueryKey(ShortcutQueryKeyEnum.LATEST_1_MONTH),
83 trend: 'CUSTOMER_TREND', 83 trend: 'CUSTOMER_TREND',
84 }); 84 });
85 85
86 - const transferResult = res.map((item) => [item.ts, item.value]); 86 + const transferResult = res.map((item) => [item.date, item.value]);
87 setOptions({ 87 setOptions({
88 tooltip: { 88 tooltip: {
89 trigger: 'axis', 89 trigger: 'axis',
@@ -95,7 +95,7 @@ @@ -95,7 +95,7 @@
95 }, 95 },
96 }, 96 },
97 xAxis: { 97 xAxis: {
98 - type: 'time', 98 + type: 'category',
99 splitLine: { 99 splitLine: {
100 show: true, 100 show: true,
101 lineStyle: { 101 lineStyle: {
@@ -37,7 +37,15 @@ @@ -37,7 +37,15 @@
37 <DatePicker 37 <DatePicker
38 @change="(_, DateString) => onDateChange(_, DateString, role === RoleEnum.CUSTOMER_USER)" 38 @change="(_, DateString) => onDateChange(_, DateString, role === RoleEnum.CUSTOMER_USER)"
39 v-model:value="dateValue" 39 v-model:value="dateValue"
40 - /> 40 + >
  41 + <Button
  42 + type="link"
  43 + class="!px-0"
  44 + :style="dateValue ? { color: '#0960bd', fontWeight: 500 } : { color: '#000000d9' }"
  45 + >
  46 + {{ dateValue ? (dateValue as moment.Moment).format('YYYY-MM-DD') : '自定义' }}
  47 + </Button>
  48 + </DatePicker>
41 </div> 49 </div>
42 </template> 50 </template>
43 <div v-if="activeKey === '1'"> 51 <div v-if="activeKey === '1'">
@@ -99,13 +107,13 @@ @@ -99,13 +107,13 @@
99 <Tooltip :overlayStyle="{ maxWidth: '340px' }"> 107 <Tooltip :overlayStyle="{ maxWidth: '340px' }">
100 <template #title> 108 <template #title>
101 <section> 109 <section>
102 - <div>30天: 查询最近30天的数据,间隔时间为1天.</div> 110 + <div>最近一个月: 查询最近一个月的数据,间隔时间为1天.</div>
103 <div>最近三个月: 查询最近三个月的数据,间隔时间为1天.</div> 111 <div>最近三个月: 查询最近三个月的数据,间隔时间为1天.</div>
104 - <div>最近一年: 查询最近一年的数据,间隔时间为30天.</div> 112 + <div>最近一年: 查询最近一年的数据,间隔时间为1月.</div>
105 <div> 113 <div>
106 间隔时间: 114 间隔时间:
107 <span class="font-bold underline"> 以当天的(最后时间)作为结束时间 </span> 115 <span class="font-bold underline"> 以当天的(最后时间)作为结束时间 </span>
108 - ,往前推移对应天数或小时的时间作为开始时间,然后在此时间区间内进行分组聚合查询. 116 + ,往前推移对应天数或的时间作为开始时间,然后在此时间区间内进行分组聚合查询.
109 </div> 117 </div>
110 </section> 118 </section>
111 </template> 119 </template>
@@ -120,9 +128,28 @@ @@ -120,9 +128,28 @@
120 </template> 128 </template>
121 <DatePicker.RangePicker 129 <DatePicker.RangePicker
122 @change="onDateCustomerChange" 130 @change="onDateCustomerChange"
  131 + :disabledDate="handleDisableDate"
  132 + @calendarChange="handleCalendarChange"
123 size="small" 133 size="small"
124 v-model:value="customerDateValue" 134 v-model:value="customerDateValue"
125 - /> 135 + >
  136 + <Button
  137 + type="link"
  138 + class="!px-0"
  139 + :style="
  140 + customerDateValue && customerDateValue.length
  141 + ? { color: '#0960bd', fontWeight: 500 }
  142 + : { color: '#000000d9' }
  143 + "
  144 + >{{
  145 + customerDateValue && customerDateValue.length
  146 + ? `${(customerDateValue?.[0] as moment.Moment)?.format('YYYY-MM-DD')}
  147 + ~
  148 + ${(customerDateValue?.[1] as moment.Moment)?.format('YYYY-MM-DD')}`
  149 + : '自定义'
  150 + }}</Button
  151 + >
  152 + </DatePicker.RangePicker>
126 </div> 153 </div>
127 </template> 154 </template>
128 <CustomerTrend :customerTrendList="customerTrendList" /> 155 <CustomerTrend :customerTrendList="customerTrendList" />
@@ -130,8 +157,8 @@ @@ -130,8 +157,8 @@
130 </div> 157 </div>
131 </template> 158 </template>
132 <script lang="ts" setup> 159 <script lang="ts" setup>
133 - import { ref, reactive } from 'vue';  
134 - import { Card, DatePicker, Tooltip } from 'ant-design-vue'; 160 + import { ref, reactive, unref } from 'vue';
  161 + import { Card, DatePicker, Tooltip, Button } from 'ant-design-vue';
135 import VisitAnalysis from './VisitAnalysis.vue'; 162 import VisitAnalysis from './VisitAnalysis.vue';
136 import VisitAnalysisBar from './VisitAnalysisBar.vue'; 163 import VisitAnalysisBar from './VisitAnalysisBar.vue';
137 import { RoleEnum, isAdmin } from '/@/enums/roleEnum'; 164 import { RoleEnum, isAdmin } from '/@/enums/roleEnum';
@@ -146,6 +173,7 @@ @@ -146,6 +173,7 @@
146 import { getTrendData } from '/@/api/dashboard'; 173 import { getTrendData } from '/@/api/dashboard';
147 import { useGlobSetting } from '/@/hooks/setting'; 174 import { useGlobSetting } from '/@/hooks/setting';
148 import { QuestionCircleOutlined } from '@ant-design/icons-vue'; 175 import { QuestionCircleOutlined } from '@ant-design/icons-vue';
  176 + import { RangePickerValue } from 'ant-design-vue/lib/date-picker/interface';
149 177
150 defineExpose({ 178 defineExpose({
151 isAdmin, 179 isAdmin,
@@ -496,6 +524,18 @@ @@ -496,6 +524,18 @@
496 // onDateTenantChange, 524 // onDateTenantChange,
497 onDateCustomerChange, 525 onDateCustomerChange,
498 } = useDate(); 526 } = useDate();
  527 +
  528 + const handleCalendarChange = (val: RangePickerValue) => {
  529 + customerDateValue.value = val as any;
  530 + };
  531 +
  532 + const handleDisableDate = (current: moment.Moment) => {
  533 + if (!unref(customerDateValue) || unref(customerDateValue).length === 0) {
  534 + return false;
  535 + }
  536 + const diffDate = current.diff(unref(customerDateValue)[0], 'days');
  537 + return Math.abs(diffDate) > 30;
  538 + };
499 </script> 539 </script>
500 540
501 <style lang="less"> 541 <style lang="less">
@@ -47,7 +47,15 @@ @@ -47,7 +47,15 @@
47 <DatePicker 47 <DatePicker
48 @change="(_, DateString) => onDateChange(_, DateString, role === RoleEnum.CUSTOMER_USER)" 48 @change="(_, DateString) => onDateChange(_, DateString, role === RoleEnum.CUSTOMER_USER)"
49 v-model:value="dateValue" 49 v-model:value="dateValue"
50 - /> 50 + >
  51 + <Button
  52 + type="link"
  53 + class="!px-0"
  54 + :style="dateValue ? { color: '#0960bd', fontWeight: 500 } : { color: '#000000d9' }"
  55 + >
  56 + {{ dateValue ? (dateValue as moment.Moment).format('YYYY-MM-DD') : '自定义' }}
  57 + </Button>
  58 + </DatePicker>
51 </div> 59 </div>
52 </template> 60 </template>
53 <!-- <div v-if="activeKey === '1'"> 61 <!-- <div v-if="activeKey === '1'">
@@ -84,13 +92,13 @@ @@ -84,13 +92,13 @@
84 <Tooltip :overlayStyle="{ maxWidth: '340px' }"> 92 <Tooltip :overlayStyle="{ maxWidth: '340px' }">
85 <template #title> 93 <template #title>
86 <section> 94 <section>
87 - <div>30天: 查询最近30天的数据,间隔时间为1天.</div> 95 + <div>最近一个月: 查询最近一个月的数据,间隔时间为1天.</div>
88 <div>最近三个月: 查询最近三个月的数据,间隔时间为1天.</div> 96 <div>最近三个月: 查询最近三个月的数据,间隔时间为1天.</div>
89 - <div>最近一年: 查询最近一年的数据,间隔时间为30天.</div> 97 + <div>最近一年: 查询最近一年的数据,间隔时间为1月.</div>
90 <div> 98 <div>
91 间隔时间: 99 间隔时间:
92 <span class="font-bold underline"> 以当天的(最后时间)作为结束时间 </span> 100 <span class="font-bold underline"> 以当天的(最后时间)作为结束时间 </span>
93 - ,往前推移对应天数或小时的时间作为开始时间,然后在此时间区间内进行分组聚合查询. 101 + ,往前推移对应天数或的时间作为开始时间,然后在此时间区间内进行分组聚合查询.
94 </div> 102 </div>
95 </section> 103 </section>
96 </template> 104 </template>
@@ -106,8 +114,27 @@ @@ -106,8 +114,27 @@
106 <DatePicker.RangePicker 114 <DatePicker.RangePicker
107 @change="onDateTenantChange" 115 @change="onDateTenantChange"
108 size="small" 116 size="small"
  117 + @calendarChange="handleCalendarChange"
  118 + :disabledDate="handleDisableDate"
109 v-model:value="tenantDateValue" 119 v-model:value="tenantDateValue"
110 - /> 120 + >
  121 + <Button
  122 + type="link"
  123 + class="!px-0"
  124 + :style="
  125 + tenantDateValue && tenantDateValue.length
  126 + ? { color: '#0960bd', fontWeight: 500 }
  127 + : { color: '#000000d9' }
  128 + "
  129 + >{{
  130 + tenantDateValue && tenantDateValue.length
  131 + ? `${(tenantDateValue?.[0] as moment.Moment)?.format('YYYY-MM-DD')}
  132 + ~
  133 + ${(tenantDateValue?.[1] as moment.Moment)?.format('YYYY-MM-DD')}`
  134 + : '自定义'
  135 + }}</Button
  136 + >
  137 + </DatePicker.RangePicker>
111 </div> 138 </div>
112 </template> 139 </template>
113 <TenantTrend :tenantTrendList="tenantTrendList" /> 140 <TenantTrend :tenantTrendList="tenantTrendList" />
@@ -139,8 +166,8 @@ @@ -139,8 +166,8 @@
139 </div> 166 </div>
140 </template> 167 </template>
141 <script lang="ts" setup> 168 <script lang="ts" setup>
142 - import { ref, reactive } from 'vue';  
143 - import { Card, DatePicker, Tooltip } from 'ant-design-vue'; 169 + import { ref, reactive, unref } from 'vue';
  170 + import { Card, DatePicker, Tooltip, Button } from 'ant-design-vue';
144 import { QuestionCircleOutlined } from '@ant-design/icons-vue'; 171 import { QuestionCircleOutlined } from '@ant-design/icons-vue';
145 // import VisitAnalysis from './VisitAnalysis.vue'; 172 // import VisitAnalysis from './VisitAnalysis.vue';
146 import VisitAnalysisBar from './VisitAnalysisBar.vue'; 173 import VisitAnalysisBar from './VisitAnalysisBar.vue';
@@ -155,6 +182,7 @@ @@ -155,6 +182,7 @@
155 import { useDate } from '../hooks/useDate'; 182 import { useDate } from '../hooks/useDate';
156 import { getTrendData } from '/@/api/dashboard'; 183 import { getTrendData } from '/@/api/dashboard';
157 import { useGlobSetting } from '/@/hooks/setting'; 184 import { useGlobSetting } from '/@/hooks/setting';
  185 + import { RangePickerValue } from 'ant-design-vue/lib/date-picker/interface';
158 186
159 defineExpose({ 187 defineExpose({
160 isAdmin, 188 isAdmin,
@@ -514,6 +542,18 @@ @@ -514,6 +542,18 @@
514 onDateTenantChange, 542 onDateTenantChange,
515 // onDateCustomerChange, 543 // onDateCustomerChange,
516 } = useDate(); 544 } = useDate();
  545 +
  546 + const handleCalendarChange = (val: RangePickerValue) => {
  547 + tenantDateValue.value = val as any;
  548 + };
  549 +
  550 + const handleDisableDate = (current: moment.Moment) => {
  551 + if (!unref(tenantDateValue) || unref(tenantDateValue).length === 0) {
  552 + return false;
  553 + }
  554 + const diffDate = current.diff(unref(tenantDateValue)[0], 'days');
  555 + return Math.abs(diffDate) > 30;
  556 + };
517 </script> 557 </script>
518 558
519 <style lang="less"> 559 <style lang="less">
@@ -31,7 +31,7 @@ @@ -31,7 +31,7 @@
31 }, 31 },
32 }, 32 },
33 xAxis: { 33 xAxis: {
34 - type: 'time', 34 + type: 'category',
35 splitLine: { 35 splitLine: {
36 show: true, 36 show: true,
37 lineStyle: { 37 lineStyle: {
@@ -79,10 +79,10 @@ @@ -79,10 +79,10 @@
79 const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); 79 const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
80 onMounted(async () => { 80 onMounted(async () => {
81 const res = await getTrendData({ 81 const res = await getTrendData({
82 - ...getDateByShortcutQueryKey(ShortcutQueryKeyEnum.LATEST_30_DAY), 82 + ...getDateByShortcutQueryKey(ShortcutQueryKeyEnum.LATEST_1_MONTH),
83 trend: 'TENANT_TREND', 83 trend: 'TENANT_TREND',
84 }); 84 });
85 - const transferResult = res.map((item) => [item.ts, item.value]); 85 + const transferResult = res.map((item) => [item.date, item.value]);
86 setOptions({ 86 setOptions({
87 tooltip: { 87 tooltip: {
88 trigger: 'axis', 88 trigger: 'axis',
@@ -94,7 +94,7 @@ @@ -94,7 +94,7 @@
94 }, 94 },
95 }, 95 },
96 xAxis: { 96 xAxis: {
97 - type: 'time', 97 + type: 'category',
98 splitLine: { 98 splitLine: {
99 show: true, 99 show: true,
100 lineStyle: { 100 lineStyle: {
1 import { dateUtil, formatToDateTime } from '/@/utils/dateUtil'; 1 import { dateUtil, formatToDateTime } from '/@/utils/dateUtil';
2 import { ref } from 'vue'; 2 import { ref } from 'vue';
3 import { getTrendData } from '/@/api/dashboard'; 3 import { getTrendData } from '/@/api/dashboard';
  4 +import { RangePickerValue } from 'ant-design-vue/lib/date-picker/interface';
4 5
5 export enum ShortcutQueryKeyEnum { 6 export enum ShortcutQueryKeyEnum {
6 - LATEST_30_DAY = 'LATEST_30_DAY', 7 + LATEST_1_MONTH = 'LATEST_1_MONTH',
7 LATEST_3_MONTH = 'LATEST_3_MONTH', 8 LATEST_3_MONTH = 'LATEST_3_MONTH',
8 LATEST_1_YEAR = 'LATEST_1_YEAR', 9 LATEST_1_YEAR = 'LATEST_1_YEAR',
9 } 10 }
10 11
11 export function getDateByShortcutQueryKey(value: ShortcutQueryKeyEnum) { 12 export function getDateByShortcutQueryKey(value: ShortcutQueryKeyEnum) {
12 const mapping = { 13 const mapping = {
13 - [ShortcutQueryKeyEnum.LATEST_30_DAY]: () => { 14 + [ShortcutQueryKeyEnum.LATEST_1_MONTH]: () => {
14 return { 15 return {
15 - startTs: dateUtil().subtract(30, 'day').startOf('day').valueOf(), 16 + startTs: dateUtil().subtract(1, 'month').startOf('day').valueOf(),
16 interval: 24 * 60 * 60 * 1000, 17 interval: 24 * 60 * 60 * 1000,
17 }; 18 };
18 }, 19 },
@@ -40,13 +41,13 @@ export function getDateByShortcutQueryKey(value: ShortcutQueryKeyEnum) { @@ -40,13 +41,13 @@ export function getDateByShortcutQueryKey(value: ShortcutQueryKeyEnum) {
40 41
41 export function useDate() { 42 export function useDate() {
42 const tenantDateValue = ref([]); 43 const tenantDateValue = ref([]);
43 - const customerDateValue = ref([]); 44 + const customerDateValue = ref<RangePickerValue>([]);
44 const tenantTrendList = ref([]); 45 const tenantTrendList = ref([]);
45 const customerTrendList = ref([]); 46 const customerTrendList = ref([]);
46 const activeTenantIndex = ref(0); 47 const activeTenantIndex = ref(0);
47 const activeCustomerIndex = ref(0); 48 const activeCustomerIndex = ref(0);
48 const TenantOrCustomerDateList = ref([ 49 const TenantOrCustomerDateList = ref([
49 - { label: '30天', value: ShortcutQueryKeyEnum.LATEST_30_DAY }, 50 + { label: '最近一个月', value: ShortcutQueryKeyEnum.LATEST_1_MONTH },
50 { label: '最近三个月', value: ShortcutQueryKeyEnum.LATEST_3_MONTH }, 51 { label: '最近三个月', value: ShortcutQueryKeyEnum.LATEST_3_MONTH },
51 { label: '最近一年', value: ShortcutQueryKeyEnum.LATEST_1_YEAR }, 52 { label: '最近一年', value: ShortcutQueryKeyEnum.LATEST_1_YEAR },
52 ]); 53 ]);
@@ -65,7 +66,7 @@ export function useDate() { @@ -65,7 +66,7 @@ export function useDate() {
65 ...getDateByShortcutQueryKey(value), 66 ...getDateByShortcutQueryKey(value),
66 trend: 'TENANT_TREND', 67 trend: 'TENANT_TREND',
67 }); 68 });
68 - tenantTrendList.value = res.map((item) => [item.ts, item.value]); 69 + tenantTrendList.value = res.map((item) => [item.date, item.value]);
69 } else { 70 } else {
70 if (activeCustomerIndex.value === index) return; 71 if (activeCustomerIndex.value === index) return;
71 activeCustomerIndex.value = index; 72 activeCustomerIndex.value = index;
@@ -74,7 +75,7 @@ export function useDate() { @@ -74,7 +75,7 @@ export function useDate() {
74 ...getDateByShortcutQueryKey(value), 75 ...getDateByShortcutQueryKey(value),
75 trend: 'CUSTOMER_TREND', 76 trend: 'CUSTOMER_TREND',
76 }); 77 });
77 - customerTrendList.value = res.map((item) => [item.ts, item.value]); 78 + customerTrendList.value = res.map((item) => [item.date, item.value]);
78 } 79 }
79 } 80 }
80 81
@@ -103,7 +103,9 @@ @@ -103,7 +103,9 @@
103 const value = { 103 const value = {
104 ['触发属性']: findName, 104 ['触发属性']: findName,
105 ['触发条件']: `${findLogin}${curr.value.logicValue}`, 105 ['触发条件']: `${findLogin}${curr.value.logicValue}`,
106 - ['触发值']: `${curr.value.realValue}${findAttribute.detail?.dataType?.specs?.unit?.key}`, 106 + ['触发值']: `${curr.value.realValue}${
  107 + findAttribute.detail?.dataType?.specs?.unit?.key ?? ''
  108 + }`,
107 }; 109 };
108 const data = { 110 const data = {
109 [item.name]: value, 111 [item.name]: value,
@@ -60,7 +60,7 @@ @@ -60,7 +60,7 @@
60 span: 12, 60 span: 12,
61 }, 61 },
62 componentProps: { 62 componentProps: {
63 - maxLength: 255, 63 + maxLength: 64,
64 placeholder: '请输入邮件主题', 64 placeholder: '请输入邮件主题',
65 }, 65 },
66 }, 66 },
@@ -72,7 +72,7 @@ @@ -72,7 +72,7 @@
72 colProps: { 72 colProps: {
73 span: 12, 73 span: 12,
74 }, 74 },
75 - rules: [...emailRule, { required: true ,message:'主送人不能为空'}], 75 + rules: [...emailRule, { required: true, message: '主送人不能为空' }],
76 componentProps: { 76 componentProps: {
77 maxLength: 255, 77 maxLength: 255,
78 placeholder: '请输入主送', 78 placeholder: '请输入主送',
@@ -43,7 +43,7 @@ @@ -43,7 +43,7 @@
43 <div 43 <div
44 v-show="!item.notFoundData" 44 v-show="!item.notFoundData"
45 :id="`chart-${item.device}`" 45 :id="`chart-${item.device}`"
46 - style="width: 100%; height: 400px" 46 + class="w-full h-96"
47 ></div> 47 ></div>
48 </div> 48 </div>
49 </div> 49 </div>
@@ -273,6 +273,9 @@ @@ -273,6 +273,9 @@
273 series, 273 series,
274 xAxis: { data: xAxisData }, 274 xAxis: { data: xAxisData },
275 } as echarts.EChartsOption); 275 } as echarts.EChartsOption);
  276 +
  277 + await nextTick();
  278 + resize();
276 } catch (error) { 279 } catch (error) {
277 } finally { 280 } finally {
278 loading.value = false; 281 loading.value = false;
@@ -67,7 +67,7 @@ @@ -67,7 +67,7 @@
67 if (credentials) { 67 if (credentials) {
68 for (let i in credentials) Reflect.set(credentialsFile, i, credentials[i]); 68 for (let i in credentials) Reflect.set(credentialsFile, i, credentials[i]);
69 } 69 }
70 - setFieldsValue(value); 70 + setFieldsValue({ ...value, type: credentials.type });
71 }; 71 };
72 72
73 const resetValue = () => resetFields(); 73 const resetValue = () => resetFields();
@@ -576,7 +576,17 @@ export const actionSchema: FormSchema[] = [ @@ -576,7 +576,17 @@ export const actionSchema: FormSchema[] = [
576 const { setFieldsValue } = formActionType; 576 const { setFieldsValue } = formActionType;
577 return { 577 return {
578 placeholder: '请选择类型', 578 placeholder: '请选择类型',
579 - api: findDictItemByCode, 579 + api: async (parmas: Recordable) => {
  580 + try {
  581 + const record = await findDictItemByCode(parmas);
  582 + return record.filter(
  583 + (item) =>
  584 + item.itemValue !== CommandTypeEnum.ATTRIBUTE.toString() || item.itemText != '属性'
  585 + );
  586 + } catch (error) {
  587 + return [];
  588 + }
  589 + },
580 labelField: 'itemText', 590 labelField: 'itemText',
581 valueField: 'itemValue', 591 valueField: 'itemValue',
582 params: { 592 params: {
@@ -267,8 +267,10 @@ @@ -267,8 +267,10 @@
267 const validate = getFieldsValue(); 267 const validate = getFieldsValue();
268 //ft-add-2022-11-22 268 //ft-add-2022-11-22
269 const type = validate?.outTarget; 269 const type = validate?.outTarget;
270 - if (type === 'DEVICE_OUT' && validate.device == 'PART') {  
271 - if (validate.deviceId == undefined) return createMessage.error('请选择设备'); 270 + if (type === 'DEVICE_OUT') {
  271 + if (!validate.deviceProfileId) return createMessage.error('请选择产品');
  272 + if (validate.device == 'PART' && validate.deviceId == undefined)
  273 + return createMessage.error('请选择设备');
272 } 274 }
273 //ft-add-2022-11-22 275 //ft-add-2022-11-22
274 //TODO-fengtao-设备验证 276 //TODO-fengtao-设备验证
@@ -191,7 +191,8 @@ @@ -191,7 +191,8 @@
191 const updateFn: DataFetchUpdateFn = (message, attribute) => { 191 const updateFn: DataFetchUpdateFn = (message, attribute) => {
192 const { data = {} } = message; 192 const { data = {} } = message;
193 const [latest] = data[attribute] || []; 193 const [latest] = data[attribute] || [];
194 - const [_, value] = latest; 194 + const [name, value] = latest;
  195 + if (!name && !value) return;
195 noSendValue.value = getNumberValue(value); 196 noSendValue.value = getNumberValue(value);
196 sliderValue.value = getNumberValue(value); 197 sliderValue.value = getNumberValue(value);
197 }; 198 };