Commit ff66250277cfaee6b67017cecd42dabec59d76c6
Merge branch 'main_dev' into 'main'
perf: 优化场景联动显示 See merge request yunteng/thingskit-front!1004
Showing
9 changed files
with
109 additions
and
27 deletions
... | ... | @@ -471,7 +471,6 @@ export const formSchema: BFormSchema[] = [ |
471 | 471 | dynamicRules: () => { |
472 | 472 | return [ |
473 | 473 | { |
474 | - // required: model[SchemaFiled.AGG] !== AggregateDataEnum.NONE, | |
475 | 474 | required: true, |
476 | 475 | message: '间隔时间为必填项', |
477 | 476 | type: 'number', |
... | ... | @@ -479,7 +478,11 @@ export const formSchema: BFormSchema[] = [ |
479 | 478 | ]; |
480 | 479 | }, |
481 | 480 | ifShow({ values }) { |
482 | - return values[SchemaFiled.WAY] === QueryWay.TIME_PERIOD && exectueIsImmed(values.executeWay); | |
481 | + return ( | |
482 | + values[SchemaFiled.WAY] === QueryWay.TIME_PERIOD && | |
483 | + exectueIsImmed(values.executeWay) && | |
484 | + values[SchemaFiled.DATA_TYPE] !== DataTypeEnum.ORIGINAL | |
485 | + ); | |
483 | 486 | }, |
484 | 487 | componentProps({ formModel, formActionType }) { |
485 | 488 | const options = | ... | ... |
... | ... | @@ -34,7 +34,12 @@ |
34 | 34 | @change="(value) => handleChangeChars(value, item.device, item)" |
35 | 35 | v-bind="createPickerSearch()" |
36 | 36 | placeholder="请选择设备属性" |
37 | - :options="item?.attributes?.map((item1) => ({ label: item1, value: item1 }))" | |
37 | + :options=" | |
38 | + item?.attributes?.map((attrItem: any) => ({ | |
39 | + label: attrItem.label, | |
40 | + value: attrItem.value, | |
41 | + })) | |
42 | + " | |
38 | 43 | /> |
39 | 44 | </div> |
40 | 45 | <div class="w-full h-full flex justify-center items-center"> |
... | ... | @@ -64,6 +69,8 @@ |
64 | 69 | import { ExecuteReportRecord } from '/@/api/export/model/exportModel'; |
65 | 70 | import { Select, Spin, Empty } from 'ant-design-vue'; |
66 | 71 | import { createPickerSearch } from '/@/utils/pickerSearch'; |
72 | + import { getDeviceDetail } from '/@/api/device/deviceManager'; | |
73 | + import { getAttribute } from '/@/api/ruleengine/ruleengineApi'; | |
67 | 74 | |
68 | 75 | interface ResponsData { |
69 | 76 | attr: string; |
... | ... | @@ -141,20 +148,66 @@ |
141 | 148 | return chartOption; |
142 | 149 | }; |
143 | 150 | |
151 | + const handleDeviceProfileAttributes = async (entityId: string) => { | |
152 | + const deviceDetailRes = await getDeviceDetail(entityId); | |
153 | + const { deviceProfileId } = deviceDetailRes; | |
154 | + if (!deviceProfileId) return; | |
155 | + const attributeRes = await getAttribute(deviceProfileId); | |
156 | + return handleDataFormat(deviceDetailRes, attributeRes); | |
157 | + }; | |
158 | + | |
159 | + const handleDataFormat = (deviceDetail: any, attributes: any) => { | |
160 | + const { name, tbDeviceId } = deviceDetail; | |
161 | + const attribute = attributes.map((item: any) => ({ | |
162 | + identifier: item.identifier, | |
163 | + name: item.name, | |
164 | + detail: item.detail, | |
165 | + })); | |
166 | + return { | |
167 | + name, | |
168 | + tbDeviceId, | |
169 | + attribute, | |
170 | + }; | |
171 | + }; | |
172 | + | |
144 | 173 | const [register, { setModalProps }] = useModalInner( |
145 | 174 | async (data: { record: ExecuteReportRecord }) => { |
146 | 175 | setModalProps({ loading: true }); |
147 | 176 | try { |
148 | 177 | currentRecord = data.record; |
149 | 178 | const deviceInfo = data.record.executeCondition.executeAttributes || []; |
150 | - chartInstance.value = deviceInfo.map((item) => ({ | |
151 | - ...item, | |
152 | - active: item.attributes.at(0), | |
153 | - })); | |
179 | + let attributesList: Recordable[] = []; | |
180 | + // 处理为物模型里的标识符名 | |
181 | + const reflectDeviceList = deviceInfo.map(async (item) => { | |
182 | + const { device, attributes } = item as Recordable; | |
183 | + if (!device) return; | |
184 | + const thingsModel = (await handleDeviceProfileAttributes(item.device)) as Recordable; | |
185 | + const { tbDeviceId, attribute } = thingsModel as Recordable; | |
186 | + if (!tbDeviceId) return; | |
187 | + if (device === tbDeviceId) { | |
188 | + attributesList = attributes.reduce((acc, curr) => { | |
189 | + attribute.forEach((item: Recordable) => { | |
190 | + if (item.identifier === curr) { | |
191 | + acc.push({ | |
192 | + label: item.name, | |
193 | + value: item.identifier, | |
194 | + }); | |
195 | + } | |
196 | + }); | |
197 | + return [...acc]; | |
198 | + }, []); | |
199 | + } | |
200 | + return { | |
201 | + ...item, | |
202 | + active: attributes.at(0), | |
203 | + attributes: attributesList, | |
204 | + }; | |
205 | + }); | |
206 | + chartInstance.value = (await Promise.all(reflectDeviceList)) as any as ChartInstance[]; | |
154 | 207 | for (const item of unref(chartInstance)) { |
155 | 208 | const { attributes, device } = item; |
156 | 209 | |
157 | - const keys = attributes.length ? attributes.at(0) : ''; | |
210 | + const keys = attributes.length ? (attributes as any[]).at(0)?.value : ''; | |
158 | 211 | |
159 | 212 | const sendParams = { |
160 | 213 | ...data.record.executeCondition.executeCondition, | ... | ... |
... | ... | @@ -9,6 +9,7 @@ export const formSchemas: FormSchema[] = [ |
9 | 9 | field: CheckExistenceFieldsEnum.MESSAGE_NAMES, |
10 | 10 | component: 'Select', |
11 | 11 | label: CheckExistenceFieldsNameEnum.MESSAGE_NAMES, |
12 | + rules: [{ required: true, type: 'array' }], | |
12 | 13 | componentProps: { |
13 | 14 | mode: 'tags', |
14 | 15 | open: false, |
... | ... | @@ -20,6 +21,7 @@ export const formSchemas: FormSchema[] = [ |
20 | 21 | field: CheckExistenceFieldsEnum.METADATA_NAMES, |
21 | 22 | component: 'Select', |
22 | 23 | label: CheckExistenceFieldsNameEnum.METADATA_NAMES, |
24 | + rules: [{ required: true, type: 'array' }], | |
23 | 25 | componentProps: { |
24 | 26 | mode: 'tags', |
25 | 27 | open: false, | ... | ... |
... | ... | @@ -25,7 +25,7 @@ export const getFormSchemas = (route: RouteLocationNormalizedLoaded): FormSchema |
25 | 25 | component: 'ApiSearchSelect', |
26 | 26 | componentProps: () => { |
27 | 27 | return { |
28 | - placeholder: '请选择所属产品', | |
28 | + placeholder: '请选择规则链', | |
29 | 29 | showSearch: true, |
30 | 30 | params: { |
31 | 31 | pageSize: 50, | ... | ... |
... | ... | @@ -62,7 +62,7 @@ export const formSchemas: FormSchema[] = [ |
62 | 62 | { |
63 | 63 | field: FormFieldsEnum.STATUS, |
64 | 64 | label: '状态', |
65 | - component: 'Input', | |
65 | + component: 'Select', | |
66 | 66 | componentProps: { |
67 | 67 | options: Object.keys(StatusEnum).map((value) => ({ label: StatusNameEnum[value], value })), |
68 | 68 | allowClear: true, | ... | ... |
... | ... | @@ -13,23 +13,26 @@ |
13 | 13 | <template v-for="(item, optionIndex) in options" :key="item.flag"> |
14 | 14 | <div :class="optionIndex >= 1 ? 'mt-4' : ''" class="flex"> |
15 | 15 | <div class="ml-4 mr-4 flex items-center"> |
16 | - <Checkbox v-model:checked="item.enabled">星期{{ item.flag }}</Checkbox> | |
16 | + <Checkbox v-model:checked="item.enabled" :disabled="modalStatus" | |
17 | + >星期{{ item.flag }}</Checkbox | |
18 | + > | |
17 | 19 | </div> |
18 | 20 | <TimePicker |
19 | 21 | placeholder="开始时间" |
20 | 22 | v-model:value="item.startsOn" |
21 | 23 | value-format="x" |
22 | 24 | format="HH:mm" |
23 | - :disabled="!item.enabled" | |
25 | + @change="handleBlur(item.startsOn, item.endsOn, item)" | |
26 | + :disabled="!item.enabled || modalStatus" | |
24 | 27 | /> |
25 | 28 | <span class="ml-4 mr-4 flex items-center">~</span> |
26 | 29 | <TimePicker |
27 | - @change="handleBlur(item.startsOn, item.endsOn)" | |
30 | + @change="handleBlur(item.startsOn, item.endsOn, item)" | |
28 | 31 | placeholder="结束时间" |
29 | 32 | v-model:value="item.endsOn" |
30 | 33 | value-format="x" |
31 | 34 | format="HH:mm" |
32 | - :disabled="!item.enabled" | |
35 | + :disabled="!item.enabled || modalStatus" | |
33 | 36 | /> |
34 | 37 | </div> |
35 | 38 | </template> |
... | ... | @@ -40,6 +43,8 @@ |
40 | 43 | v-model:value="timeState.startsOn" |
41 | 44 | value-format="x" |
42 | 45 | format="HH:mm" |
46 | + :disabled="modalStatus" | |
47 | + @change="handleTimeBlur(timeState.startsOn, timeState.endsOn)" | |
43 | 48 | /> |
44 | 49 | <span class="ml-4 mr-4">~</span> |
45 | 50 | <TimePicker |
... | ... | @@ -48,6 +53,7 @@ |
48 | 53 | v-model:value="timeState.endsOn" |
49 | 54 | value-format="x" |
50 | 55 | format="HH:mm" |
56 | + :disabled="modalStatus" | |
51 | 57 | /> |
52 | 58 | </template> |
53 | 59 | </BasicForm> |
... | ... | @@ -55,7 +61,7 @@ |
55 | 61 | </template> |
56 | 62 | |
57 | 63 | <script lang="ts" setup> |
58 | - import { reactive, ref, watch, nextTick } from 'vue'; | |
64 | + import { reactive, ref, watch, nextTick, unref } from 'vue'; | |
59 | 65 | import { useModalInner, BasicModal } from '/@/components/Modal'; |
60 | 66 | import { BasicForm, useForm } from '/@/components/Form'; |
61 | 67 | import { alarmScheduleSchemas } from '../config/config.data'; |
... | ... | @@ -66,7 +72,7 @@ |
66 | 72 | const title = ref(''); |
67 | 73 | const isUpdateFlag = ref(false); |
68 | 74 | const { createMessage } = useMessage(); |
69 | - const [registerForm, { setFieldsValue, getFieldsValue }] = useForm({ | |
75 | + const [registerForm, { setFieldsValue, getFieldsValue, setProps }] = useForm({ | |
70 | 76 | showActionButtonGroup: false, |
71 | 77 | schemas: alarmScheduleSchemas, |
72 | 78 | }); |
... | ... | @@ -143,7 +149,7 @@ |
143 | 149 | nextTick(() => { |
144 | 150 | setModalProps({ |
145 | 151 | okButtonProps: { |
146 | - disabled: flag, | |
152 | + disabled: flag || unref(modalStatus), | |
147 | 153 | }, |
148 | 154 | }); |
149 | 155 | }); |
... | ... | @@ -153,6 +159,7 @@ |
153 | 159 | } |
154 | 160 | ); |
155 | 161 | |
162 | + const modalStatus = ref(false); | |
156 | 163 | const [registerModal, { closeModal, setModalProps }] = useModalInner((data) => { |
157 | 164 | watch([timeState, basicFormRef.value.formModel], ([timeState, formModel]) => { |
158 | 165 | setModalProps({ |
... | ... | @@ -160,7 +167,8 @@ |
160 | 167 | disabled: |
161 | 168 | timeState.startsOn === null || |
162 | 169 | timeState.endsOn === null || |
163 | - !formModel.daysOfWeek?.length, | |
170 | + !formModel.daysOfWeek?.length || | |
171 | + unref(modalStatus), | |
164 | 172 | }, |
165 | 173 | }); |
166 | 174 | watch( |
... | ... | @@ -171,7 +179,7 @@ |
171 | 179 | } |
172 | 180 | ); |
173 | 181 | }); |
174 | - const { value, currentIndex, isUpdate, scheduleData } = data; | |
182 | + const { value, currentIndex, isUpdate, scheduleData, disabled } = data; | |
175 | 183 | isUpdateFlag.value = isUpdate; |
176 | 184 | if (value === 'SPECIFIC_TIME') { |
177 | 185 | title.value = '定时启用'; |
... | ... | @@ -179,6 +187,16 @@ |
179 | 187 | title.value = '自定义启用'; |
180 | 188 | } |
181 | 189 | |
190 | + if (disabled) { | |
191 | + modalStatus.value = disabled; | |
192 | + setProps({ disabled }); | |
193 | + setModalProps({ | |
194 | + okButtonProps: { | |
195 | + disabled, | |
196 | + }, | |
197 | + }); | |
198 | + } | |
199 | + | |
182 | 200 | index.value = currentIndex; |
183 | 201 | const dayZenoTime = Math.round(new Date(new Date().toLocaleDateString()).getTime()); |
184 | 202 | // 编辑 |
... | ... | @@ -211,13 +229,15 @@ |
211 | 229 | const scheduleData = ref({ |
212 | 230 | type: 'ANY_TIME', |
213 | 231 | }); |
214 | - const handleBlur = (eS, eE) => { | |
215 | - if (eS > eE) { | |
232 | + const handleBlur = (eS, eE, item: Recordable) => { | |
233 | + if (eS && eE && eS > eE) { | |
234 | + item?.endsOn && (item.endsOn = null); | |
216 | 235 | return createMessage.warn('开始时间不能大于结束时间'); |
217 | 236 | } |
218 | 237 | }; |
219 | 238 | const handleTimeBlur = (eS, eE) => { |
220 | - if (eS > eE) { | |
239 | + if (eS && eE && eS > eE) { | |
240 | + timeState.endsOn = null; | |
221 | 241 | return createMessage.warn('开始时间不能大于结束时间'); |
222 | 242 | } |
223 | 243 | }; | ... | ... |
... | ... | @@ -147,22 +147,24 @@ |
147 | 147 | const currentIndex = ref(0); |
148 | 148 | const [registerModal, { openModal }] = useModal(); |
149 | 149 | const handleScheduleChange = (value) => { |
150 | - if (unref(disabled)) return; | |
150 | + // if (unref(disabled)) return; | |
151 | 151 | const index = scheduleOptions.findIndex((item) => item.value === value); |
152 | 152 | // 报警日程弹窗 |
153 | 153 | if (index !== 0) { |
154 | + if (unref(disabled) && unref(currentIndex) !== index) return; | |
154 | 155 | openModal(true, { |
155 | 156 | isUpdate: isUpdate.value, |
156 | 157 | value, |
157 | 158 | currentIndex: currentIndex.value, |
158 | 159 | scheduleData, |
160 | + disabled: unref(disabled), | |
159 | 161 | }); |
160 | 162 | } else { |
161 | 163 | alarmScheduleRef.value.scheduleData = { |
162 | 164 | type: value, |
163 | 165 | }; |
164 | 166 | } |
165 | - currentIndex.value = index; | |
167 | + if (!unref(disabled)) currentIndex.value = index; | |
166 | 168 | }; |
167 | 169 | const handleCancel = (index) => { |
168 | 170 | currentIndex.value = index; | ... | ... |
... | ... | @@ -199,22 +199,24 @@ |
199 | 199 | const [registerModal, { openModal }] = useModal(); |
200 | 200 | const currentIndex = ref(0); |
201 | 201 | const handleScheduleChange = (value) => { |
202 | - if (unref(disabled)) return; | |
202 | + // if (unref(disabled)) return; | |
203 | 203 | const index = scheduleOptions.findIndex((item) => item.value === value); |
204 | 204 | // 报警日程弹窗 |
205 | 205 | if (index !== 0) { |
206 | + if (unref(disabled) && unref(currentIndex) !== index) return; | |
206 | 207 | openModal(true, { |
207 | 208 | isUpdate: isUpdate.value, |
208 | 209 | value, |
209 | 210 | currentIndex: currentIndex.value, |
210 | 211 | scheduleData, |
212 | + disabled: unref(disabled), | |
211 | 213 | }); |
212 | 214 | } else { |
213 | 215 | alarmScheduleRef.value.scheduleData = { |
214 | 216 | type: value, |
215 | 217 | }; |
216 | 218 | } |
217 | - currentIndex.value = index; | |
219 | + if (!unref(disabled)) currentIndex.value = index; | |
218 | 220 | }; |
219 | 221 | const handleCancel = (index) => { |
220 | 222 | currentIndex.value = index; | ... | ... |