Commit aee2e0b87e73089617f3f967125e89cd7c5507d1
Merge branch 'main_dev' into 'main'
fix:设备批量导入产品类型错误 See merge request yunteng/thingskit-front!1117
Showing
89 changed files
with
1116 additions
and
881 deletions
@@ -25,7 +25,7 @@ module.exports = defineConfig({ | @@ -25,7 +25,7 @@ module.exports = defineConfig({ | ||
25 | 'plugin:jest/recommended', | 25 | 'plugin:jest/recommended', |
26 | ], | 26 | ], |
27 | rules: { | 27 | rules: { |
28 | - 'no-console': 'error', | 28 | + 'no-console': ['error', { allow: ['warn', 'error'] }], |
29 | 'vue/script-setup-uses-vars': 'error', | 29 | 'vue/script-setup-uses-vars': 'error', |
30 | '@typescript-eslint/ban-ts-ignore': 'off', | 30 | '@typescript-eslint/ban-ts-ignore': 'off', |
31 | '@typescript-eslint/explicit-function-return-type': 'off', | 31 | '@typescript-eslint/explicit-function-return-type': 'off', |
@@ -51,6 +51,11 @@ enum DeviceManagerApi { | @@ -51,6 +51,11 @@ enum DeviceManagerApi { | ||
51 | * @description 通过设备列表获取设备信息 | 51 | * @description 通过设备列表获取设备信息 |
52 | */ | 52 | */ |
53 | QUERY_DEVICES = '/device/get/devices', | 53 | QUERY_DEVICES = '/device/get/devices', |
54 | + | ||
55 | + /** | ||
56 | + * @description 批量变更产品 | ||
57 | + */ | ||
58 | + BATCH_UPDATE_PRODUCT = '/device/batch/update', | ||
54 | } | 59 | } |
55 | 60 | ||
56 | export const devicePage = (params: DeviceQueryParam) => { | 61 | export const devicePage = (params: DeviceQueryParam) => { |
@@ -378,3 +383,13 @@ export const doBatchClearAlarm = (ids: string[]) => { | @@ -378,3 +383,13 @@ export const doBatchClearAlarm = (ids: string[]) => { | ||
378 | { joinPrefix: false } | 383 | { joinPrefix: false } |
379 | ); | 384 | ); |
380 | }; | 385 | }; |
386 | + | ||
387 | +export const doBatchUpdateProduct = (params: { deviceIds: string[]; deviceProfileId: string }) => { | ||
388 | + return defHttp.post( | ||
389 | + { | ||
390 | + url: DeviceManagerApi.BATCH_UPDATE_PRODUCT, | ||
391 | + data: params, | ||
392 | + }, | ||
393 | + { joinPrefix: false } | ||
394 | + ); | ||
395 | +}; |
@@ -65,3 +65,19 @@ export interface ImportModelOfMatterType { | @@ -65,3 +65,19 @@ export interface ImportModelOfMatterType { | ||
65 | tkDeviceProfileId?: string; | 65 | tkDeviceProfileId?: string; |
66 | categoryId?: string; | 66 | categoryId?: string; |
67 | } | 67 | } |
68 | + | ||
69 | +export interface ModelOfMatterItemRecordType { | ||
70 | + id: string; | ||
71 | + creator: string; | ||
72 | + createTime: string; | ||
73 | + enabled: boolean; | ||
74 | + tenantId: string; | ||
75 | + functionType: string; | ||
76 | + functionName: string; | ||
77 | + identifier: string; | ||
78 | + extensionDesc: any; | ||
79 | + accessMode: string; | ||
80 | + functionJson: FunctionJson; | ||
81 | + status: number; | ||
82 | + deviceProfileId: string; | ||
83 | +} |
@@ -2,6 +2,7 @@ import { BasicPageParams } from '../model/baseModel'; | @@ -2,6 +2,7 @@ import { BasicPageParams } from '../model/baseModel'; | ||
2 | import { | 2 | import { |
3 | GetModelTslParams, | 3 | GetModelTslParams, |
4 | ImportModelOfMatterType, | 4 | ImportModelOfMatterType, |
5 | + ModelOfMatterItemRecordType, | ||
5 | ModelOfMatterParams, | 6 | ModelOfMatterParams, |
6 | } from './model/modelOfMatterModel'; | 7 | } from './model/modelOfMatterModel'; |
7 | import { defHttp } from '/@/utils/http/axios'; | 8 | import { defHttp } from '/@/utils/http/axios'; |
@@ -36,7 +37,7 @@ export const getModelList = ( | @@ -36,7 +37,7 @@ export const getModelList = ( | ||
36 | id?: string; | 37 | id?: string; |
37 | } | 38 | } |
38 | ) => { | 39 | ) => { |
39 | - return defHttp.get({ | 40 | + return defHttp.get<ModelOfMatterItemRecordType[]>({ |
40 | url: `${ModelOfMatter.LIST}`, | 41 | url: `${ModelOfMatter.LIST}`, |
41 | params, | 42 | params, |
42 | }); | 43 | }); |
@@ -14,7 +14,6 @@ export function saveMenuApi( | @@ -14,7 +14,6 @@ export function saveMenuApi( | ||
14 | update = false, | 14 | update = false, |
15 | mode: ErrorMessageMode = 'modal' | 15 | mode: ErrorMessageMode = 'modal' |
16 | ) { | 16 | ) { |
17 | - console.log(params); | ||
18 | if (!update) { | 17 | if (!update) { |
19 | return defHttp.post<MenuOperationApiResult>( | 18 | return defHttp.post<MenuOperationApiResult>( |
20 | { | 19 | { |
@@ -48,13 +48,21 @@ | @@ -48,13 +48,21 @@ | ||
48 | <template #content> | 48 | <template #content> |
49 | <section class="flex flex-wrap w-36"> | 49 | <section class="flex flex-wrap w-36"> |
50 | <table class="border-collapse" @click="handleSelectConfirm"> | 50 | <table class="border-collapse" @click="handleSelectConfirm"> |
51 | - <tr v-for="row in MAX_ROW" :key="row" class="border border-gray-300 border-solid"> | 51 | + <tr |
52 | + v-for="rowNumber in MAX_ROW" | ||
53 | + :key="rowNumber" | ||
54 | + class="border border-gray-300 border-solid" | ||
55 | + > | ||
52 | <td | 56 | <td |
53 | - v-for="col in MAX_COL" | ||
54 | - :class="selectedLayout.col >= col && selectedLayout.row >= row ? 'bg-blue-500' : ''" | ||
55 | - :key="col" | 57 | + v-for="colNumber in MAX_COL" |
58 | + :class=" | ||
59 | + selectedLayout.col >= colNumber && selectedLayout.row >= rowNumber | ||
60 | + ? 'bg-blue-500' | ||
61 | + : '' | ||
62 | + " | ||
63 | + :key="colNumber" | ||
56 | class="w-4 h-4 border border-gray-300 border-solid cursor-pointer" | 64 | class="w-4 h-4 border border-gray-300 border-solid cursor-pointer" |
57 | - @mouseover="handleOver(row, col)" | 65 | + @mouseover="handleOver(rowNumber, colNumber)" |
58 | > | 66 | > |
59 | </td> | 67 | </td> |
60 | </tr> | 68 | </tr> |
@@ -77,7 +77,6 @@ | @@ -77,7 +77,6 @@ | ||
77 | try { | 77 | try { |
78 | const data = e.target && e.target.result; | 78 | const data = e.target && e.target.result; |
79 | const workbook = XLSX.read(data, { type: 'array' }); | 79 | const workbook = XLSX.read(data, { type: 'array' }); |
80 | - // console.log(workbook); | ||
81 | /* DO SOMETHING WITH workbook HERE */ | 80 | /* DO SOMETHING WITH workbook HERE */ |
82 | const excelData = getExcelData(workbook); | 81 | const excelData = getExcelData(workbook); |
83 | emit('success', excelData); | 82 | emit('success', excelData); |
@@ -90,7 +90,7 @@ | @@ -90,7 +90,7 @@ | ||
90 | () => { | 90 | () => { |
91 | !unref(isFirstLoad) && fetch(); | 91 | !unref(isFirstLoad) && fetch(); |
92 | }, | 92 | }, |
93 | - { deep: true }, | 93 | + { deep: true } |
94 | ); | 94 | ); |
95 | 95 | ||
96 | async function fetch() { | 96 | async function fetch() { |
@@ -110,6 +110,7 @@ | @@ -110,6 +110,7 @@ | ||
110 | } | 110 | } |
111 | emitChange(); | 111 | emitChange(); |
112 | } catch (error) { | 112 | } catch (error) { |
113 | + // eslint-disable-next-line no-console | ||
113 | console.warn(error); | 114 | console.warn(error); |
114 | } finally { | 115 | } finally { |
115 | loading.value = false; | 116 | loading.value = false; |
@@ -156,6 +156,7 @@ | @@ -156,6 +156,7 @@ | ||
156 | } | 156 | } |
157 | emitChange(); | 157 | emitChange(); |
158 | } catch (error) { | 158 | } catch (error) { |
159 | + // eslint-disable-next-line no-console | ||
159 | console.warn(error); | 160 | console.warn(error); |
160 | } finally { | 161 | } finally { |
161 | loading.value = false; | 162 | loading.value = false; |
@@ -54,7 +54,7 @@ | @@ -54,7 +54,7 @@ | ||
54 | }, | 54 | }, |
55 | // api params | 55 | // api params |
56 | params: { | 56 | params: { |
57 | - type: Object as PropType<Recordable>, | 57 | + type: [Object, String, Number] as any, |
58 | default: () => ({}), | 58 | default: () => ({}), |
59 | }, | 59 | }, |
60 | // support xxx.xxx.xx | 60 | // support xxx.xxx.xx |
1 | +<script setup lang="ts"> | ||
2 | + import { InputGroup, Button, Popconfirm } from 'ant-design-vue'; | ||
3 | + import { computed, ref, unref, watch } from 'vue'; | ||
4 | + import { componentMap } from '../componentMap'; | ||
5 | + import { ComponentType } from '../types'; | ||
6 | + import Icon from '/@/components/Icon'; | ||
7 | + import { PopConfirm } from '/@/components/Table'; | ||
8 | + import { upperFirst } from '/@/components/Transition/src/ExpandTransition'; | ||
9 | + | ||
10 | + const props = withDefaults( | ||
11 | + defineProps<{ | ||
12 | + value?: number | string | Recordable | Recordable[]; | ||
13 | + component?: ComponentType; | ||
14 | + componentProps?: Recordable; | ||
15 | + disabled?: boolean; | ||
16 | + changeEvent?: string; | ||
17 | + valueField?: string; | ||
18 | + defaultLockStatus?: boolean; | ||
19 | + popconfirm?: Omit<PopConfirm, 'confirm' | 'cancel'>; | ||
20 | + }>(), | ||
21 | + { | ||
22 | + changeEvent: 'change', | ||
23 | + valueField: 'value', | ||
24 | + disabled: false, | ||
25 | + component: 'Input', | ||
26 | + defaultLockStatus: true, | ||
27 | + componentProps: () => ({}), | ||
28 | + } | ||
29 | + ); | ||
30 | + | ||
31 | + const slots = defineSlots<{ | ||
32 | + popconfirmTitle?: () => any; | ||
33 | + }>(); | ||
34 | + | ||
35 | + const emits = defineEmits(['change']); | ||
36 | + | ||
37 | + const ControlComponent = computed(() => componentMap.get(props.component)); | ||
38 | + | ||
39 | + const getControlComponentProps = computed(() => { | ||
40 | + const { componentProps, changeEvent, component, valueField, value } = props; | ||
41 | + const isCheck = component && ['Switch', 'Checkbox'].includes(component); | ||
42 | + const eventKey = `on${upperFirst(changeEvent)}`; | ||
43 | + return { | ||
44 | + ...componentProps, | ||
45 | + [eventKey]: (...args: Nullable<Recordable>[]) => { | ||
46 | + const [e] = args; | ||
47 | + if (componentProps?.[eventKey]) { | ||
48 | + componentProps?.[eventKey](...args); | ||
49 | + } | ||
50 | + const target = e ? e.target : null; | ||
51 | + const value = target ? (isCheck ? target.checked : target.value) : e; | ||
52 | + emits('change', value); | ||
53 | + }, | ||
54 | + [valueField]: value, | ||
55 | + }; | ||
56 | + }); | ||
57 | + | ||
58 | + const popconfirmVisible = ref(false); | ||
59 | + | ||
60 | + const confirm = () => { | ||
61 | + controlDisableStatus.value = false; | ||
62 | + popconfirmVisible.value = false; | ||
63 | + }; | ||
64 | + | ||
65 | + const cancel = () => { | ||
66 | + popconfirmVisible.value = false; | ||
67 | + }; | ||
68 | + | ||
69 | + const getPopConfirmProps = computed(() => { | ||
70 | + const { popconfirm } = props; | ||
71 | + | ||
72 | + return { | ||
73 | + ...popconfirm, | ||
74 | + onConfirm: confirm, | ||
75 | + onCancel: cancel, | ||
76 | + onVisibleChange: () => { | ||
77 | + if (!unref(controlDisableStatus)) { | ||
78 | + popconfirmVisible.value = false; | ||
79 | + controlDisableStatus.value = true; | ||
80 | + return; | ||
81 | + } | ||
82 | + }, | ||
83 | + title: slots.popconfirmTitle ? slots.popconfirmTitle : popconfirm?.title, | ||
84 | + }; | ||
85 | + }); | ||
86 | + | ||
87 | + const controlDisableStatus = ref(props.defaultLockStatus); | ||
88 | + | ||
89 | + watch( | ||
90 | + () => props.defaultLockStatus, | ||
91 | + (target) => { | ||
92 | + controlDisableStatus.value = !!target; | ||
93 | + }, | ||
94 | + { immediate: true } | ||
95 | + ); | ||
96 | +</script> | ||
97 | + | ||
98 | +<template> | ||
99 | + <InputGroup compact class="w-full !flex"> | ||
100 | + <ControlComponent | ||
101 | + v-bind="getControlComponentProps" | ||
102 | + class="flex-auto" | ||
103 | + :disabled="controlDisableStatus" | ||
104 | + /> | ||
105 | + <Popconfirm v-model:visible="popconfirmVisible" v-bind="getPopConfirmProps"> | ||
106 | + <Button type="primary" :disabled="disabled"> | ||
107 | + <Icon | ||
108 | + :icon="controlDisableStatus ? 'ant-design:lock-outlined' : 'ant-design:unlock-outlined'" | ||
109 | + /> | ||
110 | + </Button> | ||
111 | + </Popconfirm> | ||
112 | + </InputGroup> | ||
113 | +</template> |
@@ -113,7 +113,7 @@ | @@ -113,7 +113,7 @@ | ||
113 | const { TabPane } = Tabs; | 113 | const { TabPane } = Tabs; |
114 | const { prefixCls } = useDesign('easy-cron-inner'); | 114 | const { prefixCls } = useDesign('easy-cron-inner'); |
115 | provide('prefixCls', prefixCls); | 115 | provide('prefixCls', prefixCls); |
116 | - const emit = defineEmits([...cronEmits]); | 116 | + const emit = defineEmits(cronEmits); |
117 | const props = defineProps({ ...cronProps }); | 117 | const props = defineProps({ ...cronProps }); |
118 | const activeKey = ref(props.hideSecond ? 'minute' : 'second'); | 118 | const activeKey = ref(props.hideSecond ? 'minute' : 'second'); |
119 | const second = ref('*'); | 119 | const second = ref('*'); |
@@ -236,7 +236,7 @@ | @@ -236,7 +236,7 @@ | ||
236 | if (/^[0-7]$/.test(week)) { | 236 | if (/^[0-7]$/.test(week)) { |
237 | return convert(week); | 237 | return convert(week); |
238 | } else if (patten1.test(week)) { | 238 | } else if (patten1.test(week)) { |
239 | - return week.replace(patten1, ($0, before, separator, after) => { | 239 | + return week.replace(patten1, (_$0, before, separator, after) => { |
240 | if (separator === '/') { | 240 | if (separator === '/') { |
241 | return convert(before) + separator + after; | 241 | return convert(before) + separator + after; |
242 | } else { | 242 | } else { |
@@ -23,8 +23,8 @@ | @@ -23,8 +23,8 @@ | ||
23 | 23 | ||
24 | export default defineComponent({ | 24 | export default defineComponent({ |
25 | name: 'EasyCronModal', | 25 | name: 'EasyCronModal', |
26 | - inheritAttrs: false, | ||
27 | components: { BasicModal, EasyCron, Button }, | 26 | components: { BasicModal, EasyCron, Button }, |
27 | + inheritAttrs: false, | ||
28 | setup() { | 28 | setup() { |
29 | const attrs = useAttrs(); | 29 | const attrs = useAttrs(); |
30 | const [registerModal, { closeModal }] = useModalInner(); | 30 | const [registerModal, { closeModal }] = useModalInner(); |
@@ -45,7 +45,7 @@ export function useTabSetup(props, context, options) { | @@ -45,7 +45,7 @@ export function useTabSetup(props, context, options) { | ||
45 | 45 | ||
46 | // 根据不同的类型计算出的value | 46 | // 根据不同的类型计算出的value |
47 | const computeValue = computed(() => { | 47 | const computeValue = computed(() => { |
48 | - let valueArray: any[] = []; | 48 | + const valueArray: any[] = []; |
49 | switch (type.value) { | 49 | switch (type.value) { |
50 | case TypeEnum.unset: | 50 | case TypeEnum.unset: |
51 | valueArray.push('?'); | 51 | valueArray.push('?'); |
@@ -79,7 +79,7 @@ export function useTabSetup(props, context, options) { | @@ -79,7 +79,7 @@ export function useTabSetup(props, context, options) { | ||
79 | }); | 79 | }); |
80 | // 指定值范围区间,介于最小值和最大值之间 | 80 | // 指定值范围区间,介于最小值和最大值之间 |
81 | const specifyRange = computed(() => { | 81 | const specifyRange = computed(() => { |
82 | - let range: number[] = []; | 82 | + const range: number[] = []; |
83 | if (maxValue.value != null) { | 83 | if (maxValue.value != null) { |
84 | for (let i = minValue.value; i <= maxValue.value; i++) { | 84 | for (let i = minValue.value; i <= maxValue.value; i++) { |
85 | range.push(i); | 85 | range.push(i); |
@@ -143,4 +143,5 @@ export type ComponentType = | @@ -143,4 +143,5 @@ export type ComponentType = | ||
143 | | 'ConditionFilter' | 143 | | 'ConditionFilter' |
144 | | 'TimeRangePicker' | 144 | | 'TimeRangePicker' |
145 | | 'TriggerDurationInput' | 145 | | 'TriggerDurationInput' |
146 | - | 'AlarmProfileSelect'; | 146 | + | 'AlarmProfileSelect' |
147 | + | 'LockControlGroup'; |
@@ -44,7 +44,7 @@ | @@ -44,7 +44,7 @@ | ||
44 | </ModalWrapper> | 44 | </ModalWrapper> |
45 | 45 | ||
46 | <template #[item]="data" v-for="item in Object.keys(omit($slots, 'default'))"> | 46 | <template #[item]="data" v-for="item in Object.keys(omit($slots, 'default'))"> |
47 | - <slot :name="item" v-bind="data"></slot> | 47 | + <slot :name="item" v-bind="data || {}"></slot> |
48 | </template> | 48 | </template> |
49 | </Modal> | 49 | </Modal> |
50 | </template> | 50 | </template> |
@@ -207,7 +207,6 @@ | @@ -207,7 +207,6 @@ | ||
207 | }); | 207 | }); |
208 | 208 | ||
209 | function handleSearch(searchValue: string) { | 209 | function handleSearch(searchValue: string) { |
210 | - console.log('searchValue', searchValue); | ||
211 | if (searchValue !== searchText.value) searchText.value = searchValue; | 210 | if (searchValue !== searchText.value) searchText.value = searchValue; |
212 | emit('update:searchValue', searchValue); | 211 | emit('update:searchValue', searchValue); |
213 | if (!searchValue) { | 212 | if (!searchValue) { |
@@ -16,8 +16,6 @@ | @@ -16,8 +16,6 @@ | ||
16 | import { computed, defineComponent, unref, ref } from 'vue'; | 16 | import { computed, defineComponent, unref, ref } from 'vue'; |
17 | import { Layout } from 'ant-design-vue'; | 17 | import { Layout } from 'ant-design-vue'; |
18 | 18 | ||
19 | - import { GithubFilled } from '@ant-design/icons-vue'; | ||
20 | - | ||
21 | import { DOC_URL, GITHUB_URL, SITE_URL } from '/@/settings/siteSetting'; | 19 | import { DOC_URL, GITHUB_URL, SITE_URL } from '/@/settings/siteSetting'; |
22 | import { openWindow } from '/@/utils'; | 20 | import { openWindow } from '/@/utils'; |
23 | 21 | ||
@@ -29,7 +27,7 @@ | @@ -29,7 +27,7 @@ | ||
29 | 27 | ||
30 | export default defineComponent({ | 28 | export default defineComponent({ |
31 | name: 'LayoutFooter', | 29 | name: 'LayoutFooter', |
32 | - components: { Footer: Layout.Footer, GithubFilled }, | 30 | + components: { Footer: Layout.Footer }, |
33 | setup() { | 31 | setup() { |
34 | const { t } = useI18n(); | 32 | const { t } = useI18n(); |
35 | const { getShowFooter } = useRootSetting(); | 33 | const { getShowFooter } = useRootSetting(); |
@@ -148,7 +148,6 @@ | @@ -148,7 +148,6 @@ | ||
148 | 148 | ||
149 | function renderMenu() { | 149 | function renderMenu() { |
150 | const { menus, ...menuProps } = unref(getCommonProps); | 150 | const { menus, ...menuProps } = unref(getCommonProps); |
151 | - // console.log(menus); | ||
152 | if (!menus || !menus.length) return null; | 151 | if (!menus || !menus.length) return null; |
153 | return !props.isHorizontal ? ( | 152 | return !props.isHorizontal ? ( |
154 | <SimpleMenu {...menuProps} isSplitMenu={unref(getSplit)} items={menus} /> | 153 | <SimpleMenu {...menuProps} isSplitMenu={unref(getSplit)} items={menus} /> |
@@ -100,7 +100,7 @@ export default defineComponent({ | @@ -100,7 +100,7 @@ export default defineComponent({ | ||
100 | <> | 100 | <> |
101 | <TypePicker | 101 | <TypePicker |
102 | menuTypeList={menuTypeList} | 102 | menuTypeList={menuTypeList} |
103 | - handler={(item: typeof menuTypeList[0]) => { | 103 | + handler={(item: (typeof menuTypeList)[0]) => { |
104 | baseHandler(HandlerEnum.CHANGE_LAYOUT, { | 104 | baseHandler(HandlerEnum.CHANGE_LAYOUT, { |
105 | mode: item.mode, | 105 | mode: item.mode, |
106 | type: item.type, | 106 | type: item.type, |
@@ -47,7 +47,7 @@ export function initAppConfigStore() { | @@ -47,7 +47,7 @@ export function initAppConfigStore() { | ||
47 | grayMode && updateGrayMode(grayMode); | 47 | grayMode && updateGrayMode(grayMode); |
48 | colorWeak && updateColorWeak(colorWeak); | 48 | colorWeak && updateColorWeak(colorWeak); |
49 | } catch (error) { | 49 | } catch (error) { |
50 | - console.log(error); | 50 | + console.error(error); |
51 | } | 51 | } |
52 | appStore.setProjectConfig(projCfg); | 52 | appStore.setProjectConfig(projCfg); |
53 | 53 |
@@ -4,7 +4,6 @@ import { defineStore } from 'pinia'; | @@ -4,7 +4,6 @@ import { defineStore } from 'pinia'; | ||
4 | 4 | ||
5 | import { LOCK_INFO_KEY } from '/@/enums/cacheEnum'; | 5 | import { LOCK_INFO_KEY } from '/@/enums/cacheEnum'; |
6 | import { Persistent } from '/@/utils/cache/persistent'; | 6 | import { Persistent } from '/@/utils/cache/persistent'; |
7 | -import { useUserStore } from './user'; | ||
8 | 7 | ||
9 | interface LockState { | 8 | interface LockState { |
10 | lockInfo: Nullable<LockInfo>; | 9 | lockInfo: Nullable<LockInfo>; |
@@ -111,7 +111,6 @@ export const usePermissionStore = defineStore({ | @@ -111,7 +111,6 @@ export const usePermissionStore = defineStore({ | ||
111 | * 否则不是超级管理员-获取对应角色的权限列表 | 111 | * 否则不是超级管理员-获取对应角色的权限列表 |
112 | */ | 112 | */ |
113 | const codeList = await getPermCode(); | 113 | const codeList = await getPermCode(); |
114 | - // console.log('codeList', codeList); | ||
115 | this.setPermCodeList(codeList); | 114 | this.setPermCodeList(codeList); |
116 | /** | 115 | /** |
117 | * 如果是超级管理员则获取对应权限列表 | 116 | * 如果是超级管理员则获取对应权限列表 |
@@ -234,7 +234,6 @@ export const useUserStore = defineStore({ | @@ -234,7 +234,6 @@ export const useUserStore = defineStore({ | ||
234 | // try { | 234 | // try { |
235 | // await doLogout(); | 235 | // await doLogout(); |
236 | // } catch { | 236 | // } catch { |
237 | - // console.log('注销Token失败'); | ||
238 | // } | 237 | // } |
239 | // this.resetState(); | 238 | // this.resetState(); |
240 | // setAuthCache(JWT_TOKEN_KEY, undefined); | 239 | // setAuthCache(JWT_TOKEN_KEY, undefined); |
@@ -85,9 +85,7 @@ | @@ -85,9 +85,7 @@ | ||
85 | /^[1](([3][0-9])|([4][0,1,4-9])|([5][0-3,5-9])|([6][2,5,6,7])|([7][0-8])|([8][0-9])|([9][0-3,5-9]))[0-9]{8}$/; | 85 | /^[1](([3][0-9])|([4][0,1,4-9])|([5][0-3,5-9])|([6][2,5,6,7])|([7][0-8])|([8][0-9])|([9][0-3,5-9]))[0-9]{8}$/; |
86 | if (reg.test(formData.mobile)) { | 86 | if (reg.test(formData.mobile)) { |
87 | const sendRes = await passwordResetCode(formData.mobile); | 87 | const sendRes = await passwordResetCode(formData.mobile); |
88 | - console.log(sendRes); | ||
89 | if (sendRes === '') { | 88 | if (sendRes === '') { |
90 | - console.log('发送成功了'); | ||
91 | return true; | 89 | return true; |
92 | } | 90 | } |
93 | return false; | 91 | return false; |
@@ -27,7 +27,6 @@ | @@ -27,7 +27,6 @@ | ||
27 | onMounted(() => { | 27 | onMounted(() => { |
28 | // 记录当前的UserId | 28 | // 记录当前的UserId |
29 | userId.value = userStore.getUserInfo?.userId; | 29 | userId.value = userStore.getUserInfo?.userId; |
30 | - console.log('Mounted', userStore.getUserInfo); | ||
31 | }); | 30 | }); |
32 | 31 | ||
33 | onBeforeUnmount(() => { | 32 | onBeforeUnmount(() => { |
@@ -11,8 +11,7 @@ | @@ -11,8 +11,7 @@ | ||
11 | */ | 11 | */ |
12 | export function simpleDebounce(fn, delay = 100) { | 12 | export function simpleDebounce(fn, delay = 100) { |
13 | let timer: any | null = null; | 13 | let timer: any | null = null; |
14 | - return function () { | ||
15 | - let args = arguments; | 14 | + return function (...args) { |
16 | if (timer) { | 15 | if (timer) { |
17 | clearTimeout(timer); | 16 | clearTimeout(timer); |
18 | } | 17 | } |
@@ -61,4 +60,3 @@ export function dateFormat(date, block) { | @@ -61,4 +60,3 @@ export function dateFormat(date, block) { | ||
61 | }); | 60 | }); |
62 | return format; | 61 | return format; |
63 | } | 62 | } |
64 | - |
@@ -36,7 +36,6 @@ export function checkStatus( | @@ -36,7 +36,6 @@ export function checkStatus( | ||
36 | } | 36 | } |
37 | break; | 37 | break; |
38 | case 403: | 38 | case 403: |
39 | - // console.log('403', errMessage); | ||
40 | // errMessage = t('sys.api.errMsg403'); | 39 | // errMessage = t('sys.api.errMsg403'); |
41 | errMessage = errMessage; | 40 | errMessage = errMessage; |
42 | break; | 41 | break; |
@@ -8,7 +8,6 @@ export function listToTree(lists: getMenuListResultModel): getMenuListResultMode | @@ -8,7 +8,6 @@ export function listToTree(lists: getMenuListResultModel): getMenuListResultMode | ||
8 | lists.forEach((goods) => { | 8 | lists.forEach((goods) => { |
9 | goods['menuName'] = t(goods.meta.title); // 为goods添加属性menuName | 9 | goods['menuName'] = t(goods.meta.title); // 为goods添加属性menuName |
10 | 10 | ||
11 | - // console.log(goods.children?.length); | ||
12 | if (goods.children?.length) { | 11 | if (goods.children?.length) { |
13 | listToTree(goods.children); | 12 | listToTree(goods.children); |
14 | // goods.children.forEach((goodChildren) => { | 13 | // goods.children.forEach((goodChildren) => { |
@@ -102,8 +102,7 @@ | @@ -102,8 +102,7 @@ | ||
102 | avatar: [{ uid: buildUUID(), name: 'name', url: data.record.avatar } as FileItem], | 102 | avatar: [{ uid: buildUUID(), name: 'name', url: data.record.avatar } as FileItem], |
103 | }); | 103 | }); |
104 | } | 104 | } |
105 | - const { avatar, ...params } = data.record; | ||
106 | - console.log(avatar); | 105 | + const { ...params } = data.record; |
107 | await setFieldsValue({ ...params }); | 106 | await setFieldsValue({ ...params }); |
108 | } else { | 107 | } else { |
109 | editId.value = ''; | 108 | editId.value = ''; |
@@ -82,11 +82,11 @@ | @@ -82,11 +82,11 @@ | ||
82 | </script> | 82 | </script> |
83 | 83 | ||
84 | <template> | 84 | <template> |
85 | - <section class="flex"> | ||
86 | - <ApiTreeSelect v-bind="getBindProps" /> | ||
87 | - <Button v-if="getShowCreate" type="link" @click="handleOpenCreate" :disabled="disabled" | ||
88 | - >新增组织</Button | ||
89 | - > | 85 | + <section class="!flex"> |
86 | + <ApiTreeSelect v-bind="getBindProps" class="flex-auto" /> | ||
87 | + <Button v-if="getShowCreate" type="link" @click="handleOpenCreate" :disabled="disabled"> | ||
88 | + 新增组织 | ||
89 | + </Button> | ||
90 | <OrganizationDrawer v-if="getShowCreate" @register="registerDrawer" @success="handleReload" /> | 90 | <OrganizationDrawer v-if="getShowCreate" @register="registerDrawer" @success="handleReload" /> |
91 | </section> | 91 | </section> |
92 | </template> | 92 | </template> |
@@ -75,9 +75,7 @@ export const formSchema: FormSchema[] = [ | @@ -75,9 +75,7 @@ export const formSchema: FormSchema[] = [ | ||
75 | } | 75 | } |
76 | }, | 76 | }, |
77 | // showUploadList: true, | 77 | // showUploadList: true, |
78 | - onDownload(file) { | ||
79 | - console.log(file); | ||
80 | - }, | 78 | + onDownload() {}, |
81 | onPreview: (fileList: FileItem) => { | 79 | onPreview: (fileList: FileItem) => { |
82 | createImgPreview({ imageList: [fileList.url!] }); | 80 | createImgPreview({ imageList: [fileList.url!] }); |
83 | }, | 81 | }, |
@@ -153,7 +153,7 @@ | @@ -153,7 +153,7 @@ | ||
153 | <template #renderItem="{ item }: BasicCardListRenderItem<BigScreenCenterItemsModel>"> | 153 | <template #renderItem="{ item }: BasicCardListRenderItem<BigScreenCenterItemsModel>"> |
154 | <Card | 154 | <Card |
155 | :style="{ | 155 | :style="{ |
156 | - '--viewType': item.viewType === ViewType.PUBLIC_VIEW ? '#1890ff' : '#faad14', | 156 | + '--viewType': item.viewType === ViewType.PUBLIC_VIEW ? '#faad14' : '#1890ff', |
157 | }" | 157 | }" |
158 | class="card-container" | 158 | class="card-container" |
159 | > | 159 | > |
@@ -192,7 +192,6 @@ | @@ -192,7 +192,6 @@ | ||
192 | getRestData.value = resp; | 192 | getRestData.value = resp; |
193 | commonRest(resp, jsonEditorRef.value?.setJsonValue); | 193 | commonRest(resp, jsonEditorRef.value?.setJsonValue); |
194 | } catch (e) { | 194 | } catch (e) { |
195 | - console.log(e); | ||
196 | if (Object.prototype.toString.call(e) === '[object Object]') { | 195 | if (Object.prototype.toString.call(e) === '[object Object]') { |
197 | jsonEditorRef.value?.setJsonValue(e); | 196 | jsonEditorRef.value?.setJsonValue(e); |
198 | } else { | 197 | } else { |
@@ -61,7 +61,7 @@ export const useUtils = () => { | @@ -61,7 +61,7 @@ export const useUtils = () => { | ||
61 | } | 61 | } |
62 | } | 62 | } |
63 | } catch (e) { | 63 | } catch (e) { |
64 | - console.log(`Post没有传递params${e}`); | 64 | + console.error(`Post没有传递params${e}`); |
65 | } | 65 | } |
66 | return _result.join('&'); | 66 | return _result.join('&'); |
67 | }; | 67 | }; |
1 | import { FormProps, FormSchema, useComponentRegister } from '/@/components/Form'; | 1 | import { FormProps, FormSchema, useComponentRegister } from '/@/components/Form'; |
2 | import { findDictItemByCode } from '/@/api/system/dict'; | 2 | import { findDictItemByCode } from '/@/api/system/dict'; |
3 | -import { deviceProfile, getGatewayDevice } from '/@/api/device/deviceManager'; | 3 | +import { getGatewayDevice, queryDeviceProfileBy } from '/@/api/device/deviceManager'; |
4 | import { TransportTypeEnum } from '../../profiles/components/TransportDescript/const'; | 4 | import { TransportTypeEnum } from '../../profiles/components/TransportDescript/const'; |
5 | import { JSONEditorValidator } from '/@/components/CodeEditor/src/JSONEditor'; | 5 | import { JSONEditorValidator } from '/@/components/CodeEditor/src/JSONEditor'; |
6 | import { JSONEditor } from '/@/components/CodeEditor'; | 6 | import { JSONEditor } from '/@/components/CodeEditor'; |
7 | import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; | 7 | import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; |
8 | import { getModelServices } from '/@/api/device/modelOfMatter'; | 8 | import { getModelServices } from '/@/api/device/modelOfMatter'; |
9 | import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel'; | 9 | import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel'; |
10 | -import { nextTick, toRaw, unref } from 'vue'; | 10 | +import { h, nextTick, toRaw, unref } from 'vue'; |
11 | import ObjectModelValidateForm from '/@/components/Form/src/externalCompns/components/ObjectModelValidateForm/ObjectModelValidateForm.vue'; | 11 | import ObjectModelValidateForm from '/@/components/Form/src/externalCompns/components/ObjectModelValidateForm/ObjectModelValidateForm.vue'; |
12 | import { CommandDeliveryWayEnum, ServiceCallTypeEnum } from '/@/enums/toolEnum'; | 12 | import { CommandDeliveryWayEnum, ServiceCallTypeEnum } from '/@/enums/toolEnum'; |
13 | import { TaskTypeEnum } from '/@/views/task/center/config'; | 13 | import { TaskTypeEnum } from '/@/views/task/center/config'; |
@@ -18,9 +18,13 @@ import { uploadThumbnail } from '/@/api/configuration/center/configurationCenter | @@ -18,9 +18,13 @@ import { uploadThumbnail } from '/@/api/configuration/center/configurationCenter | ||
18 | 18 | ||
19 | import { getOrganizationList } from '/@/api/system/system'; | 19 | import { getOrganizationList } from '/@/api/system/system'; |
20 | import { copyTransFun } from '/@/utils/fnUtils'; | 20 | import { copyTransFun } from '/@/utils/fnUtils'; |
21 | +import LockControlGroup from '/@/components/Form/src/components/LockControlGroup.vue'; | ||
22 | +import { OrgTreeSelect } from '/@/views/common/OrgTreeSelect'; | ||
21 | 23 | ||
22 | useComponentRegister('JSONEditor', JSONEditor); | 24 | useComponentRegister('JSONEditor', JSONEditor); |
23 | useComponentRegister('ObjectModelValidateForm', ObjectModelValidateForm); | 25 | useComponentRegister('ObjectModelValidateForm', ObjectModelValidateForm); |
26 | +useComponentRegister('LockControlGroup', LockControlGroup); | ||
27 | +useComponentRegister('OrgTreeSelect', OrgTreeSelect); | ||
24 | 28 | ||
25 | export enum TypeEnum { | 29 | export enum TypeEnum { |
26 | IS_GATEWAY = 'GATEWAY', | 30 | IS_GATEWAY = 'GATEWAY', |
@@ -30,6 +34,17 @@ export enum TypeEnum { | @@ -30,6 +34,17 @@ export enum TypeEnum { | ||
30 | export const isGateWay = (type: string) => { | 34 | export const isGateWay = (type: string) => { |
31 | return type === TypeEnum.IS_GATEWAY; | 35 | return type === TypeEnum.IS_GATEWAY; |
32 | }; | 36 | }; |
37 | + | ||
38 | +const updateProductHelpMessage = [ | ||
39 | + '注意:', | ||
40 | + '修改设备产品时,如果"大屏"、"组态"、"看板"、"场景联动"、"数据流转"等有关联设备,请自行调整并保存。', | ||
41 | +]; | ||
42 | + | ||
43 | +const updateOrgHelpMessage = [ | ||
44 | + '注意:', | ||
45 | + '1、修改设备组织时,如果"大屏"、"组态"、"看板"、"场景联动"、"数据流转"等有关联设备,请自行调整并保存。', | ||
46 | + '2、网关设备在修改组织时,其关联网关子设备组织归属于网关组织及以下不用修改,否则将同步更新网关子设备组织为网关组织。', | ||
47 | +]; | ||
33 | // 第一步的表单 | 48 | // 第一步的表单 |
34 | export const step1Schemas: FormSchema[] = [ | 49 | export const step1Schemas: FormSchema[] = [ |
35 | { | 50 | { |
@@ -96,43 +111,60 @@ export const step1Schemas: FormSchema[] = [ | @@ -96,43 +111,60 @@ export const step1Schemas: FormSchema[] = [ | ||
96 | show: false, | 111 | show: false, |
97 | }, | 112 | }, |
98 | { | 113 | { |
114 | + field: 'isUpdate', | ||
115 | + label: '编辑模式', | ||
116 | + component: 'Switch', | ||
117 | + show: false, | ||
118 | + }, | ||
119 | + { | ||
99 | field: 'profileId', | 120 | field: 'profileId', |
100 | label: '所属产品', | 121 | label: '所属产品', |
101 | required: true, | 122 | required: true, |
102 | - component: 'ApiSelect', | 123 | + component: 'LockControlGroup', |
124 | + helpMessage: updateProductHelpMessage, | ||
125 | + renderComponentContent: () => ({ | ||
126 | + popconfirmTitle: () => | ||
127 | + updateProductHelpMessage.map((text) => h('div', { style: { maxWidth: '200px' } }, text)), | ||
128 | + }), | ||
103 | componentProps: ({ formActionType, formModel }) => { | 129 | componentProps: ({ formActionType, formModel }) => { |
104 | const { setFieldsValue } = formActionType; | 130 | const { setFieldsValue } = formActionType; |
105 | return { | 131 | return { |
106 | - api: async () => { | ||
107 | - const options = await deviceProfile(); | ||
108 | - const { profileId } = formModel; | ||
109 | - if (profileId) { | ||
110 | - const selectRecord = options.find((item) => item.tbProfileId === profileId); | ||
111 | - selectRecord && setFieldsValue({ transportType: selectRecord!.transportType }); | ||
112 | - } | ||
113 | - return options; | ||
114 | - }, | ||
115 | - labelField: 'name', | ||
116 | - valueField: 'tbProfileId', | ||
117 | - onChange( | ||
118 | - _value: string, | ||
119 | - option: { deviceType: string; transportType: string; id: string } | ||
120 | - ) { | ||
121 | - const { deviceType, transportType, id } = option; | ||
122 | - setFieldsValue({ | ||
123 | - deviceType: deviceType, | ||
124 | - transportType, | ||
125 | - deviceProfileId: id, | ||
126 | - gatewayId: null, | ||
127 | - codeType: transportType === TransportTypeEnum.TCP ? TaskTypeEnum.MODBUS_RTU : null, | ||
128 | - code: null, | ||
129 | - addressCode: null, | ||
130 | - }); | 132 | + component: 'ApiSelect', |
133 | + defaultLockStatus: !!formModel?.isUpdate, | ||
134 | + componentProps: { | ||
135 | + api: async () => { | ||
136 | + const options = await queryDeviceProfileBy({ | ||
137 | + deviceType: formModel?.isUpdate ? formModel?.deviceType : null, | ||
138 | + }); | ||
139 | + const { profileId } = formModel; | ||
140 | + if (profileId) { | ||
141 | + const selectRecord = options.find((item) => item.tbProfileId === profileId); | ||
142 | + selectRecord && setFieldsValue({ transportType: selectRecord!.transportType }); | ||
143 | + } | ||
144 | + return options; | ||
145 | + }, | ||
146 | + labelField: 'name', | ||
147 | + valueField: 'tbProfileId', | ||
148 | + onChange( | ||
149 | + _value: string, | ||
150 | + option: { deviceType: string; transportType: string; id: string } | ||
151 | + ) { | ||
152 | + const { deviceType, transportType, id } = option; | ||
153 | + setFieldsValue({ | ||
154 | + deviceType: deviceType, | ||
155 | + transportType, | ||
156 | + deviceProfileId: id, | ||
157 | + gatewayId: null, | ||
158 | + codeType: transportType === TransportTypeEnum.TCP ? TaskTypeEnum.MODBUS_RTU : null, | ||
159 | + code: null, | ||
160 | + addressCode: null, | ||
161 | + }); | ||
162 | + }, | ||
163 | + showSearch: true, | ||
164 | + placeholder: '请选择产品', | ||
165 | + filterOption: (inputValue: string, option: Record<'label' | 'value', string>) => | ||
166 | + option.label.includes(inputValue), | ||
131 | }, | 167 | }, |
132 | - showSearch: true, | ||
133 | - placeholder: '请选择产品', | ||
134 | - filterOption: (inputValue: string, option: Record<'label' | 'value', string>) => | ||
135 | - option.label.includes(inputValue), | ||
136 | }; | 168 | }; |
137 | }, | 169 | }, |
138 | }, | 170 | }, |
@@ -311,9 +343,19 @@ export const step1Schemas: FormSchema[] = [ | @@ -311,9 +343,19 @@ export const step1Schemas: FormSchema[] = [ | ||
311 | { | 343 | { |
312 | field: 'organizationId', | 344 | field: 'organizationId', |
313 | label: '所属组织', | 345 | label: '所属组织', |
314 | - component: 'Select', | 346 | + component: 'LockControlGroup', |
315 | required: true, | 347 | required: true, |
316 | - slot: 'addOrg', | 348 | + helpMessage: updateOrgHelpMessage, |
349 | + renderComponentContent: () => ({ | ||
350 | + popconfirmTitle: () => | ||
351 | + updateOrgHelpMessage.map((text) => h('div', { style: { maxWidth: '240px' } }, text)), | ||
352 | + }), | ||
353 | + componentProps: ({ formModel }) => { | ||
354 | + return { | ||
355 | + component: 'OrgTreeSelect', | ||
356 | + defaultLockStatus: !!formModel?.isUpdate, | ||
357 | + }; | ||
358 | + }, | ||
317 | }, | 359 | }, |
318 | { | 360 | { |
319 | field: 'label', | 361 | field: 'label', |
@@ -7,6 +7,63 @@ import { h } from 'vue'; | @@ -7,6 +7,63 @@ import { h } from 'vue'; | ||
7 | import { Tag, Tooltip } from 'ant-design-vue'; | 7 | import { Tag, Tooltip } from 'ant-design-vue'; |
8 | import { handeleCopy } from '../../profiles/step/topic'; | 8 | import { handeleCopy } from '../../profiles/step/topic'; |
9 | 9 | ||
10 | +export enum DeviceListAuthEnum { | ||
11 | + /** | ||
12 | + * @description 新增 | ||
13 | + */ | ||
14 | + CREATE = 'api:yt:device:post', | ||
15 | + | ||
16 | + /** | ||
17 | + * @description 删除 | ||
18 | + */ | ||
19 | + DELETE = 'api:yt:device:delete', | ||
20 | + | ||
21 | + /** | ||
22 | + * @description 编辑 | ||
23 | + */ | ||
24 | + UPDATE = 'api:yt:device:update', | ||
25 | + | ||
26 | + /** | ||
27 | + * @description 详情 | ||
28 | + */ | ||
29 | + DETAIL = 'api:yt:device:get', | ||
30 | + | ||
31 | + /** | ||
32 | + * @description 导入 | ||
33 | + */ | ||
34 | + IMPORT = 'api:yt:device:import', | ||
35 | + | ||
36 | + /** | ||
37 | + * @description 公开 | ||
38 | + */ | ||
39 | + PUBLIC = 'api:yt:device:public', | ||
40 | + | ||
41 | + /** | ||
42 | + * @description 上下线 | ||
43 | + */ | ||
44 | + ONLINE = 'api:yt:device:online:record', | ||
45 | + | ||
46 | + /** | ||
47 | + * @description 管理设备凭证 | ||
48 | + */ | ||
49 | + EQUIPMENT = 'api:yt:device:equipment', | ||
50 | + | ||
51 | + /** | ||
52 | + * @description 分配客户 | ||
53 | + */ | ||
54 | + ASSIGN = 'api:yt:device:assign', | ||
55 | + | ||
56 | + /** | ||
57 | + * @description 命令下发 | ||
58 | + */ | ||
59 | + RPC = 'api:yt:device:rpc', | ||
60 | + | ||
61 | + /** | ||
62 | + * @description 更新产品 | ||
63 | + */ | ||
64 | + UPDATE_PRODUCT = 'api:yt:device:update:product', | ||
65 | +} | ||
66 | + | ||
10 | // 表格列数据 | 67 | // 表格列数据 |
11 | export const columns: BasicColumn[] = [ | 68 | export const columns: BasicColumn[] = [ |
12 | { | 69 | { |
1 | +import { getDeviceProfile } from '/@/api/alarm/position'; | ||
2 | +import { FormSchema } from '/@/components/Form'; | ||
3 | + | ||
4 | +enum FormFieldsEnum { | ||
5 | + DEVICE_TYPE = 'deviceType', | ||
6 | + SOURCE_DEVICE_PROFILE_ID = 'sourceDeviceProfileName', | ||
7 | + TARGET_DEVICE_PROFILE_ID = 'deviceProfileId', | ||
8 | +} | ||
9 | + | ||
10 | +export type FormGetFiledValueResultType = Record<FormFieldsEnum, string>; | ||
11 | + | ||
12 | +export const formSchemas: FormSchema[] = [ | ||
13 | + { | ||
14 | + field: FormFieldsEnum.SOURCE_DEVICE_PROFILE_ID, | ||
15 | + component: 'Input', | ||
16 | + label: '源产品', | ||
17 | + dynamicDisabled: true, | ||
18 | + required: true, | ||
19 | + }, | ||
20 | + { | ||
21 | + field: FormFieldsEnum.DEVICE_TYPE, | ||
22 | + label: '设备类型', | ||
23 | + component: 'Input', | ||
24 | + show: false, | ||
25 | + }, | ||
26 | + { | ||
27 | + field: FormFieldsEnum.TARGET_DEVICE_PROFILE_ID, | ||
28 | + component: 'ApiSelect', | ||
29 | + label: '目标产品', | ||
30 | + required: true, | ||
31 | + componentProps: ({ formModel }) => { | ||
32 | + return { | ||
33 | + api: getDeviceProfile, | ||
34 | + params: formModel[FormFieldsEnum.DEVICE_TYPE], | ||
35 | + labelField: 'name', | ||
36 | + valueField: 'tbProfileId', | ||
37 | + placeholder: '请选择目标产品', | ||
38 | + getPopupContainer: () => document.body, | ||
39 | + }; | ||
40 | + }, | ||
41 | + }, | ||
42 | +]; |
1 | +<script setup lang="ts"> | ||
2 | + import { ref, unref } from 'vue'; | ||
3 | + import { BatchUpdateProductModalParamsType } from '.'; | ||
4 | + import { FormGetFiledValueResultType, formSchemas } from './config'; | ||
5 | + import { doBatchUpdateProduct } from '/@/api/device/deviceManager'; | ||
6 | + import { BasicForm, useForm } from '/@/components/Form'; | ||
7 | + import Icon from '/@/components/Icon'; | ||
8 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | ||
9 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
10 | + | ||
11 | + const emits = defineEmits(['register', 'success']); | ||
12 | + | ||
13 | + const deviceIds = ref<string[]>([]); | ||
14 | + const [registerForm, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ | ||
15 | + layout: 'vertical', | ||
16 | + showActionButtonGroup: false, | ||
17 | + schemas: formSchemas, | ||
18 | + }); | ||
19 | + | ||
20 | + const [registerModal, { setModalProps, closeModal }] = useModalInner( | ||
21 | + async ({ record }: BatchUpdateProductModalParamsType) => { | ||
22 | + resetFields(); | ||
23 | + deviceIds.value = record.deviceIds; | ||
24 | + setFieldsValue(record); | ||
25 | + } | ||
26 | + ); | ||
27 | + | ||
28 | + const { createMessage } = useMessage(); | ||
29 | + const handleOk = async () => { | ||
30 | + try { | ||
31 | + await validate(); | ||
32 | + setModalProps({ loading: true, confirmLoading: true }); | ||
33 | + | ||
34 | + const result = getFieldsValue() as FormGetFiledValueResultType; | ||
35 | + | ||
36 | + await doBatchUpdateProduct({ | ||
37 | + deviceIds: unref(deviceIds), | ||
38 | + deviceProfileId: result.deviceProfileId, | ||
39 | + }); | ||
40 | + | ||
41 | + createMessage.success('操作成功'); | ||
42 | + | ||
43 | + closeModal(); | ||
44 | + emits('success'); | ||
45 | + } finally { | ||
46 | + setModalProps({ loading: false, confirmLoading: false }); | ||
47 | + } | ||
48 | + }; | ||
49 | +</script> | ||
50 | + | ||
51 | +<template> | ||
52 | + <BasicModal @register="registerModal" @ok="handleOk"> | ||
53 | + <template #title> | ||
54 | + <div>批量更新产品</div> | ||
55 | + <div class="mt-4 font-normal text-sm"> | ||
56 | + <Icon icon="ant-design:info-circle-outlined" /> | ||
57 | + <span> | ||
58 | + 注意:修改设备产品时只能修改为同类型产品,如果"大屏"、"组态"、"看板"、"场景联动"、"数据流转"等有关联设备,请自行调整并保存。 | ||
59 | + </span> | ||
60 | + </div> | ||
61 | + </template> | ||
62 | + <!-- <template #title> | ||
63 | + <span></span> | ||
64 | + </template> --> | ||
65 | + <BasicForm @register="registerForm" /> | ||
66 | + </BasicModal> | ||
67 | +</template> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | @next="handleStep1Next" | 20 | @next="handleStep1Next" |
21 | ref="DeviceStep1Ref" | 21 | ref="DeviceStep1Ref" |
22 | v-show="current === 0" | 22 | v-show="current === 0" |
23 | - :isUpdate="!isUpdate" | 23 | + :isUpdate="isUpdate" |
24 | /> | 24 | /> |
25 | <DeviceStep2 | 25 | <DeviceStep2 |
26 | ref="DeviceStep2Ref" | 26 | ref="DeviceStep2Ref" |
@@ -33,7 +33,7 @@ | @@ -33,7 +33,7 @@ | ||
33 | </BasicModal> | 33 | </BasicModal> |
34 | </template> | 34 | </template> |
35 | <script lang="ts"> | 35 | <script lang="ts"> |
36 | - import { defineComponent, ref, computed, unref } from 'vue'; | 36 | + import { defineComponent, ref, computed, unref, nextTick } from 'vue'; |
37 | import { BasicModal, useModalInner } from '/@/components/Modal'; | 37 | import { BasicModal, useModalInner } from '/@/components/Modal'; |
38 | import { createOrEditDevice } from '/@/api/device/deviceManager'; | 38 | import { createOrEditDevice } from '/@/api/device/deviceManager'; |
39 | import DeviceStep1 from '../step/DeviceStep1.vue'; | 39 | import DeviceStep1 from '../step/DeviceStep1.vue'; |
@@ -60,16 +60,17 @@ | @@ -60,16 +60,17 @@ | ||
60 | const DeviceStep2Ref = ref<InstanceType<typeof DeviceStep2>>(); | 60 | const DeviceStep2Ref = ref<InstanceType<typeof DeviceStep2>>(); |
61 | const { createMessage } = useMessage(); | 61 | const { createMessage } = useMessage(); |
62 | const current = ref(0); | 62 | const current = ref(0); |
63 | - const isUpdate = ref<Boolean>(false); | 63 | + const isUpdate = ref(false); |
64 | const deviceInfo = ref({}); | 64 | const deviceInfo = ref({}); |
65 | let currentDeviceData = {} as Recordable; | 65 | let currentDeviceData = {} as Recordable; |
66 | const getTitle = computed(() => (!unref(isUpdate) ? '新增设备' : '编辑设备')); | 66 | const getTitle = computed(() => (!unref(isUpdate) ? '新增设备' : '编辑设备')); |
67 | // 所有参数 | 67 | // 所有参数 |
68 | let stepState = ref(); | 68 | let stepState = ref(); |
69 | // 编辑回显 | 69 | // 编辑回显 |
70 | - const [register, { closeModal, setModalProps }] = useModalInner((data) => { | 70 | + const [register, { closeModal, setModalProps }] = useModalInner(async (data) => { |
71 | setModalProps({ confirmLoading: false, loading: true }); | 71 | setModalProps({ confirmLoading: false, loading: true }); |
72 | isUpdate.value = data?.isUpdate; | 72 | isUpdate.value = data?.isUpdate; |
73 | + await nextTick(); | ||
73 | if (unref(isUpdate)) { | 74 | if (unref(isUpdate)) { |
74 | const { record } = data; | 75 | const { record } = data; |
75 | currentDeviceData = record; | 76 | currentDeviceData = record; |
@@ -2,26 +2,6 @@ | @@ -2,26 +2,6 @@ | ||
2 | <div class="step1"> | 2 | <div class="step1"> |
3 | <div class="step1-form"> | 3 | <div class="step1-form"> |
4 | <BasicForm @register="register"> | 4 | <BasicForm @register="register"> |
5 | - <template #addOrg="{ model, field }"> | ||
6 | - <div style="display: flex; align-items: center"> | ||
7 | - <div style="width: 245px"> | ||
8 | - <a-tree-select | ||
9 | - @change="handleTreeOrg" | ||
10 | - v-model:value="model[field]" | ||
11 | - show-search | ||
12 | - style="width: 100%" | ||
13 | - :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }" | ||
14 | - placeholder="请选择组织" | ||
15 | - allow-clear | ||
16 | - tree-default-expand-all | ||
17 | - :tree-data="model?.['organizationList'] || treeData" | ||
18 | - /> | ||
19 | - </div> | ||
20 | - <div> | ||
21 | - <a-button type="link" @click="handleOpenOrgDrawer">新增组织</a-button> | ||
22 | - </div> | ||
23 | - </div> | ||
24 | - </template> | ||
25 | <template #snCode="{ model, field }"> | 5 | <template #snCode="{ model, field }"> |
26 | <div class="flex"> | 6 | <div class="flex"> |
27 | <Input :maxlength="36" v-model:value="model[field]" placeholder="请输入设备名称" /> | 7 | <Input :maxlength="36" v-model:value="model[field]" placeholder="请输入设备名称" /> |
@@ -36,7 +16,7 @@ | @@ -36,7 +16,7 @@ | ||
36 | </Input> | 16 | </Input> |
37 | </template> | 17 | </template> |
38 | </BasicForm> | 18 | </BasicForm> |
39 | - <div class="flex justify-center" v-if="isUpdate"> | 19 | + <div class="flex justify-center" v-if="!isUpdate"> |
40 | <a-button type="primary" @click="nextStep">下一步</a-button> | 20 | <a-button type="primary" @click="nextStep">下一步</a-button> |
41 | </div> | 21 | </div> |
42 | </div> | 22 | </div> |
@@ -91,11 +71,10 @@ | @@ -91,11 +71,10 @@ | ||
91 | </Spin> | 71 | </Spin> |
92 | </div> | 72 | </div> |
93 | </Modal> | 73 | </Modal> |
94 | - <DeptDrawer @register="registerModal" @success="handleSuccess" /> | ||
95 | </div> | 74 | </div> |
96 | </template> | 75 | </template> |
97 | <script lang="ts"> | 76 | <script lang="ts"> |
98 | - import { defineComponent, ref, nextTick, unref, reactive, toRefs, onMounted } from 'vue'; | 77 | + import { defineComponent, ref, nextTick, unref, reactive } from 'vue'; |
99 | import { BasicForm, useForm } from '/@/components/Form'; | 78 | import { BasicForm, useForm } from '/@/components/Form'; |
100 | import { step1Schemas } from '../../config/data'; | 79 | import { step1Schemas } from '../../config/data'; |
101 | import { useScript } from '/@/hooks/web/useScript'; | 80 | import { useScript } from '/@/hooks/web/useScript'; |
@@ -109,8 +88,6 @@ | @@ -109,8 +88,6 @@ | ||
109 | import { validatorLongitude, validatorLatitude } from '/@/utils/rules'; | 88 | import { validatorLongitude, validatorLatitude } from '/@/utils/rules'; |
110 | import { getOrganizationList } from '/@/api/system/system'; | 89 | import { getOrganizationList } from '/@/api/system/system'; |
111 | import { copyTransFun } from '/@/utils/fnUtils'; | 90 | import { copyTransFun } from '/@/utils/fnUtils'; |
112 | - import { useDrawer } from '/@/components/Drawer'; | ||
113 | - import DeptDrawer from '/@/views/system/organization/OrganizationDrawer.vue'; | ||
114 | import { TaskTypeEnum } from '/@/views/task/center/config'; | 91 | import { TaskTypeEnum } from '/@/views/task/center/config'; |
115 | import { toRaw } from 'vue'; | 92 | import { toRaw } from 'vue'; |
116 | import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; | 93 | import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; |
@@ -129,7 +106,6 @@ | @@ -129,7 +106,6 @@ | ||
129 | FormItem: Form.Item, | 106 | FormItem: Form.Item, |
130 | Row, | 107 | Row, |
131 | Col, | 108 | Col, |
132 | - DeptDrawer, | ||
133 | Spin, | 109 | Spin, |
134 | }, | 110 | }, |
135 | props: { | 111 | props: { |
@@ -152,16 +128,7 @@ | @@ -152,16 +128,7 @@ | ||
152 | copyTransFun(data as any as any[]); | 128 | copyTransFun(data as any as any[]); |
153 | orgData.treeData = data; | 129 | orgData.treeData = data; |
154 | }; | 130 | }; |
155 | - onMounted(async () => { | ||
156 | - await getOrganizationListFunc(); | ||
157 | - }); | ||
158 | - const { treeData } = toRefs(orgData); | ||
159 | - const [registerModal, { openDrawer }] = useDrawer(); | ||
160 | - const handleOpenOrgDrawer = () => { | ||
161 | - openDrawer(true, { | ||
162 | - isUpdate: false, | ||
163 | - }); | ||
164 | - }; | 131 | + |
165 | const handleSuccess = async () => { | 132 | const handleSuccess = async () => { |
166 | await getOrganizationListFunc(); | 133 | await getOrganizationListFunc(); |
167 | }; | 134 | }; |
@@ -178,27 +145,18 @@ | @@ -178,27 +145,18 @@ | ||
178 | const devicePic = ref(''); | 145 | const devicePic = ref(''); |
179 | const loading = ref(false); | 146 | const loading = ref(false); |
180 | 147 | ||
181 | - const [ | ||
182 | - register, | ||
183 | - { | ||
184 | - validate, | ||
185 | - resetFields, | ||
186 | - setFieldsValue, | ||
187 | - getFieldsValue, | ||
188 | - updateSchema, | ||
189 | - clearValidate, | ||
190 | - validateFields, | ||
191 | - }, | ||
192 | - ] = useForm({ | ||
193 | - labelWidth: 140, | ||
194 | - schemas: step1Schemas, | ||
195 | - actionColOptions: { | ||
196 | - span: 14, | ||
197 | - }, | ||
198 | - labelAlign: 'right', | ||
199 | - showResetButton: false, | ||
200 | - showSubmitButton: false, | ||
201 | - }); | 148 | + const [register, { validate, resetFields, setFieldsValue, getFieldsValue, updateSchema }] = |
149 | + useForm({ | ||
150 | + labelWidth: 140, | ||
151 | + schemas: step1Schemas, | ||
152 | + actionColOptions: { | ||
153 | + span: 14, | ||
154 | + }, | ||
155 | + labelAlign: 'right', | ||
156 | + showResetButton: false, | ||
157 | + showSubmitButton: false, | ||
158 | + }); | ||
159 | + | ||
202 | async function nextStep() { | 160 | async function nextStep() { |
203 | try { | 161 | try { |
204 | let values = await validate(); | 162 | let values = await validate(); |
@@ -245,7 +203,7 @@ | @@ -245,7 +203,7 @@ | ||
245 | const selectPosition = async () => { | 203 | const selectPosition = async () => { |
246 | visible.value = true; | 204 | visible.value = true; |
247 | if ( | 205 | if ( |
248 | - !unref(isUpdate1) && | 206 | + unref(isUpdate1) && |
249 | unref(devicePositionState).longitude && | 207 | unref(devicePositionState).longitude && |
250 | unref(devicePositionState).latitude | 208 | unref(devicePositionState).latitude |
251 | ) { | 209 | ) { |
@@ -440,8 +398,10 @@ | @@ -440,8 +398,10 @@ | ||
440 | positionState.address = deviceInfo.address; | 398 | positionState.address = deviceInfo.address; |
441 | devicePositionState.value = { ...toRaw(positionState) }; | 399 | devicePositionState.value = { ...toRaw(positionState) }; |
442 | devicePic.value = deviceInfo.avatar; | 400 | devicePic.value = deviceInfo.avatar; |
401 | + | ||
443 | if (deviceInfo.avatar) { | 402 | if (deviceInfo.avatar) { |
444 | setFieldsValue({ | 403 | setFieldsValue({ |
404 | + isUpdate: unref(isUpdate1), | ||
445 | icon: [{ uid: buildUUID(), name: 'name', url: deviceInfo.avatar } as FileItem], | 405 | icon: [{ uid: buildUUID(), name: 'name', url: deviceInfo.avatar } as FileItem], |
446 | }); | 406 | }); |
447 | } | 407 | } |
@@ -449,6 +409,7 @@ | @@ -449,6 +409,7 @@ | ||
449 | ...data, | 409 | ...data, |
450 | code: data?.code, | 410 | code: data?.code, |
451 | addressCode: parseInt(data?.code || '', 16), | 411 | addressCode: parseInt(data?.code || '', 16), |
412 | + isUpdate: unref(isUpdate1), | ||
452 | }); | 413 | }); |
453 | } | 414 | } |
454 | // 父组件调用获取字段值的方法 | 415 | // 父组件调用获取字段值的方法 |
@@ -499,13 +460,6 @@ | @@ -499,13 +460,6 @@ | ||
499 | }); | 460 | }); |
500 | } | 461 | } |
501 | 462 | ||
502 | - const handleTreeOrg = (option: string) => { | ||
503 | - if (option) clearValidate('organizationId'); | ||
504 | - else { | ||
505 | - validateFields(['organizationId']); | ||
506 | - } | ||
507 | - }; | ||
508 | - | ||
509 | return { | 463 | return { |
510 | resetFields, | 464 | resetFields, |
511 | positionState, | 465 | positionState, |
@@ -534,11 +488,7 @@ | @@ -534,11 +488,7 @@ | ||
534 | loading, | 488 | loading, |
535 | rules, | 489 | rules, |
536 | redirectPosition, | 490 | redirectPosition, |
537 | - treeData, | ||
538 | - registerModal, | ||
539 | - handleOpenOrgDrawer, | ||
540 | handleSuccess, | 491 | handleSuccess, |
541 | - handleTreeOrg, | ||
542 | devicePositionState, | 492 | devicePositionState, |
543 | spinning, | 493 | spinning, |
544 | }; | 494 | }; |
@@ -100,11 +100,9 @@ | @@ -100,11 +100,9 @@ | ||
100 | const { send, close } = useWebSocket(state.server, { | 100 | const { send, close } = useWebSocket(state.server, { |
101 | onConnected() { | 101 | onConnected() { |
102 | send(state.sendValue); | 102 | send(state.sendValue); |
103 | - console.log('建立连接了'); | ||
104 | }, | 103 | }, |
105 | onMessage(_, e) { | 104 | onMessage(_, e) { |
106 | const { data } = JSON.parse(e.data); | 105 | const { data } = JSON.parse(e.data); |
107 | - console.log('来新消息了', '---data---', data); | ||
108 | const newArray: socketDataType[] = []; | 106 | const newArray: socketDataType[] = []; |
109 | for (const key in data) { | 107 | for (const key in data) { |
110 | const [time, value] = data[key].flat(1); | 108 | const [time, value] = data[key].flat(1); |
@@ -134,7 +132,6 @@ | @@ -134,7 +132,6 @@ | ||
134 | }); | 132 | }); |
135 | }, | 133 | }, |
136 | onDisconnected() { | 134 | onDisconnected() { |
137 | - console.log('断开连接了'); | ||
138 | close(); | 135 | close(); |
139 | }, | 136 | }, |
140 | onError() { | 137 | onError() { |
@@ -32,13 +32,12 @@ | @@ -32,13 +32,12 @@ | ||
32 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; | 32 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
33 | import { Switch } from 'ant-design-vue'; | 33 | import { Switch } from 'ant-design-vue'; |
34 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; | 34 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; |
35 | - import { watch } from 'vue'; | ||
36 | import VideoModal from './videoModal.vue'; | 35 | import VideoModal from './videoModal.vue'; |
37 | import { useModal } from '/@/components/Modal'; | 36 | import { useModal } from '/@/components/Modal'; |
38 | import { onMounted } from 'vue'; | 37 | import { onMounted } from 'vue'; |
39 | import { useMessage } from '/@/hooks/web/useMessage'; | 38 | import { useMessage } from '/@/hooks/web/useMessage'; |
40 | 39 | ||
41 | - const props = defineProps({ | 40 | + defineProps({ |
42 | fromId: { | 41 | fromId: { |
43 | type: String, | 42 | type: String, |
44 | default: '', | 43 | default: '', |
@@ -49,13 +48,6 @@ | @@ -49,13 +48,6 @@ | ||
49 | }, | 48 | }, |
50 | }); | 49 | }); |
51 | 50 | ||
52 | - watch( | ||
53 | - () => props, | ||
54 | - () => { | ||
55 | - console.log(props, 'props'); | ||
56 | - } | ||
57 | - ); | ||
58 | - | ||
59 | const [registerModal, { openModal }] = useModal(); | 51 | const [registerModal, { openModal }] = useModal(); |
60 | 52 | ||
61 | const [registerTable, { setTableData, setProps, setSelectedRowKeys, reload }] = useTable({ | 53 | const [registerTable, { setTableData, setProps, setSelectedRowKeys, reload }] = useTable({ |
@@ -68,14 +60,10 @@ | @@ -68,14 +60,10 @@ | ||
68 | labelWidth: 120, | 60 | labelWidth: 120, |
69 | schemas: searchFormSchema, | 61 | schemas: searchFormSchema, |
70 | }, | 62 | }, |
71 | - beforeFetch: (params) => { | ||
72 | - console.log(params); | ||
73 | - }, | ||
74 | useSearchForm: true, | 63 | useSearchForm: true, |
75 | }); | 64 | }); |
76 | 65 | ||
77 | - const handleTurnVideo = async (checked: Boolean, record: Recordable) => { | ||
78 | - console.log(checked, record, 'record'); | 66 | + const handleTurnVideo = async (checked: Boolean, _record: Recordable) => { |
79 | setProps({ | 67 | setProps({ |
80 | loading: true, | 68 | loading: true, |
81 | }); | 69 | }); |
@@ -281,7 +269,6 @@ | @@ -281,7 +269,6 @@ | ||
281 | }); | 269 | }); |
282 | 270 | ||
283 | const handlePlay = (record: Recordable) => { | 271 | const handlePlay = (record: Recordable) => { |
284 | - console.log(record); | ||
285 | openModal(true, { | 272 | openModal(true, { |
286 | record, | 273 | record, |
287 | }); | 274 | }); |
@@ -4,41 +4,57 @@ | @@ -4,41 +4,57 @@ | ||
4 | <OrganizationIdTree @select="handleSelect" ref="organizationIdTreeRef" /> | 4 | <OrganizationIdTree @select="handleSelect" ref="organizationIdTreeRef" /> |
5 | <BasicTable style="flex: auto" @register="registerTable" class="w-5/6 xl:w-4/5"> | 5 | <BasicTable style="flex: auto" @register="registerTable" class="w-5/6 xl:w-4/5"> |
6 | <template #toolbar> | 6 | <template #toolbar> |
7 | - <Authority value="api:yt:device:post"> | 7 | + <Authority :value="DeviceListAuthEnum.CREATE"> |
8 | <a-button type="primary" @click="handleCreate" v-if="authBtn(role)"> | 8 | <a-button type="primary" @click="handleCreate" v-if="authBtn(role)"> |
9 | 新增设备 | 9 | 新增设备 |
10 | </a-button> | 10 | </a-button> |
11 | </Authority> | 11 | </Authority> |
12 | - <Authority value="api:yt:device:delete"> | ||
13 | - <Popconfirm | ||
14 | - title="您确定要批量删除数据" | ||
15 | - ok-text="确定" | ||
16 | - cancel-text="取消" | ||
17 | - @confirm="handleDelete()" | ||
18 | - > | ||
19 | - <a-button color="error" v-if="authBtn(role)" :disabled="!isExistOption"> | ||
20 | - 批量删除 | ||
21 | - </a-button> | ||
22 | - </Popconfirm> | ||
23 | - </Authority> | ||
24 | - <Authority value="api:yt:device:import"> | 12 | + |
13 | + <Authority :value="DeviceListAuthEnum.IMPORT"> | ||
25 | <Button type="primary" @click="handleBatchImport">导入</Button> | 14 | <Button type="primary" @click="handleBatchImport">导入</Button> |
26 | </Authority> | 15 | </Authority> |
27 | - <Authority value="api:yt:device:assign"> | ||
28 | - <a-button | 16 | + |
17 | + <Authority | ||
18 | + :value="[ | ||
19 | + DeviceListAuthEnum.DELETE, | ||
20 | + DeviceListAuthEnum.ASSIGN, | ||
21 | + DeviceListAuthEnum.UPDATE_PRODUCT, | ||
22 | + ]" | ||
23 | + > | ||
24 | + <AuthDropDown | ||
29 | v-if="authBtn(role)" | 25 | v-if="authBtn(role)" |
30 | - type="primary" | ||
31 | - @click="handleBatchAssign" | ||
32 | :disabled="!isExistOption" | 26 | :disabled="!isExistOption" |
27 | + :dropMenuList="[ | ||
28 | + { | ||
29 | + text: '删除设备', | ||
30 | + auth: DeviceListAuthEnum.DELETE, | ||
31 | + icon: 'ant-design:delete-outlined', | ||
32 | + event: '', | ||
33 | + popconfirm: { | ||
34 | + title: '您确定要批量删除数据', | ||
35 | + onConfirm: () => handleDelete(), | ||
36 | + }, | ||
37 | + }, | ||
38 | + { | ||
39 | + text: '分配客户', | ||
40 | + auth: DeviceListAuthEnum.ASSIGN, | ||
41 | + icon: 'mdi:account-arrow-left', | ||
42 | + event: '', | ||
43 | + onClick: handleBatchAssign.bind(null), | ||
44 | + }, | ||
45 | + { | ||
46 | + text: '更新产品', | ||
47 | + auth: DeviceListAuthEnum.UPDATE_PRODUCT, | ||
48 | + icon: 'clarity:note-edit-line', | ||
49 | + event: '', | ||
50 | + disabled: batchUpdateProductFlag, | ||
51 | + onClick: handelOpenBatchUpdateProductModal, | ||
52 | + }, | ||
53 | + ]" | ||
33 | > | 54 | > |
34 | - 批量分配 | ||
35 | - </a-button> | 55 | + <Button type="primary" :disabled="!isExistOption">批量操作</Button> |
56 | + </AuthDropDown> | ||
36 | </Authority> | 57 | </Authority> |
37 | - <!-- <Authority> | ||
38 | - <a-button type="primary" @click="handelCollect()" :disabled="!isExistOption"> | ||
39 | - 批量收藏 | ||
40 | - </a-button> | ||
41 | - </Authority> --> | ||
42 | </template> | 58 | </template> |
43 | <template #img="{ record }"> | 59 | <template #img="{ record }"> |
44 | <TableImg | 60 | <TableImg |
@@ -121,12 +137,12 @@ | @@ -121,12 +137,12 @@ | ||
121 | { | 137 | { |
122 | label: '详情', | 138 | label: '详情', |
123 | icon: 'ant-design:eye-outlined', | 139 | icon: 'ant-design:eye-outlined', |
124 | - auth: 'api:yt:device:get', | 140 | + auth: DeviceListAuthEnum.DETAIL, |
125 | onClick: handleDetail.bind(null, record), | 141 | onClick: handleDetail.bind(null, record), |
126 | }, | 142 | }, |
127 | { | 143 | { |
128 | label: '编辑', | 144 | label: '编辑', |
129 | - auth: 'api:yt:device:update', | 145 | + auth: DeviceListAuthEnum.UPDATE, |
130 | icon: 'clarity:note-edit-line', | 146 | icon: 'clarity:note-edit-line', |
131 | ifShow: authBtn(role), | 147 | ifShow: authBtn(role), |
132 | onClick: handleEdit.bind(null, record), | 148 | onClick: handleEdit.bind(null, record), |
@@ -138,7 +154,7 @@ | @@ -138,7 +154,7 @@ | ||
138 | label: '取消分配', | 154 | label: '取消分配', |
139 | icon: 'mdi:account-arrow-left', | 155 | icon: 'mdi:account-arrow-left', |
140 | ifShow: authBtn(role) && !record?.customerAdditionalInfo?.isPublic, | 156 | ifShow: authBtn(role) && !record?.customerAdditionalInfo?.isPublic, |
141 | - auth: 'api:yt:device:assign', | 157 | + auth: DeviceListAuthEnum.ASSIGN, |
142 | popConfirm: { | 158 | popConfirm: { |
143 | title: '是否取消分配客户', | 159 | title: '是否取消分配客户', |
144 | confirm: handleCancelDispatchCustomer.bind(null, record), | 160 | confirm: handleCancelDispatchCustomer.bind(null, record), |
@@ -148,12 +164,12 @@ | @@ -148,12 +164,12 @@ | ||
148 | label: '分配客户', | 164 | label: '分配客户', |
149 | icon: 'mdi:account-arrow-right', | 165 | icon: 'mdi:account-arrow-right', |
150 | ifShow: authBtn(role), | 166 | ifShow: authBtn(role), |
151 | - auth: 'api:yt:device:assign', | 167 | + auth: DeviceListAuthEnum.ASSIGN, |
152 | onClick: handleDispatchCustomer.bind(null, record), | 168 | onClick: handleDispatchCustomer.bind(null, record), |
153 | }, | 169 | }, |
154 | { | 170 | { |
155 | label: record?.customerAdditionalInfo?.isPublic ? '私有' : '公开', | 171 | label: record?.customerAdditionalInfo?.isPublic ? '私有' : '公开', |
156 | - auth: 'api:yt:device:public', | 172 | + auth: DeviceListAuthEnum.PUBLIC, |
157 | icon: record?.customerAdditionalInfo?.isPublic | 173 | icon: record?.customerAdditionalInfo?.isPublic |
158 | ? 'ant-design:lock-outlined' | 174 | ? 'ant-design:lock-outlined' |
159 | : 'ant-design:unlock-outlined', | 175 | : 'ant-design:unlock-outlined', |
@@ -161,7 +177,7 @@ | @@ -161,7 +177,7 @@ | ||
161 | }, | 177 | }, |
162 | { | 178 | { |
163 | label: '上下线记录', | 179 | label: '上下线记录', |
164 | - auth: 'api:yt:device:online:record', | 180 | + auth: DeviceListAuthEnum.ONLINE, |
165 | icon: 'ant-design:rise-outlined', | 181 | icon: 'ant-design:rise-outlined', |
166 | onClick: handleUpAndDownRecord.bind(null, record), | 182 | onClick: handleUpAndDownRecord.bind(null, record), |
167 | }, | 183 | }, |
@@ -173,7 +189,6 @@ | @@ -173,7 +189,6 @@ | ||
173 | } | 189 | } |
174 | : { | 190 | : { |
175 | label: '取消收藏', | 191 | label: '取消收藏', |
176 | - auth: 'api:yt:device:online:record', | ||
177 | icon: 'ant-design:heart-outlined', | 192 | icon: 'ant-design:heart-outlined', |
178 | popConfirm: { | 193 | popConfirm: { |
179 | title: '是否取消收藏', | 194 | title: '是否取消收藏', |
@@ -182,7 +197,7 @@ | @@ -182,7 +197,7 @@ | ||
182 | }, | 197 | }, |
183 | { | 198 | { |
184 | label: '删除', | 199 | label: '删除', |
185 | - auth: 'api:yt:device:delete', | 200 | + auth: DeviceListAuthEnum.DELETE, |
186 | icon: 'ant-design:delete-outlined', | 201 | icon: 'ant-design:delete-outlined', |
187 | ifShow: authBtn(role) && record.customerId === undefined, | 202 | ifShow: authBtn(role) && record.customerId === undefined, |
188 | color: 'error', | 203 | color: 'error', |
@@ -208,11 +223,16 @@ | @@ -208,11 +223,16 @@ | ||
208 | <CustomerModal @register="registerCustomerModal" @reload="handleReload" /> | 223 | <CustomerModal @register="registerCustomerModal" @reload="handleReload" /> |
209 | 224 | ||
210 | <BatchImportModal @register="registerImportModal" @import-finally="handleImportFinally" /> | 225 | <BatchImportModal @register="registerImportModal" @import-finally="handleImportFinally" /> |
226 | + | ||
227 | + <BatchUpdateProductModal | ||
228 | + @register="registerBatchUpdateProductModal" | ||
229 | + @success="handleBatchUpdateProductSuccess" | ||
230 | + /> | ||
211 | </PageWrapper> | 231 | </PageWrapper> |
212 | </div> | 232 | </div> |
213 | </template> | 233 | </template> |
214 | -<script lang="ts"> | ||
215 | - import { defineComponent, reactive, unref, onMounted } from 'vue'; | 234 | +<script lang="ts" setup> |
235 | + import { reactive, onMounted, ref } from 'vue'; | ||
216 | import { | 236 | import { |
217 | DeviceModel, | 237 | DeviceModel, |
218 | DeviceRecord, | 238 | DeviceRecord, |
@@ -220,8 +240,8 @@ | @@ -220,8 +240,8 @@ | ||
220 | DeviceTypeEnum, | 240 | DeviceTypeEnum, |
221 | } from '/@/api/device/model/deviceModel'; | 241 | } from '/@/api/device/model/deviceModel'; |
222 | import { BasicTable, useTable, TableAction, TableImg } from '/@/components/Table'; | 242 | import { BasicTable, useTable, TableAction, TableImg } from '/@/components/Table'; |
223 | - import { columns, searchFormSchema } from './config/device.data'; | ||
224 | - import { Tag, Popover, Popconfirm, Button, Tooltip } from 'ant-design-vue'; | 243 | + import { columns, DeviceListAuthEnum, searchFormSchema } from './config/device.data'; |
244 | + import { Tag, Popover, Button, Tooltip } from 'ant-design-vue'; | ||
225 | import { HeartTwoTone } from '@ant-design/icons-vue'; | 245 | import { HeartTwoTone } from '@ant-design/icons-vue'; |
226 | import { | 246 | import { |
227 | deleteDevice, | 247 | deleteDevice, |
@@ -246,326 +266,295 @@ | @@ -246,326 +266,295 @@ | ||
246 | import { USER_INFO_KEY } from '/@/enums/cacheEnum'; | 266 | import { USER_INFO_KEY } from '/@/enums/cacheEnum'; |
247 | import { getAuthCache } from '/@/utils/auth'; | 267 | import { getAuthCache } from '/@/utils/auth'; |
248 | import { authBtn } from '/@/enums/roleEnum'; | 268 | import { authBtn } from '/@/enums/roleEnum'; |
249 | - import { useClipboard } from '@vueuse/core'; | ||
250 | import { QuestionCircleOutlined } from '@ant-design/icons-vue'; | 269 | import { QuestionCircleOutlined } from '@ant-design/icons-vue'; |
251 | import { Authority } from '/@/components/Authority'; | 270 | import { Authority } from '/@/components/Authority'; |
252 | import { useRoute, useRouter } from 'vue-router'; | 271 | import { useRoute, useRouter } from 'vue-router'; |
253 | import { useBatchOperation } from '/@/utils/useBatchOperation'; | 272 | import { useBatchOperation } from '/@/utils/useBatchOperation'; |
254 | import { useSyncConfirm } from '/@/hooks/component/useSyncConfirm'; | 273 | import { useSyncConfirm } from '/@/hooks/component/useSyncConfirm'; |
255 | import { useAuthDeviceDetail } from './hook/useAuthDeviceDetail'; | 274 | import { useAuthDeviceDetail } from './hook/useAuthDeviceDetail'; |
275 | + import { | ||
276 | + BatchUpdateProductModal, | ||
277 | + BatchUpdateProductModalParamsType, | ||
278 | + } from './cpns/modal/BatchUpdateProductModal'; | ||
279 | + import { DataActionModeEnum } from '/@/enums/toolEnum'; | ||
280 | + import { AuthDropDown } from '/@/components/Widget'; | ||
256 | 281 | ||
257 | - export default defineComponent({ | ||
258 | - name: 'DeviceManagement', | ||
259 | - components: { | ||
260 | - BasicTable, | ||
261 | - PageWrapper, | ||
262 | - TableAction, | ||
263 | - OrganizationIdTree, | ||
264 | - Tag, | ||
265 | - DeviceModal, | ||
266 | - DeviceDetailDrawer, | ||
267 | - CustomerModal, | ||
268 | - TableImg, | ||
269 | - QuestionCircleOutlined, | ||
270 | - Popover, | ||
271 | - Authority, | ||
272 | - Popconfirm, | ||
273 | - BatchImportModal, | ||
274 | - Button, | ||
275 | - // HeartOutlined, | ||
276 | - HeartTwoTone, | ||
277 | - Tooltip, | ||
278 | - }, | ||
279 | - setup(_) { | ||
280 | - const { isCustomer } = useAuthDeviceDetail(); | ||
281 | - const { createMessage } = useMessage(); | ||
282 | - const go = useGo(); | ||
283 | - const ROUTER = useRouter(); | ||
284 | - const ROUTE = useRoute(); | ||
285 | - const searchInfo = reactive<Recordable>({}); | ||
286 | - const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo); | ||
287 | - const [registerModal, { openModal }] = useModal(); | ||
288 | - const [registerCustomerModal, { openModal: openCustomerModal }] = useModal(); | ||
289 | - const [registerDetailDrawer, { openDrawer }] = useDrawer(); | ||
290 | - const [registerTbDetailDrawer, { openDrawer: openTbDeviceDrawer }] = useDrawer(); | ||
291 | - const [registerGatewayDetailDrawer, { openDrawer: openGatewayDetailDrawer }] = useDrawer(); | ||
292 | - const [registerImportModal, { openModal: openImportModal }] = useModal(); | 282 | + const { isCustomer } = useAuthDeviceDetail(); |
283 | + const { createMessage } = useMessage(); | ||
284 | + const go = useGo(); | ||
285 | + const ROUTER = useRouter(); | ||
286 | + const ROUTE = useRoute(); | ||
287 | + const searchInfo = reactive<Recordable>({}); | ||
288 | + const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo); | ||
289 | + const [registerModal, { openModal }] = useModal(); | ||
290 | + const [registerCustomerModal, { openModal: openCustomerModal }] = useModal(); | ||
291 | + const [registerDetailDrawer, { openDrawer }] = useDrawer(); | ||
292 | + const [registerTbDetailDrawer, { openDrawer: openTbDeviceDrawer }] = useDrawer(); | ||
293 | + const [registerGatewayDetailDrawer, { openDrawer: openGatewayDetailDrawer }] = useDrawer(); | ||
294 | + const [registerImportModal, { openModal: openImportModal }] = useModal(); | ||
295 | + const [registerBatchUpdateProductModal, { openModal: openBatchUpdateProductModal }] = useModal(); | ||
293 | 296 | ||
294 | - const [ | ||
295 | - registerTable, | ||
296 | - { | ||
297 | - reload, | ||
298 | - setLoading, | ||
299 | - setSelectedRowKeys, | ||
300 | - getForm, | ||
301 | - getSelectRowKeys, | ||
302 | - getSelectRows, | ||
303 | - getRowSelection, | ||
304 | - }, | ||
305 | - ] = useTable({ | ||
306 | - title: '设备列表', | ||
307 | - api: devicePage, | ||
308 | - columns, | ||
309 | - beforeFetch: (params) => { | ||
310 | - const { deviceProfileId } = params; | ||
311 | - if (!deviceProfileId) return; | ||
312 | - const obj = { | ||
313 | - ...params, | ||
314 | - ...{ | ||
315 | - deviceProfileIds: deviceProfileId ? [deviceProfileId] : null, | ||
316 | - }, | ||
317 | - }; | ||
318 | - delete obj.deviceProfileId; | ||
319 | - return obj; | ||
320 | - }, | ||
321 | - formConfig: { | ||
322 | - labelWidth: 100, | ||
323 | - schemas: searchFormSchema, | ||
324 | - resetFunc: resetFn, | ||
325 | - }, | ||
326 | - useSearchForm: true, | ||
327 | - showTableSetting: true, | ||
328 | - bordered: true, | ||
329 | - showIndexColumn: false, | ||
330 | - rowKey: 'id', | ||
331 | - searchInfo: searchInfo, | ||
332 | - clickToRowSelect: false, | ||
333 | - actionColumn: { | ||
334 | - width: 200, | ||
335 | - title: '操作', | ||
336 | - slots: { customRender: 'action' }, | ||
337 | - fixed: 'right', | ||
338 | - }, | ||
339 | - rowSelection: { | ||
340 | - type: 'checkbox', | ||
341 | - getCheckboxProps: (record: DeviceModel) => { | ||
342 | - return { disabled: !!record.customerId }; | ||
343 | - }, | 297 | + const batchUpdateProductFlag = ref(true); |
298 | + | ||
299 | + const [ | ||
300 | + registerTable, | ||
301 | + { | ||
302 | + reload, | ||
303 | + setLoading, | ||
304 | + setSelectedRowKeys, | ||
305 | + getForm, | ||
306 | + getSelectRowKeys, | ||
307 | + getSelectRows, | ||
308 | + getRowSelection, | ||
309 | + clearSelectedRowKeys, | ||
310 | + }, | ||
311 | + ] = useTable({ | ||
312 | + title: '设备列表', | ||
313 | + api: devicePage, | ||
314 | + columns, | ||
315 | + beforeFetch: (params) => { | ||
316 | + const { deviceProfileId } = params; | ||
317 | + if (!deviceProfileId) return; | ||
318 | + const obj = { | ||
319 | + ...params, | ||
320 | + ...{ | ||
321 | + deviceProfileIds: deviceProfileId ? [deviceProfileId] : null, | ||
344 | }, | 322 | }, |
345 | - }); | 323 | + }; |
324 | + delete obj.deviceProfileId; | ||
325 | + return obj; | ||
326 | + }, | ||
327 | + formConfig: { | ||
328 | + labelWidth: 100, | ||
329 | + schemas: searchFormSchema, | ||
330 | + resetFunc: resetFn, | ||
331 | + }, | ||
332 | + useSearchForm: true, | ||
333 | + showTableSetting: true, | ||
334 | + bordered: true, | ||
335 | + showIndexColumn: false, | ||
336 | + rowKey: 'id', | ||
337 | + searchInfo: searchInfo, | ||
338 | + clickToRowSelect: false, | ||
339 | + actionColumn: { | ||
340 | + width: 200, | ||
341 | + title: '操作', | ||
342 | + slots: { customRender: 'action' }, | ||
343 | + fixed: 'right', | ||
344 | + }, | ||
345 | + rowSelection: { | ||
346 | + type: 'checkbox', | ||
347 | + getCheckboxProps: (record: DeviceModel) => { | ||
348 | + return { disabled: !!record.customerId }; | ||
349 | + }, | ||
350 | + onSelect(_record, _selected, selectedRows) { | ||
351 | + const [firstItem] = selectedRows as DeviceRecord[]; | ||
352 | + const { deviceType } = firstItem || {}; | ||
353 | + batchUpdateProductFlag.value = | ||
354 | + !selectedRows.length || | ||
355 | + !selectedRows.every((item) => (item as DeviceRecord).deviceType === deviceType); | ||
356 | + }, | ||
357 | + onSelectAll(_selected, selectedRows) { | ||
358 | + const [firstItem] = selectedRows as DeviceRecord[]; | ||
359 | + const { deviceType } = firstItem || {}; | ||
360 | + batchUpdateProductFlag.value = | ||
361 | + !selectedRows.length || | ||
362 | + !selectedRows.every((item) => (item as DeviceRecord).deviceType === deviceType); | ||
363 | + }, | ||
364 | + }, | ||
365 | + }); | ||
346 | 366 | ||
347 | - const { isExistOption } = useBatchOperation(getRowSelection, setSelectedRowKeys); | 367 | + const { isExistOption } = useBatchOperation(getRowSelection, setSelectedRowKeys); |
348 | 368 | ||
349 | - const userInfo: any = getAuthCache(USER_INFO_KEY); | ||
350 | - const role: string = userInfo.roles[0]; | 369 | + const userInfo: any = getAuthCache(USER_INFO_KEY); |
370 | + const role: string = userInfo.roles[0]; | ||
351 | 371 | ||
352 | - function handleCreate() { | ||
353 | - openModal(true, { | ||
354 | - isUpdate: false, | ||
355 | - }); | ||
356 | - } | ||
357 | - // 分配客户 | ||
358 | - function handleDispatchCustomer(record: Recordable) { | ||
359 | - openCustomerModal(true, record); | ||
360 | - } | ||
361 | - function handleReload() { | ||
362 | - setSelectedRowKeys([]); | ||
363 | - handleSuccess(); | ||
364 | - } | ||
365 | - // 取消分配客户 | ||
366 | - async function handleCancelDispatchCustomer(record: Recordable) { | ||
367 | - try { | ||
368 | - // 该设备是否正在被场景联动使用中? | ||
369 | - await cancelDispatchCustomer(record); | ||
370 | - handleReload(); | ||
371 | - } catch {} | ||
372 | - } | 372 | + function handleCreate() { |
373 | + openModal(true, { | ||
374 | + isUpdate: false, | ||
375 | + }); | ||
376 | + } | ||
377 | + // 分配客户 | ||
378 | + function handleDispatchCustomer(record: Recordable) { | ||
379 | + openCustomerModal(true, record); | ||
380 | + } | ||
381 | + function handleReload() { | ||
382 | + setSelectedRowKeys([]); | ||
383 | + handleSuccess(); | ||
384 | + } | ||
385 | + // 取消分配客户 | ||
386 | + async function handleCancelDispatchCustomer(record: Recordable) { | ||
387 | + try { | ||
388 | + // 该设备是否正在被场景联动使用中? | ||
389 | + await cancelDispatchCustomer(record); | ||
390 | + handleReload(); | ||
391 | + } catch {} | ||
392 | + } | ||
373 | 393 | ||
374 | - function handleDetail(record: Recordable) { | ||
375 | - const { id, tbDeviceId, deviceProfile, deviceType } = record; | ||
376 | - const { transportType } = deviceProfile || {}; | ||
377 | - openDrawer(true, { | ||
378 | - id, | ||
379 | - tbDeviceId, | ||
380 | - transportType, | ||
381 | - deviceType, | ||
382 | - }); | ||
383 | - } | 394 | + function handleDetail(record: Recordable) { |
395 | + const { id, tbDeviceId, deviceProfile, deviceType } = record; | ||
396 | + const { transportType } = deviceProfile || {}; | ||
397 | + openDrawer(true, { | ||
398 | + id, | ||
399 | + tbDeviceId, | ||
400 | + transportType, | ||
401 | + deviceType, | ||
402 | + }); | ||
403 | + } | ||
384 | 404 | ||
385 | - async function handleEdit(record: Recordable) { | ||
386 | - if (record.deviceType === 'SENSOR') { | ||
387 | - const res = await getGATEWAY(record.tbDeviceId); | ||
388 | - Reflect.set(record, 'gatewayId', res.tbDeviceId); | ||
389 | - } | ||
390 | - openModal(true, { | ||
391 | - isUpdate: true, | ||
392 | - record, | ||
393 | - }); | ||
394 | - } | ||
395 | - function handleSuccess() { | ||
396 | - reload(); | ||
397 | - } | ||
398 | - function handleSelect(organization) { | ||
399 | - searchInfo.organizationId = organization; | ||
400 | - handleSuccess(); | ||
401 | - } | ||
402 | - function goDeviceProfile(e) { | ||
403 | - go(PageEnum.DEVICE_PROFILE + '?name=' + encodeURIComponent(String(e))); | ||
404 | - } | ||
405 | - const { copied, copy } = useClipboard({ legacy: true }); | ||
406 | - const copySN = async (snCode: string) => { | ||
407 | - await copy(snCode); | ||
408 | - if (unref(copied)) { | ||
409 | - createMessage.success('复制成功~'); | ||
410 | - } | ||
411 | - }; | 405 | + async function handleEdit(record: Recordable) { |
406 | + if (record.deviceType === 'SENSOR') { | ||
407 | + const res = await getGATEWAY(record.tbDeviceId); | ||
408 | + Reflect.set(record, 'gatewayId', res.tbDeviceId); | ||
409 | + } | ||
410 | + openModal(true, { | ||
411 | + isUpdate: true, | ||
412 | + record, | ||
413 | + }); | ||
414 | + } | ||
415 | + function handleSuccess() { | ||
416 | + reload(); | ||
417 | + } | ||
418 | + function handleSelect(organization) { | ||
419 | + searchInfo.organizationId = organization; | ||
420 | + handleSuccess(); | ||
421 | + } | ||
422 | + function goDeviceProfile(e) { | ||
423 | + go(PageEnum.DEVICE_PROFILE + '?name=' + encodeURIComponent(String(e))); | ||
424 | + } | ||
412 | 425 | ||
413 | - const handleOpenTbDeviceDetail = (data: { id: string; tbDeviceId: string }) => { | ||
414 | - openTbDeviceDrawer(true, data); | ||
415 | - }; | 426 | + const handleOpenTbDeviceDetail = (data: { id: string; tbDeviceId: string }) => { |
427 | + openTbDeviceDrawer(true, data); | ||
428 | + }; | ||
416 | 429 | ||
417 | - const handleOpenGatewayDetail = (data: { id: string; tbDeviceId: string }) => { | ||
418 | - openGatewayDetailDrawer(true, data); | ||
419 | - }; | 430 | + const handleOpenGatewayDetail = (data: { id: string; tbDeviceId: string }) => { |
431 | + openGatewayDetailDrawer(true, data); | ||
432 | + }; | ||
420 | 433 | ||
421 | - const handleUpAndDownRecord = (record: Record<'name' | 'alias', string>) => { | ||
422 | - ROUTER.push({ | ||
423 | - path: '/operation/onlinerecord', | ||
424 | - query: { deviceName: record.alias || record.name }, | ||
425 | - }); | ||
426 | - }; | 434 | + const handleUpAndDownRecord = (record: Record<'name' | 'alias', string>) => { |
435 | + ROUTER.push({ | ||
436 | + path: '/operation/onlinerecord', | ||
437 | + query: { deviceName: record.alias || record.name }, | ||
438 | + }); | ||
439 | + }; | ||
427 | 440 | ||
428 | - const handleCheckHasDiffenterOrg = (options: DeviceModel[]) => { | ||
429 | - let orgId: string | undefined; | ||
430 | - let flag = false; | ||
431 | - for (const item of options) { | ||
432 | - const _orgId = item.organizationId; | ||
433 | - if (!orgId) orgId = _orgId; | ||
434 | - if (orgId !== _orgId) { | ||
435 | - flag = true; | ||
436 | - break; | ||
437 | - } | ||
438 | - } | ||
439 | - return flag; | ||
440 | - }; | 441 | + const handleCheckHasDiffenterOrg = (options: DeviceModel[]) => { |
442 | + let orgId: string | undefined; | ||
443 | + let flag = false; | ||
444 | + for (const item of options) { | ||
445 | + const _orgId = item.organizationId; | ||
446 | + if (!orgId) orgId = _orgId; | ||
447 | + if (orgId !== _orgId) { | ||
448 | + flag = true; | ||
449 | + break; | ||
450 | + } | ||
451 | + } | ||
452 | + return flag; | ||
453 | + }; | ||
441 | 454 | ||
442 | - const handleBatchAssign = () => { | ||
443 | - const options = getSelectRows(); | ||
444 | - if (handleCheckHasDiffenterOrg(options as DeviceModel[])) { | ||
445 | - createMessage.error('当前选中项中存在不同所属组织的设备!'); | ||
446 | - return; | ||
447 | - } | ||
448 | - openCustomerModal(true, options); | ||
449 | - }; | 455 | + const handleBatchAssign = () => { |
456 | + const options = getSelectRows(); | ||
457 | + if (handleCheckHasDiffenterOrg(options as DeviceModel[])) { | ||
458 | + createMessage.error('当前选中项中存在不同所属组织的设备!'); | ||
459 | + return; | ||
460 | + } | ||
461 | + openCustomerModal(true, options); | ||
462 | + }; | ||
450 | 463 | ||
451 | - const handleDelete = async (record?: DeviceRecord) => { | ||
452 | - let ids: string[] = []; | ||
453 | - if (record) { | ||
454 | - ids.push(record.id); | ||
455 | - } else { | ||
456 | - ids = getSelectRowKeys(); | ||
457 | - } | ||
458 | - try { | ||
459 | - setLoading(true); | ||
460 | - await deleteDevice(ids); | ||
461 | - createMessage.success('删除成功'); | ||
462 | - handleReload(); | ||
463 | - } catch (error) { | ||
464 | - throw error; | ||
465 | - } finally { | ||
466 | - setLoading(false); | ||
467 | - } | ||
468 | - }; | 464 | + const handleDelete = async (record?: DeviceRecord) => { |
465 | + let ids: string[] = []; | ||
466 | + if (record) { | ||
467 | + ids.push(record.id); | ||
468 | + } else { | ||
469 | + ids = getSelectRowKeys(); | ||
470 | + } | ||
471 | + try { | ||
472 | + setLoading(true); | ||
473 | + await deleteDevice(ids); | ||
474 | + createMessage.success('删除成功'); | ||
475 | + handleReload(); | ||
476 | + } catch (error) { | ||
477 | + throw error; | ||
478 | + } finally { | ||
479 | + setLoading(false); | ||
480 | + } | ||
481 | + }; | ||
469 | 482 | ||
470 | - const handleBatchImport = () => { | ||
471 | - openImportModal(true); | ||
472 | - }; | 483 | + const handleBatchImport = () => { |
484 | + openImportModal(true); | ||
485 | + }; | ||
473 | 486 | ||
474 | - const handleImportFinally = () => { | ||
475 | - reload(); | ||
476 | - }; | 487 | + const handleImportFinally = () => { |
488 | + reload(); | ||
489 | + }; | ||
477 | 490 | ||
478 | - const { createSyncConfirm } = useSyncConfirm(); | ||
479 | - const handlePublicDevice = async (record: DeviceRecord) => { | ||
480 | - try { | ||
481 | - const publicFlag = record?.customerAdditionalInfo?.isPublic; | ||
482 | - const type = publicFlag ? '私有' : '公开'; | ||
483 | - const flag = await createSyncConfirm({ | ||
484 | - iconType: 'warning', | ||
485 | - title: `您确定要将设备 '${record.name}' 设为${type}吗?`, | ||
486 | - content: `确认后,设备及其所有数据将被设为${type}并${ | ||
487 | - publicFlag ? '不' : '' | ||
488 | - }可被其他人访问。`, | ||
489 | - }); | ||
490 | - if (!flag) return; | ||
491 | - if (publicFlag) { | ||
492 | - await privateDevice(record.tbDeviceId); | ||
493 | - } else { | ||
494 | - await publicDevice(record.tbDeviceId); | ||
495 | - } | ||
496 | - reload(); | ||
497 | - } catch (error) {} | ||
498 | - }; | 491 | + const { createSyncConfirm } = useSyncConfirm(); |
492 | + const handlePublicDevice = async (record: DeviceRecord) => { | ||
493 | + try { | ||
494 | + const publicFlag = record?.customerAdditionalInfo?.isPublic; | ||
495 | + const type = publicFlag ? '私有' : '公开'; | ||
496 | + const flag = await createSyncConfirm({ | ||
497 | + iconType: 'warning', | ||
498 | + title: `您确定要将设备 '${record.name}' 设为${type}吗?`, | ||
499 | + content: `确认后,设备及其所有数据将被设为${type}并${ | ||
500 | + publicFlag ? '不' : '' | ||
501 | + }可被其他人访问。`, | ||
502 | + }); | ||
503 | + if (!flag) return; | ||
504 | + if (publicFlag) { | ||
505 | + await privateDevice(record.tbDeviceId); | ||
506 | + } else { | ||
507 | + await publicDevice(record.tbDeviceId); | ||
508 | + } | ||
509 | + reload(); | ||
510 | + } catch (error) {} | ||
511 | + }; | ||
499 | 512 | ||
500 | - // 收藏 && 批量收藏 | ||
501 | - const handelCollect = async (record?: Recordable) => { | ||
502 | - let ids: string[] = []; | ||
503 | - if (record) { | ||
504 | - ids.push(record.id); | ||
505 | - } else { | ||
506 | - ids = await getSelectRowKeys(); | ||
507 | - } | ||
508 | - try { | ||
509 | - setLoading(true); | ||
510 | - await deviceCollect(ids); | ||
511 | - createMessage.success('操作成功'); | ||
512 | - handleReload(); | ||
513 | - } catch (error) { | ||
514 | - throw error; | ||
515 | - } finally { | ||
516 | - setLoading(false); | ||
517 | - } | ||
518 | - }; | 513 | + // 收藏 && 批量收藏 |
514 | + const handelCollect = async (record?: Recordable) => { | ||
515 | + let ids: string[] = []; | ||
516 | + if (record) { | ||
517 | + ids.push(record.id); | ||
518 | + } else { | ||
519 | + ids = await getSelectRowKeys(); | ||
520 | + } | ||
521 | + try { | ||
522 | + setLoading(true); | ||
523 | + await deviceCollect(ids); | ||
524 | + createMessage.success('操作成功'); | ||
525 | + handleReload(); | ||
526 | + } catch (error) { | ||
527 | + throw error; | ||
528 | + } finally { | ||
529 | + setLoading(false); | ||
530 | + } | ||
531 | + }; | ||
519 | 532 | ||
520 | - onMounted(() => { | ||
521 | - const queryParams = ROUTE.query as Record<'deviceProfileId', undefined | string>; | ||
522 | - const { setFieldsValue } = getForm(); | ||
523 | - setFieldsValue({ deviceProfileId: queryParams.deviceProfileId }); | ||
524 | - }); | ||
525 | - return { | ||
526 | - registerTable, | ||
527 | - handleCreate, | ||
528 | - handleDetail, | ||
529 | - handleEdit, | ||
530 | - handleSuccess, | ||
531 | - goDeviceProfile, | ||
532 | - handleSelect, | ||
533 | - registerModal, | ||
534 | - registerDetailDrawer, | ||
535 | - DeviceTypeEnum, | ||
536 | - DeviceState, | ||
537 | - searchInfo, | ||
538 | - organizationIdTreeRef, | ||
539 | - handleDispatchCustomer, | ||
540 | - handleCancelDispatchCustomer, | ||
541 | - registerCustomerModal, | ||
542 | - authBtn, | ||
543 | - role, | ||
544 | - copySN, | ||
545 | - isExistOption, | ||
546 | - handleDelete, | ||
547 | - handelCollect, | ||
548 | - // hasBatchDelete, | ||
549 | - // handleDeleteOrBatchDelete, | ||
550 | - handleReload, | ||
551 | - registerTbDetailDrawer, | ||
552 | - handleOpenTbDeviceDetail, | ||
553 | - handleOpenGatewayDetail, | ||
554 | - registerGatewayDetailDrawer, | ||
555 | - handleUpAndDownRecord, | ||
556 | - handleBatchAssign, | ||
557 | - registerImportModal, | ||
558 | - handleBatchImport, | ||
559 | - handleImportFinally, | ||
560 | - handlePublicDevice, | ||
561 | - isCustomer, | ||
562 | - }; | ||
563 | - }, | 533 | + onMounted(() => { |
534 | + const queryParams = ROUTE.query as Record<'deviceProfileId', undefined | string>; | ||
535 | + const { setFieldsValue } = getForm(); | ||
536 | + setFieldsValue({ deviceProfileId: queryParams.deviceProfileId }); | ||
564 | }); | 537 | }); |
538 | + | ||
539 | + const handelOpenBatchUpdateProductModal = () => { | ||
540 | + const rows: DeviceRecord[] = getSelectRows(); | ||
541 | + const [firstItem] = rows; | ||
542 | + | ||
543 | + openBatchUpdateProductModal(true, { | ||
544 | + mode: DataActionModeEnum.UPDATE, | ||
545 | + record: { | ||
546 | + sourceDeviceProfileName: firstItem.deviceProfile.name, | ||
547 | + deviceType: firstItem.deviceType, | ||
548 | + deviceIds: rows.map((item) => item.tbDeviceId), | ||
549 | + }, | ||
550 | + } as BatchUpdateProductModalParamsType); | ||
551 | + }; | ||
552 | + | ||
553 | + const handleBatchUpdateProductSuccess = () => { | ||
554 | + reload(); | ||
555 | + clearSelectedRowKeys(); | ||
556 | + batchUpdateProductFlag.value = true; | ||
557 | + }; | ||
565 | </script> | 558 | </script> |
566 | 559 | ||
567 | -<style scoped lang="css"> | ||
568 | - /* /deep/.ant-message-notice-content { | ||
569 | - max-width: 600px !important; | ||
570 | - } */ | ||
571 | -</style> | 560 | +<style scoped lang="css"></style> |
@@ -346,7 +346,6 @@ export const schemas: FormSchema[] = [ | @@ -346,7 +346,6 @@ export const schemas: FormSchema[] = [ | ||
346 | return { | 346 | return { |
347 | onChange(value) { | 347 | onChange(value) { |
348 | const { updateSchema } = formActionType; | 348 | const { updateSchema } = formActionType; |
349 | - console.log(value); | ||
350 | formModel.interval = ''; | 349 | formModel.interval = ''; |
351 | updateSchema({ | 350 | updateSchema({ |
352 | field: 'interval', | 351 | field: 'interval', |
@@ -235,7 +235,6 @@ | @@ -235,7 +235,6 @@ | ||
235 | 235 | ||
236 | function loadDataSuccess(excelDataList: ExcelData[]) { | 236 | function loadDataSuccess(excelDataList: ExcelData[]) { |
237 | tableListRef.value = []; | 237 | tableListRef.value = []; |
238 | - console.log(excelDataList); | ||
239 | for (const excelData of excelDataList) { | 238 | for (const excelData of excelDataList) { |
240 | const { | 239 | const { |
241 | header, | 240 | header, |
@@ -294,9 +293,7 @@ | @@ -294,9 +293,7 @@ | ||
294 | }); | 293 | }); |
295 | }; | 294 | }; |
296 | //导入 | 295 | //导入 |
297 | - function handleImport() { | ||
298 | - console.log('record'); | ||
299 | - } | 296 | + function handleImport() {} |
300 | function handleSuccess() { | 297 | function handleSuccess() { |
301 | reload(); | 298 | reload(); |
302 | } | 299 | } |
@@ -204,8 +204,7 @@ | @@ -204,8 +204,7 @@ | ||
204 | }); | 204 | }); |
205 | flag && createMessage.info(flag?.message); | 205 | flag && createMessage.info(flag?.message); |
206 | } catch (msg) { | 206 | } catch (msg) { |
207 | - // eslint-disable-next-line no-console | ||
208 | - console.log(msg, 'msg'); | 207 | + console.error(msg, 'msg'); |
209 | } finally { | 208 | } finally { |
210 | closeLoading(); | 209 | closeLoading(); |
211 | closeModal(); | 210 | closeModal(); |
@@ -96,7 +96,6 @@ | @@ -96,7 +96,6 @@ | ||
96 | render: (_, data: Bootstrap) => (data.notifIfDisabled ? '启用' : '禁用'), | 96 | render: (_, data: Bootstrap) => (data.notifIfDisabled ? '启用' : '禁用'), |
97 | }, | 97 | }, |
98 | ]; | 98 | ]; |
99 | - console.log(unref(getOtherSetting)); | ||
100 | const [registerOtherSettings] = useDescription({ | 99 | const [registerOtherSettings] = useDescription({ |
101 | layout: 'vertical', | 100 | layout: 'vertical', |
102 | column: 2, | 101 | column: 2, |
@@ -68,21 +68,18 @@ | @@ -68,21 +68,18 @@ | ||
68 | <Button v-if="isShowBtn" class="!bg-gray-200" type="text" @click="handleReturn"> | 68 | <Button v-if="isShowBtn" class="!bg-gray-200" type="text" @click="handleReturn"> |
69 | 返回 | 69 | 返回 |
70 | </Button> | 70 | </Button> |
71 | - <Authority :value="[ModelOfMatterPermission.DELETE, ModelCategoryPermission.DELETE]"> | 71 | + <Authority |
72 | + v-if="isShowBtn" | ||
73 | + :value="[ModelOfMatterPermission.DELETE, ModelCategoryPermission.DELETE]" | ||
74 | + > | ||
72 | <Popconfirm | 75 | <Popconfirm |
73 | title="您确定要批量删除数据" | 76 | title="您确定要批量删除数据" |
74 | ok-text="确定" | 77 | ok-text="确定" |
75 | cancel-text="取消" | 78 | cancel-text="取消" |
76 | - @confirm="handleDeleteOrBatchDelete(null)" | 79 | + @confirm="handleDeleteOrBatchDelete()" |
80 | + :disabled="getHasBatchDelete" | ||
77 | > | 81 | > |
78 | - <Button | ||
79 | - style="display: none" | ||
80 | - type="primary" | ||
81 | - color="error" | ||
82 | - :disabled="hasBatchDelete" | ||
83 | - > | ||
84 | - 批量删除 | ||
85 | - </Button> | 82 | + <Button type="primary" danger :disabled="getHasBatchDelete"> 批量删除 </Button> |
86 | </Popconfirm> | 83 | </Popconfirm> |
87 | </Authority> | 84 | </Authority> |
88 | </div> | 85 | </div> |
@@ -120,11 +117,7 @@ | @@ -120,11 +117,7 @@ | ||
120 | /> | 117 | /> |
121 | </template> | 118 | </template> |
122 | </BasicTable> | 119 | </BasicTable> |
123 | - <PhysicalModelModal | ||
124 | - :record="$props.record" | ||
125 | - @register="registerModal" | ||
126 | - @success="handleSuccess" | ||
127 | - /> | 120 | + <PhysicalModelModal :record="$props.record" @register="registerModal" @success="reload" /> |
128 | <PhysicalModelTsl :record="$props.record" @register="registerModalTsl" /> | 121 | <PhysicalModelTsl :record="$props.record" @register="registerModalTsl" /> |
129 | <SelectImport | 122 | <SelectImport |
130 | :record="$props.record" | 123 | :record="$props.record" |
@@ -142,7 +135,6 @@ | @@ -142,7 +135,6 @@ | ||
142 | ModelCategoryPermission, | 135 | ModelCategoryPermission, |
143 | physicalColumn, | 136 | physicalColumn, |
144 | } from '../device.profile.data'; | 137 | } from '../device.profile.data'; |
145 | - import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; | ||
146 | import { Authority } from '/@/components/Authority'; | 138 | import { Authority } from '/@/components/Authority'; |
147 | import PhysicalModelModal from './cpns/physical/PhysicalModelModal.vue'; | 139 | import PhysicalModelModal from './cpns/physical/PhysicalModelModal.vue'; |
148 | import PhysicalModelTsl from './cpns/physical/PhysicalModelTsl.vue'; | 140 | import PhysicalModelTsl from './cpns/physical/PhysicalModelTsl.vue'; |
@@ -156,8 +148,11 @@ | @@ -156,8 +148,11 @@ | ||
156 | releaseModel, | 148 | releaseModel, |
157 | } from '/@/api/device/modelOfMatter'; | 149 | } from '/@/api/device/modelOfMatter'; |
158 | import { OpenModelOfMatterModelParams, OpenModelMode } from './cpns/physical/types'; | 150 | import { OpenModelOfMatterModelParams, OpenModelMode } from './cpns/physical/types'; |
159 | - import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel'; | ||
160 | - import { ref, unref } from 'vue'; | 151 | + import { |
152 | + ModelOfMatterItemRecordType, | ||
153 | + ModelOfMatterParams, | ||
154 | + } from '/@/api/device/model/modelOfMatterModel'; | ||
155 | + import { computed, ref, unref } from 'vue'; | ||
161 | import { isObject } from '/@/utils/is'; | 156 | import { isObject } from '/@/utils/is'; |
162 | import { useRole } from '/@/hooks/business/useRole'; | 157 | import { useRole } from '/@/hooks/business/useRole'; |
163 | import { ExportModelCategory } from '/@/api/device/modelOfMatter'; | 158 | import { ExportModelCategory } from '/@/api/device/modelOfMatter'; |
@@ -177,50 +172,45 @@ | @@ -177,50 +172,45 @@ | ||
177 | const [registerModalTsl, { openModal: openModalTsl }] = useModal(); | 172 | const [registerModalTsl, { openModal: openModalTsl }] = useModal(); |
178 | const [registerModalSelect, { openModal: openModalSelect }] = useModal(); | 173 | const [registerModalSelect, { openModal: openModalSelect }] = useModal(); |
179 | 174 | ||
180 | - const [registerTable, { reload, setProps }] = useTable({ | ||
181 | - api: async (params: Record<'page' | 'pageSize', number>) => { | ||
182 | - return await getModelList({ | ||
183 | - ...params, | ||
184 | - id: props.record.id, | ||
185 | - selectType: props.record.ifShowClass ? 'category' : undefined, | ||
186 | - }); | ||
187 | - }, | ||
188 | - columns: props.record.ifShowClass | ||
189 | - ? physicalColumn.filter((item) => item.dataIndex !== 'status') | ||
190 | - : physicalColumn, | ||
191 | - showIndexColumn: false, | ||
192 | - clickToRowSelect: false, | ||
193 | - showTableSetting: true, | ||
194 | - bordered: true, | ||
195 | - useSearchForm: true, | ||
196 | - formConfig: { | ||
197 | - schemas: modelOfMatterForm, | ||
198 | - labelWidth: 120, | ||
199 | - }, | ||
200 | - actionColumn: { | ||
201 | - width: 200, | ||
202 | - title: '操作', | ||
203 | - dataIndex: 'action', | ||
204 | - slots: { customRender: 'action' }, | ||
205 | - fixed: 'right', | ||
206 | - }, | ||
207 | - }); | ||
208 | - | ||
209 | - // 刷新 | ||
210 | - const handleSuccess = () => { | ||
211 | - reload(); | ||
212 | - }; | ||
213 | - const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete( | ||
214 | - props.record.ifShowClass && (unref(isPlatformAdmin) || unref(isSysadmin)) | ||
215 | - ? deleteModelCategory | ||
216 | - : deleteModel, | ||
217 | - handleSuccess, | ||
218 | - setProps | ||
219 | - ); | 175 | + const [registerTable, { reload, getSelectRowKeys, getRowSelection, clearSelectedRowKeys }] = |
176 | + useTable({ | ||
177 | + api: async (params: Record<'page' | 'pageSize', number>) => { | ||
178 | + return await getModelList({ | ||
179 | + ...params, | ||
180 | + id: props.record.id, | ||
181 | + selectType: props.record.ifShowClass ? 'category' : undefined, | ||
182 | + }); | ||
183 | + }, | ||
184 | + columns: props.record.ifShowClass | ||
185 | + ? physicalColumn.filter((item) => item.dataIndex !== 'status') | ||
186 | + : physicalColumn, | ||
187 | + showIndexColumn: false, | ||
188 | + clickToRowSelect: false, | ||
189 | + showTableSetting: true, | ||
190 | + bordered: true, | ||
191 | + useSearchForm: true, | ||
192 | + rowKey: 'id', | ||
193 | + formConfig: { | ||
194 | + schemas: modelOfMatterForm, | ||
195 | + labelWidth: 120, | ||
196 | + }, | ||
197 | + actionColumn: { | ||
198 | + width: 200, | ||
199 | + title: '操作', | ||
200 | + dataIndex: 'action', | ||
201 | + slots: { customRender: 'action' }, | ||
202 | + fixed: 'right', | ||
203 | + }, | ||
204 | + rowSelection: { | ||
205 | + getCheckboxProps: (record: ModelOfMatterItemRecordType) => { | ||
206 | + return { | ||
207 | + disabled: record.status === 1, | ||
208 | + }; | ||
209 | + }, | ||
210 | + }, | ||
211 | + }); | ||
220 | 212 | ||
221 | - selectionOptions.rowSelection.getCheckboxProps = (record: Recordable) => { | ||
222 | - return { disabled: record.status === 1 }; | ||
223 | - }; | 213 | + const getHasBatchDelete = computed(() => !getRowSelection().selectedRowKeys?.length); |
224 | 214 | ||
225 | const handleViewDetail = (record: ModelOfMatterParams) => { | 215 | const handleViewDetail = (record: ModelOfMatterParams) => { |
226 | if (record) { | 216 | if (record) { |
@@ -245,6 +235,19 @@ | @@ -245,6 +235,19 @@ | ||
245 | } | 235 | } |
246 | }; | 236 | }; |
247 | 237 | ||
238 | + const handleDeleteOrBatchDelete = async (record?: ModelOfMatterItemRecordType) => { | ||
239 | + const deleteFn = | ||
240 | + props.record.ifShowClass && (unref(isPlatformAdmin) || unref(isSysadmin)) | ||
241 | + ? deleteModelCategory | ||
242 | + : deleteModel; | ||
243 | + | ||
244 | + const ids = record ? [record.id] : getSelectRowKeys(); | ||
245 | + await deleteFn(ids); | ||
246 | + createMessage.success('删除成功'); | ||
247 | + clearSelectedRowKeys(); | ||
248 | + reload(); | ||
249 | + }; | ||
250 | + | ||
248 | const handleOpenTsl = () => { | 251 | const handleOpenTsl = () => { |
249 | openModalTsl(true, { | 252 | openModalTsl(true, { |
250 | isUpdate: true, | 253 | isUpdate: true, |
@@ -30,9 +30,7 @@ | @@ -30,9 +30,7 @@ | ||
30 | import { SelectTypes } from 'ant-design-vue/es/select'; | 30 | import { SelectTypes } from 'ant-design-vue/es/select'; |
31 | 31 | ||
32 | const emit = defineEmits(['register', 'emitSelect']); | 32 | const emit = defineEmits(['register', 'emitSelect']); |
33 | - const [register] = useModalInner((data) => { | ||
34 | - console.log(data); | ||
35 | - }); | 33 | + const [register] = useModalInner(() => {}); |
36 | const heightNum = ref(80); | 34 | const heightNum = ref(80); |
37 | const visible = ref(false); | 35 | const visible = ref(false); |
38 | const selectValue = ref('LwM2M'); | 36 | const selectValue = ref('LwM2M'); |
@@ -130,14 +130,13 @@ | @@ -130,14 +130,13 @@ | ||
130 | telemetry: [], | 130 | telemetry: [], |
131 | }); | 131 | }); |
132 | 132 | ||
133 | - const [registerModel, { resetFields: resetObjectListValue, getFieldsValue: getObjectListValue }] = | ||
134 | - useForm({ | ||
135 | - labelWidth: 100, | ||
136 | - schemas: modelSchemas, | ||
137 | - actionColOptions: { | ||
138 | - span: 14, | ||
139 | - }, | ||
140 | - }); | 133 | + const [registerModel, { resetFields: resetObjectListValue }] = useForm({ |
134 | + labelWidth: 100, | ||
135 | + schemas: modelSchemas, | ||
136 | + actionColOptions: { | ||
137 | + span: 14, | ||
138 | + }, | ||
139 | + }); | ||
141 | const [ | 140 | const [ |
142 | registerSettings, | 141 | registerSettings, |
143 | { | 142 | { |
@@ -152,14 +151,13 @@ | @@ -152,14 +151,13 @@ | ||
152 | span: 14, | 151 | span: 14, |
153 | }, | 152 | }, |
154 | }); | 153 | }); |
155 | - const [registerDevice, { resetFields: resetDeviceValue, getFieldsValue: getDeviceValue }] = | ||
156 | - useForm({ | ||
157 | - labelWidth: 100, | ||
158 | - schemas: deviceSchemas, | ||
159 | - actionColOptions: { | ||
160 | - span: 14, | ||
161 | - }, | ||
162 | - }); | 154 | + const [registerDevice, { resetFields: resetDeviceValue }] = useForm({ |
155 | + labelWidth: 100, | ||
156 | + schemas: deviceSchemas, | ||
157 | + actionColOptions: { | ||
158 | + span: 14, | ||
159 | + }, | ||
160 | + }); | ||
163 | const [registerModal, { openModal }] = useModal(); | 161 | const [registerModal, { openModal }] = useModal(); |
164 | 162 | ||
165 | const handleAdd = () => { | 163 | const handleAdd = () => { |
@@ -205,10 +203,6 @@ | @@ -205,10 +203,6 @@ | ||
205 | }; | 203 | }; |
206 | 204 | ||
207 | const getFormData = async () => { | 205 | const getFormData = async () => { |
208 | - const objectListVal = getObjectListValue(); | ||
209 | - const deviceVal = getDeviceValue(); | ||
210 | - console.log('第一个tab', objectListVal); | ||
211 | - console.log('第四个tab', deviceVal); | ||
212 | getBootStrapFormValue(); | 206 | getBootStrapFormValue(); |
213 | const settingsVal = await settingsValidate(); | 207 | const settingsVal = await settingsValidate(); |
214 | if (!settingsVal) return; | 208 | if (!settingsVal) return; |
@@ -69,7 +69,7 @@ | @@ -69,7 +69,7 @@ | ||
69 | if (unref(copied)) createMessage.success('复制成功!'); | 69 | if (unref(copied)) createMessage.success('复制成功!'); |
70 | else createMessage.error('复制失败!'); | 70 | else createMessage.error('复制失败!'); |
71 | } catch (e) { | 71 | } catch (e) { |
72 | - console.log(e); | 72 | + console.error(e); |
73 | } | 73 | } |
74 | }; | 74 | }; |
75 | 75 |
@@ -172,8 +172,7 @@ export const formSchema: FormSchema[] = [ | @@ -172,8 +172,7 @@ export const formSchema: FormSchema[] = [ | ||
172 | const record = await findMessageConfig(params); | 172 | const record = await findMessageConfig(params); |
173 | return record.filter((item) => item.status === 1); | 173 | return record.filter((item) => item.status === 1); |
174 | } catch (error) { | 174 | } catch (error) { |
175 | - // eslint-disable-next-line no-console | ||
176 | - console.log(error); | 175 | + console.error(error); |
177 | return []; | 176 | return []; |
178 | } | 177 | } |
179 | }, | 178 | }, |
@@ -41,7 +41,7 @@ | @@ -41,7 +41,7 @@ | ||
41 | checksumAlgorithm: value.checksumAlgorithm, | 41 | checksumAlgorithm: value.checksumAlgorithm, |
42 | }); | 42 | }); |
43 | } catch (error) { | 43 | } catch (error) { |
44 | - console.log(error); | 44 | + console.error(error); |
45 | if ((error as { status: number }).status) { | 45 | if ((error as { status: number }).status) { |
46 | await deleteOtaPackage(id); | 46 | await deleteOtaPackage(id); |
47 | } | 47 | } |
@@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
6 | border-color: #6b7280; | 6 | border-color: #6b7280; |
7 | } | 7 | } |
8 | 8 | ||
9 | -.vue-flow__handle:hover{ | 9 | +.vue-flow__handle:hover { |
10 | background-color: #000; | 10 | background-color: #000; |
11 | } | 11 | } |
12 | 12 | ||
@@ -15,7 +15,7 @@ | @@ -15,7 +15,7 @@ | ||
15 | } | 15 | } |
16 | 16 | ||
17 | .vue-flow__handle-left { | 17 | .vue-flow__handle-left { |
18 | - left: -12px; | 18 | + left: -12px; |
19 | } | 19 | } |
20 | 20 | ||
21 | .vue-flow__background.vue-flow__container { | 21 | .vue-flow__background.vue-flow__container { |
@@ -32,7 +32,7 @@ | @@ -32,7 +32,7 @@ | ||
32 | stroke-width: 4; | 32 | stroke-width: 4; |
33 | stroke: gray; | 33 | stroke: gray; |
34 | transition: stroke-width 0.3s; | 34 | transition: stroke-width 0.3s; |
35 | -} | 35 | +} |
36 | 36 | ||
37 | .connection-focus { | 37 | .connection-focus { |
38 | stroke-width: 6; | 38 | stroke-width: 6; |
@@ -44,7 +44,7 @@ | @@ -44,7 +44,7 @@ | ||
44 | } | 44 | } |
45 | 45 | ||
46 | /* 连接线移入放大效果 */ | 46 | /* 连接线移入放大效果 */ |
47 | -.vue-flow__edge:hover > .vue-flow__edge-path { | 47 | +.vue-flow__edge:hover > .vue-flow__edge-path { |
48 | stroke-width: 6 !important; | 48 | stroke-width: 6 !important; |
49 | } | 49 | } |
50 | 50 | ||
@@ -54,18 +54,19 @@ | @@ -54,18 +54,19 @@ | ||
54 | } | 54 | } |
55 | 55 | ||
56 | .vue-flow__edge:hover .vue-flow__edge-textbg { | 56 | .vue-flow__edge:hover .vue-flow__edge-textbg { |
57 | - transform: scale(1.1) | 57 | + transform: scale(1.1); |
58 | } | 58 | } |
59 | 59 | ||
60 | -.vue-flow__edge:hover .vue-flow__edge-text{ | ||
61 | - transform: scale(1.1) | 60 | +.vue-flow__edge:hover .vue-flow__edge-text { |
61 | + transform: scale(1.1); | ||
62 | } | 62 | } |
63 | 63 | ||
64 | /* selection 选择框 */ | 64 | /* selection 选择框 */ |
65 | -.vue-flow__nodesselection-rect, .vue-flow__selection{ | 65 | +.vue-flow__nodesselection-rect, |
66 | +.vue-flow__selection { | ||
66 | border-width: 3px; | 67 | border-width: 3px; |
67 | } | 68 | } |
68 | 69 | ||
69 | -.vue-flow__nodesselection-rect { | 70 | +.vue-flow__nodesselection-rect { |
70 | pointer-events: none; | 71 | pointer-events: none; |
71 | } | 72 | } |
@@ -236,7 +236,7 @@ | @@ -236,7 +236,7 @@ | ||
236 | // 设置输出值 | 236 | // 设置输出值 |
237 | outputEditor.value.set(result); | 237 | outputEditor.value.set(result); |
238 | } catch (e) { | 238 | } catch (e) { |
239 | - console.log(e); | 239 | + console.error(e); |
240 | const { createMessage } = useMessage(); | 240 | const { createMessage } = useMessage(); |
241 | createMessage.error(e.toString()); | 241 | createMessage.error(e.toString()); |
242 | } | 242 | } |
@@ -85,9 +85,7 @@ | @@ -85,9 +85,7 @@ | ||
85 | /^[1](([3][0-9])|([4][0,1,4-9])|([5][0-3,5-9])|([6][2,5,6,7])|([7][0-8])|([8][0-9])|([9][0-3,5-9]))[0-9]{8}$/; | 85 | /^[1](([3][0-9])|([4][0,1,4-9])|([5][0-3,5-9])|([6][2,5,6,7])|([7][0-8])|([8][0-9])|([9][0-3,5-9]))[0-9]{8}$/; |
86 | if (reg.test(formData.mobile)) { | 86 | if (reg.test(formData.mobile)) { |
87 | const sendRes = await passwordResetCode(formData.mobile); | 87 | const sendRes = await passwordResetCode(formData.mobile); |
88 | - console.log(sendRes); | ||
89 | if (sendRes === '') { | 88 | if (sendRes === '') { |
90 | - console.log('发送成功了'); | ||
91 | return true; | 89 | return true; |
92 | } | 90 | } |
93 | return false; | 91 | return false; |
@@ -27,7 +27,6 @@ | @@ -27,7 +27,6 @@ | ||
27 | onMounted(() => { | 27 | onMounted(() => { |
28 | // 记录当前的UserId | 28 | // 记录当前的UserId |
29 | userId.value = userStore.getUserInfo?.userId; | 29 | userId.value = userStore.getUserInfo?.userId; |
30 | - console.log('Mounted', userStore.getUserInfo); | ||
31 | }); | 30 | }); |
32 | 31 | ||
33 | onBeforeUnmount(() => { | 32 | onBeforeUnmount(() => { |
@@ -69,8 +69,8 @@ export function useFormRules(formData?: Recordable) { | @@ -69,8 +69,8 @@ export function useFormRules(formData?: Recordable) { | ||
69 | const mobileFormRule = unref(getMobileFormRule); | 69 | const mobileFormRule = unref(getMobileFormRule); |
70 | 70 | ||
71 | const mobileRule = { | 71 | const mobileRule = { |
72 | - sms: smsFormRule, | ||
73 | - mobile: mobileFormRule, | 72 | + code: smsFormRule, |
73 | + phoneNumber: mobileFormRule, | ||
74 | }; | 74 | }; |
75 | switch (unref(currentState)) { | 75 | switch (unref(currentState)) { |
76 | // register form rules | 76 | // register form rules |
@@ -14,7 +14,6 @@ | @@ -14,7 +14,6 @@ | ||
14 | Reflect.deleteProperty(params, 'path'); | 14 | Reflect.deleteProperty(params, 'path'); |
15 | 15 | ||
16 | const _path = Array.isArray(path) ? path.join('/') : path; | 16 | const _path = Array.isArray(path) ? path.join('/') : path; |
17 | - console.log(unref(currentRoute)); | ||
18 | if (_redirect_type === 'name') { | 17 | if (_redirect_type === 'name') { |
19 | replace({ | 18 | replace({ |
20 | name: _path, | 19 | name: _path, |
@@ -138,7 +138,6 @@ | @@ -138,7 +138,6 @@ | ||
138 | } | 138 | } |
139 | if (newFieldValue.codeTown == undefined) { | 139 | if (newFieldValue.codeTown == undefined) { |
140 | validateArray.push('prov'); | 140 | validateArray.push('prov'); |
141 | - console.log(validateArray); | ||
142 | } else { | 141 | } else { |
143 | const findExistIndex1 = validateArray.findIndex((o) => o == 'prov'); | 142 | const findExistIndex1 = validateArray.findIndex((o) => o == 'prov'); |
144 | if (findExistIndex1 !== -1) { | 143 | if (findExistIndex1 !== -1) { |
@@ -5,7 +5,8 @@ | @@ -5,7 +5,8 @@ | ||
5 | <Tabs.TabPane | 5 | <Tabs.TabPane |
6 | v-if=" | 6 | v-if=" |
7 | isWhereAdmin == 'TENANT_ADMIN' || | 7 | isWhereAdmin == 'TENANT_ADMIN' || |
8 | - (isWhereAdmin == 'SYS_ADMIN' || isWhereAdmin == 'CUSTOMER_USER') | 8 | + isWhereAdmin == 'SYS_ADMIN' || |
9 | + isWhereAdmin == 'CUSTOMER_USER' | ||
9 | " | 10 | " |
10 | key="企业信息" | 11 | key="企业信息" |
11 | tab="企业信息" | 12 | tab="企业信息" |
@@ -264,7 +264,6 @@ | @@ -264,7 +264,6 @@ | ||
264 | setProps({ | 264 | setProps({ |
265 | loading: true, | 265 | loading: true, |
266 | }); | 266 | }); |
267 | - console.log(sendTime.value); | ||
268 | let startTime = null; | 267 | let startTime = null; |
269 | let endTime = null; | 268 | let endTime = null; |
270 | if (sendTime.value.length > 0) { | 269 | if (sendTime.value.length > 0) { |
@@ -10,7 +10,8 @@ | @@ -10,7 +10,8 @@ | ||
10 | 10 | ||
11 | const alert = { | 11 | const alert = { |
12 | [PackagesCategoryEnum.MAP]: [ | 12 | [PackagesCategoryEnum.MAP]: [ |
13 | - '地图组件,需绑定两个数据源,且数据源为同一设备。第一数据源为经度,第二数据源为纬度,否则地图组件不能正常显示。', | 13 | + '1、绑定数据源为结构体时,可以自行选择结构体里的属性作为经纬度', |
14 | + '2、绑定数据源为非结构体时,第一数据源为经度,第二数据源为纬度,且数据源为同一设备,并同时上报。否则地图组件不能正常显示。', | ||
14 | ], | 15 | ], |
15 | }; | 16 | }; |
16 | 17 |
@@ -34,14 +34,6 @@ | @@ -34,14 +34,6 @@ | ||
34 | const { unit, fontColor, showDeviceName } = item.componentInfo || {}; | 34 | const { unit, fontColor, showDeviceName } = item.componentInfo || {}; |
35 | const { deviceName, deviceRename, attribute, attributeRename, deviceId, attributeName } = | 35 | const { deviceName, deviceRename, attribute, attributeRename, deviceId, attributeName } = |
36 | item; | 36 | item; |
37 | - // return { | ||
38 | - // unit: unit ?? persetUnit, | ||
39 | - // fontColor: fontColor ?? persetFontColor, | ||
40 | - // showDeviceName: showDeviceName ?? persetShowDeviceName, | ||
41 | - // attribute, | ||
42 | - // deviceName, | ||
43 | - // deviceRename, | ||
44 | - // }; | ||
45 | return { | 37 | return { |
46 | unit: unit ?? presetUnit, | 38 | unit: unit ?? presetUnit, |
47 | fontColor: fontColor ?? presetFontColor, | 39 | fontColor: fontColor ?? presetFontColor, |
@@ -58,7 +50,6 @@ | @@ -58,7 +50,6 @@ | ||
58 | }); | 50 | }); |
59 | 51 | ||
60 | const getOffset = (length: number, index: number) => { | 52 | const getOffset = (length: number, index: number) => { |
61 | - // try { | ||
62 | const offsetList = ref<any>([]); | 53 | const offsetList = ref<any>([]); |
63 | switch (length) { | 54 | switch (length) { |
64 | case 1: | 55 | case 1: |
@@ -147,7 +138,6 @@ | @@ -147,7 +138,6 @@ | ||
147 | break; | 138 | break; |
148 | } | 139 | } |
149 | return unref(offsetList); | 140 | return unref(offsetList); |
150 | - // } catch {} | ||
151 | }; | 141 | }; |
152 | 142 | ||
153 | const series = ref( | 143 | const series = ref( |
@@ -263,7 +253,6 @@ | @@ -263,7 +253,6 @@ | ||
263 | series.value.forEach((item) => { | 253 | series.value.forEach((item) => { |
264 | if (item.id === deviceId && item.attribute === attribute && value) { | 254 | if (item.id === deviceId && item.attribute === attribute && value) { |
265 | item.value = getNumberValue(value); | 255 | item.value = getNumberValue(value); |
266 | - // time.value = timespan; | ||
267 | } | 256 | } |
268 | }); | 257 | }); |
269 | }); | 258 | }); |
@@ -62,7 +62,6 @@ | @@ -62,7 +62,6 @@ | ||
62 | const options = (): EChartsOption => { | 62 | const options = (): EChartsOption => { |
63 | const { unit, fontColor, pointerColor, maxNumber, valueSize } = unref(getDesign); | 63 | const { unit, fontColor, pointerColor, maxNumber, valueSize } = unref(getDesign); |
64 | 64 | ||
65 | - // getStageColor(gradientInfo); | ||
66 | return { | 65 | return { |
67 | series: [ | 66 | series: [ |
68 | { | 67 | { |
@@ -103,14 +102,6 @@ | @@ -103,14 +102,6 @@ | ||
103 | color: pointerColor, | 102 | color: pointerColor, |
104 | }, | 103 | }, |
105 | }, | 104 | }, |
106 | - // anchor: { | ||
107 | - // show: true, | ||
108 | - // showAbove: true, | ||
109 | - // size: 10, | ||
110 | - // itemStyle: { | ||
111 | - // borderWidth: 4, | ||
112 | - // }, | ||
113 | - // }, | ||
114 | title: { | 105 | title: { |
115 | show: false, | 106 | show: false, |
116 | }, | 107 | }, |
@@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
3 | import { BasicModal, useModalInner } from '/@/components/Modal'; | 3 | import { BasicModal, useModalInner } from '/@/components/Modal'; |
4 | import { formSchema, getHistorySearchParams, SchemaFiled } from './history.config'; | 4 | import { formSchema, getHistorySearchParams, SchemaFiled } from './history.config'; |
5 | import { HistoryModalOkEmitParams } from './type'; | 5 | import { HistoryModalOkEmitParams } from './type'; |
6 | - import { ref } from 'vue'; | 6 | + import { ref, unref } from 'vue'; |
7 | import { getAllDeviceByOrg } from '/@/api/dataBoard'; | 7 | import { getAllDeviceByOrg } from '/@/api/dataBoard'; |
8 | import { getDeviceHistoryInfo } from '/@/api/alarm/position'; | 8 | import { getDeviceHistoryInfo } from '/@/api/alarm/position'; |
9 | import { DataSource } from '/@/views/visual/palette/types'; | 9 | import { DataSource } from '/@/views/visual/palette/types'; |
@@ -19,58 +19,154 @@ | @@ -19,58 +19,154 @@ | ||
19 | ], | 19 | ], |
20 | }); | 20 | }); |
21 | 21 | ||
22 | - const [registerModal, { closeModal }] = useModalInner(async (dataSource: DataSource[]) => { | ||
23 | - try { | ||
24 | - dataSource = cloneDeep(dataSource); | ||
25 | - if (dataSource.length < 2) return; | ||
26 | - dataSource = dataSource.splice(0, 2); | ||
27 | - const deviceRecord = dataSource?.at(0) || ({} as DataSource); | ||
28 | - if (!deviceRecord.organizationId) return; | ||
29 | - const deviceList = await getAllDeviceByOrg( | ||
30 | - deviceRecord.organizationId, | ||
31 | - deviceRecord.deviceProfileId | ||
32 | - ); | ||
33 | - const options = deviceList | ||
34 | - .filter((item) => item.tbDeviceId === deviceRecord.deviceId) | ||
35 | - .map((item) => ({ ...item, label: item.alias || item.name, value: item.tbDeviceId })); | ||
36 | - | ||
37 | - const attKey = dataSource.map((item) => ({ | ||
38 | - ...item, | ||
39 | - label: item.attribute, | ||
40 | - value: item.attribute, | ||
41 | - })); | ||
42 | - updateSchema([ | ||
43 | - { | ||
44 | - field: SchemaFiled.DEVICE_ID, | ||
45 | - componentProps: { | ||
46 | - options, | ||
47 | - }, | 22 | + const loading = ref(false); |
23 | + const getDesign = ref(); | ||
24 | + | ||
25 | + const getTwoMap = async (dataSource) => { | ||
26 | + if (dataSource.length < 2) return; | ||
27 | + dataSource = dataSource.splice(0, 2); | ||
28 | + const deviceRecord = dataSource?.at(0) || ({} as DataSource); | ||
29 | + | ||
30 | + if (!deviceRecord.organizationId) return; | ||
31 | + const deviceList = await getAllDeviceByOrg( | ||
32 | + deviceRecord.organizationId, | ||
33 | + deviceRecord.deviceProfileId | ||
34 | + ); | ||
35 | + const options = deviceList | ||
36 | + .filter((item) => item.tbDeviceId === deviceRecord.deviceId) | ||
37 | + .map((item) => ({ ...item, label: item.alias || item.name, value: item.tbDeviceId })); | ||
38 | + | ||
39 | + const attKey = dataSource.map((item) => ({ | ||
40 | + ...item, | ||
41 | + label: item.attribute, | ||
42 | + value: item.attribute, | ||
43 | + })); | ||
44 | + | ||
45 | + updateSchemaMap(options, attKey, deviceRecord); | ||
46 | + }; | ||
47 | + | ||
48 | + const getOneMap = async (dataSource) => { | ||
49 | + const deviceRecord = dataSource?.[0]; | ||
50 | + if (!deviceRecord.organizationId) return; | ||
51 | + const deviceList = await getAllDeviceByOrg( | ||
52 | + deviceRecord.organizationId, | ||
53 | + deviceRecord.deviceProfileId | ||
54 | + ); | ||
55 | + const options = deviceList | ||
56 | + .filter((item) => item.tbDeviceId === deviceRecord.deviceId) | ||
57 | + .map((item) => ({ ...item, label: item.alias || item.name, value: item.tbDeviceId })); | ||
58 | + | ||
59 | + const attKey = dataSource?.map((item) => ({ | ||
60 | + ...item, | ||
61 | + label: item.attributeName, | ||
62 | + value: item.attribute, | ||
63 | + })); | ||
64 | + updateSchemaMap(options, attKey, deviceRecord); | ||
65 | + }; | ||
66 | + | ||
67 | + const updateSchemaMap = (options, attKey, deviceRecord) => { | ||
68 | + updateSchema([ | ||
69 | + { | ||
70 | + field: SchemaFiled.DEVICE_ID, | ||
71 | + componentProps: { | ||
72 | + options, | ||
48 | }, | 73 | }, |
49 | - { | ||
50 | - field: SchemaFiled.KEYS, | ||
51 | - component: 'Select', | ||
52 | - defaultValue: attKey.map((item) => item.value), | ||
53 | - componentProps: { | ||
54 | - options: attKey, | ||
55 | - mode: 'multiple', | ||
56 | - disabled: true, | ||
57 | - }, | 74 | + }, |
75 | + { | ||
76 | + field: SchemaFiled.KEYS, | ||
77 | + component: 'Select', | ||
78 | + defaultValue: attKey.map((item) => item.value), | ||
79 | + componentProps: { | ||
80 | + options: attKey, | ||
81 | + mode: 'multiple', | ||
82 | + disabled: true, | ||
58 | }, | 83 | }, |
59 | - ]); | 84 | + }, |
85 | + ]); | ||
60 | 86 | ||
61 | - setFieldsValue({ | ||
62 | - [SchemaFiled.DEVICE_ID]: deviceRecord.deviceId, | ||
63 | - [SchemaFiled.KEYS]: attKey.map((item) => item.value), | ||
64 | - }); | 87 | + setFieldsValue({ |
88 | + [SchemaFiled.DEVICE_ID]: deviceRecord.deviceId, | ||
89 | + [SchemaFiled.KEYS]: attKey.map((item) => item.value), | ||
90 | + }); | ||
91 | + }; | ||
92 | + | ||
93 | + const [registerModal, { closeModal }] = useModalInner(async (dataSource: DataSource[]) => { | ||
94 | + try { | ||
95 | + getDesign.value = dataSource; | ||
96 | + dataSource = cloneDeep(dataSource); | ||
97 | + //判断选择是不是结构体 | ||
98 | + if (dataSource.length == 1 && dataSource?.[0]?.lal) { | ||
99 | + getOneMap(dataSource); | ||
100 | + return; | ||
101 | + } | ||
102 | + getTwoMap(dataSource); | ||
65 | } catch (error) { | 103 | } catch (error) { |
66 | throw error; | 104 | throw error; |
67 | } | 105 | } |
68 | }); | 106 | }); |
69 | 107 | ||
108 | + const getMultipleDataSource = async (res) => { | ||
109 | + let timespanList = Object.keys(res).reduce((prev, next) => { | ||
110 | + const ts = res[next].map((item) => item.ts); | ||
111 | + return [...prev, ...ts]; | ||
112 | + }, [] as number[]); | ||
113 | + timespanList = [...new Set(timespanList)]; | ||
114 | + | ||
115 | + const track: Record<'lng' | 'lat', number>[] = []; | ||
116 | + const keys = Object.keys(res); | ||
117 | + | ||
118 | + for (const ts of timespanList) { | ||
119 | + const list: { ts: number; value: number }[] = []; | ||
120 | + for (const key of keys) { | ||
121 | + const record = res[key].find((item) => ts === item.ts); | ||
122 | + if (!validEffective(record?.value)) { | ||
123 | + continue; | ||
124 | + } | ||
125 | + list.push(record as any); | ||
126 | + } | ||
127 | + | ||
128 | + if (list.length === 2 && list.every(Boolean)) { | ||
129 | + const lng = list.at(0)?.value; | ||
130 | + const lat = list.at(1)?.value; | ||
131 | + if (lng && lat) track.push({ lng, lat }); | ||
132 | + } | ||
133 | + } | ||
134 | + return track; | ||
135 | + }; | ||
136 | + | ||
137 | + // 单数据源选择结构体 | ||
138 | + const getSingleDataSource = async (res) => { | ||
139 | + const [keys] = Object.keys(res); | ||
140 | + const track: Record<'lng' | 'lat', number>[] = []; | ||
141 | + const dataSource = res[keys]?.map((item) => { | ||
142 | + return { | ||
143 | + value: item.value ? JSON.parse(item.value) : {}, | ||
144 | + }; | ||
145 | + }); | ||
146 | + const list: { value: number }[] = []; | ||
147 | + dataSource?.forEach((item) => { | ||
148 | + if ( | ||
149 | + //判断结构体得值是不是数字 | ||
150 | + Object.values(item.value).every((item1) => { | ||
151 | + return validEffective(item1 as any); | ||
152 | + }) | ||
153 | + ) { | ||
154 | + list.push(item.value); | ||
155 | + } | ||
156 | + }); | ||
157 | + const { latitude, longitude } = unref(getDesign)?.[0]; //获取选择的经纬度选项 | ||
158 | + | ||
159 | + list.forEach((item) => { | ||
160 | + const lng = item[longitude]; | ||
161 | + const lat = item[latitude]; | ||
162 | + if (lng && lat) track.push({ lng, lat }); | ||
163 | + }); | ||
164 | + return track; | ||
165 | + }; | ||
166 | + | ||
70 | const validEffective = (value = '') => { | 167 | const validEffective = (value = '') => { |
71 | return !!(value && !isNaN(value as unknown as number)); | 168 | return !!(value && !isNaN(value as unknown as number)); |
72 | }; | 169 | }; |
73 | - const loading = ref(false); | ||
74 | const handleOk = async () => { | 170 | const handleOk = async () => { |
75 | try { | 171 | try { |
76 | await validate(); | 172 | await validate(); |
@@ -84,33 +180,9 @@ | @@ -84,33 +180,9 @@ | ||
84 | ...value, | 180 | ...value, |
85 | [SchemaFiled.KEYS]: value[SchemaFiled.KEYS].join(','), | 181 | [SchemaFiled.KEYS]: value[SchemaFiled.KEYS].join(','), |
86 | }); | 182 | }); |
183 | + const ifSingle = unref(getDesign)?.length === 1 && unref(getDesign)?.[0]?.lal; | ||
87 | 184 | ||
88 | - let timespanList = Object.keys(res).reduce((prev, next) => { | ||
89 | - const ts = res[next].map((item) => item.ts); | ||
90 | - return [...prev, ...ts]; | ||
91 | - }, [] as number[]); | ||
92 | - timespanList = [...new Set(timespanList)]; | ||
93 | - | ||
94 | - const track: Record<'lng' | 'lat', number>[] = []; | ||
95 | - const keys = Object.keys(res); | ||
96 | - | ||
97 | - for (const ts of timespanList) { | ||
98 | - const list: { ts: number; value: number }[] = []; | ||
99 | - for (const key of keys) { | ||
100 | - const record = res[key].find((item) => ts === item.ts); | ||
101 | - if (!validEffective(record?.value)) { | ||
102 | - continue; | ||
103 | - } | ||
104 | - list.push(record as any); | ||
105 | - } | ||
106 | - | ||
107 | - if (list.length === 2 && list.every(Boolean)) { | ||
108 | - const lng = list.at(0)?.value; | ||
109 | - const lat = list.at(1)?.value; | ||
110 | - if (lng && lat) track.push({ lng, lat }); | ||
111 | - } | ||
112 | - } | ||
113 | - | 185 | + const track = ifSingle ? await getSingleDataSource(res) : await getMultipleDataSource(res); |
114 | emit('ok', { track, value } as HistoryModalOkEmitParams); | 186 | emit('ok', { track, value } as HistoryModalOkEmitParams); |
115 | closeModal(); | 187 | closeModal(); |
116 | } catch (error) { | 188 | } catch (error) { |
@@ -24,6 +24,14 @@ | @@ -24,6 +24,14 @@ | ||
24 | return props.config.option.dataSource?.at(0)?.deviceId; | 24 | return props.config.option.dataSource?.at(0)?.deviceId; |
25 | }); | 25 | }); |
26 | 26 | ||
27 | + const getDesign = computed(() => { | ||
28 | + const { option } = props.config; | ||
29 | + const { dataSource } = option || {}; | ||
30 | + return { | ||
31 | + dataSource: dataSource, | ||
32 | + }; | ||
33 | + }); | ||
34 | + | ||
27 | /** | 35 | /** |
28 | * @description 经度key | 36 | * @description 经度key |
29 | */ | 37 | */ |
@@ -42,7 +50,7 @@ | @@ -42,7 +50,7 @@ | ||
42 | return !!(value && !isNaN(value as unknown as number)); | 50 | return !!(value && !isNaN(value as unknown as number)); |
43 | }; | 51 | }; |
44 | 52 | ||
45 | - const updateFn: MultipleDataFetchUpdateFn = (message, deviceId) => { | 53 | + const getTwoMap = (message, deviceId) => { |
46 | if (unref(getDeviceId) !== deviceId) return; | 54 | if (unref(getDeviceId) !== deviceId) return; |
47 | 55 | ||
48 | const { data = {} } = message; | 56 | const { data = {} } = message; |
@@ -51,7 +59,7 @@ | @@ -51,7 +59,7 @@ | ||
51 | 59 | ||
52 | const lngData = bindMessage[unref(getLngKey)] || []; | 60 | const lngData = bindMessage[unref(getLngKey)] || []; |
53 | const [lngLatest] = lngData; | 61 | const [lngLatest] = lngData; |
54 | - const [, lng] = lngLatest; | 62 | + const [, lng] = lngLatest || []; |
55 | 63 | ||
56 | const latData = bindMessage[unref(getLatKey)] || []; | 64 | const latData = bindMessage[unref(getLatKey)] || []; |
57 | const [latLatest] = latData; | 65 | const [latLatest] = latData; |
@@ -62,6 +70,34 @@ | @@ -62,6 +70,34 @@ | ||
62 | } | 70 | } |
63 | }; | 71 | }; |
64 | 72 | ||
73 | + const getOneMap = (message, deviceId) => { | ||
74 | + if (unref(getDeviceId) !== deviceId) return; | ||
75 | + | ||
76 | + const { longitude, latitude, attribute } = unref(getDesign)?.dataSource?.[0] || {}; | ||
77 | + const { data } = message || {}; | ||
78 | + const bindMessage = data[deviceId]; | ||
79 | + const [, values] = attribute && bindMessage?.[attribute][0]; | ||
80 | + | ||
81 | + const mapValues = values ? JSON.parse(values) : {}; | ||
82 | + const lng = longitude && mapValues[longitude]; | ||
83 | + const lat = latitude && mapValues[latitude]; | ||
84 | + | ||
85 | + if (validEffective(lng) && validEffective(lat)) { | ||
86 | + drawLine({ lng: Number(lng), lat: Number(lat) }); | ||
87 | + } | ||
88 | + }; | ||
89 | + | ||
90 | + const updateFn: MultipleDataFetchUpdateFn = (message, deviceId) => { | ||
91 | + const { lal } = unref(getDesign)?.dataSource?.[0] || {}; | ||
92 | + // 属性选择结构体类型时 | ||
93 | + if (lal && unref(getDesign)?.dataSource?.length == 1) { | ||
94 | + getOneMap(message, deviceId); | ||
95 | + return; | ||
96 | + } | ||
97 | + // 选择两个属性时 | ||
98 | + getTwoMap(message, deviceId); | ||
99 | + }; | ||
100 | + | ||
65 | useMultipleDataFetch(props, updateFn); | 101 | useMultipleDataFetch(props, updateFn); |
66 | 102 | ||
67 | const { drawLine } = useMapTrackPlayBack(mapInstance); | 103 | const { drawLine } = useMapTrackPlayBack(mapInstance); |
@@ -100,11 +136,3 @@ | @@ -100,11 +136,3 @@ | ||
100 | <div v-show="!loading" ref="wrapRef" :id="wrapId" class="w-full h-full no-drag"> </div> | 136 | <div v-show="!loading" ref="wrapRef" :id="wrapId" class="w-full h-full no-drag"> </div> |
101 | </main> | 137 | </main> |
102 | </template> | 138 | </template> |
103 | - | ||
104 | -<style lang="less" scoped> | ||
105 | - // .map-spin-wrapper { | ||
106 | - // :deep(.ant-spin-container) { | ||
107 | - // @apply justify-center items-center p-2 w-full h-full; | ||
108 | - // } | ||
109 | - // } | ||
110 | -</style> |
@@ -247,7 +247,6 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -247,7 +247,6 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
247 | }); | 247 | }); |
248 | }, | 248 | }, |
249 | placeholder: '请选择设备', | 249 | placeholder: '请选择设备', |
250 | - getPopupContainer: () => document.body, | ||
251 | ...createPickerSearch(), | 250 | ...createPickerSearch(), |
252 | }; | 251 | }; |
253 | }, | 252 | }, |
@@ -382,11 +381,18 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -382,11 +381,18 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
382 | return []; | 381 | return []; |
383 | }, | 382 | }, |
384 | placeholder: '请选择属性', | 383 | placeholder: '请选择属性', |
385 | - getPopupContainer: () => document.body, | ||
386 | onChange(value: string, option: Record<'label' | 'value' | any, string>) { | 384 | onChange(value: string, option: Record<'label' | 'value' | any, string>) { |
385 | + const { detail }: any = option || {}; | ||
387 | setFieldsValue({ | 386 | setFieldsValue({ |
388 | [DataSourceField.ATTRIBUTE_NAME]: value ? option.label : null, | 387 | [DataSourceField.ATTRIBUTE_NAME]: value ? option.label : null, |
389 | [DataSourceField.EXTENSION_DESC]: value ? JSON.stringify(option.extensionDesc) : '', | 388 | [DataSourceField.EXTENSION_DESC]: value ? JSON.stringify(option.extensionDesc) : '', |
389 | + // 地图组件结构体 | ||
390 | + lal: | ||
391 | + category === 'MAP' && value && detail?.dataType.type === 'STRUCT' | ||
392 | + ? JSON.stringify(detail?.dataType.specs) | ||
393 | + : null, | ||
394 | + latitude: null, | ||
395 | + longitude: null, | ||
390 | }); | 396 | }); |
391 | }, | 397 | }, |
392 | ...createPickerSearch(), | 398 | ...createPickerSearch(), |
@@ -394,6 +400,46 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -394,6 +400,46 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
394 | }, | 400 | }, |
395 | }, | 401 | }, |
396 | { | 402 | { |
403 | + field: 'lal', | ||
404 | + label: '经纬度存储的值', | ||
405 | + component: 'Input', | ||
406 | + show: false, | ||
407 | + }, | ||
408 | + { | ||
409 | + field: 'longitude', | ||
410 | + label: '经度', | ||
411 | + colProps: { span: 8 }, | ||
412 | + component: 'Select', | ||
413 | + required: true, | ||
414 | + ifShow: ({ model }) => category === 'MAP' && model.lal, | ||
415 | + componentProps({ formModel }) { | ||
416 | + const { lal } = formModel || {}; | ||
417 | + return { | ||
418 | + placeholder: '请选择经度', | ||
419 | + options: lal | ||
420 | + ? JSON.parse(lal)?.map((item) => ({ label: item.functionName, value: item.identifier })) | ||
421 | + : [], | ||
422 | + }; | ||
423 | + }, | ||
424 | + }, | ||
425 | + { | ||
426 | + field: 'latitude', | ||
427 | + label: '纬度', | ||
428 | + colProps: { span: 8 }, | ||
429 | + required: true, | ||
430 | + component: 'Select', | ||
431 | + ifShow: ({ model }) => category === 'MAP' && model.lal, | ||
432 | + componentProps({ formModel }) { | ||
433 | + const { lal } = formModel || {}; | ||
434 | + return { | ||
435 | + placeholder: '请选择纬度', | ||
436 | + options: lal | ||
437 | + ? JSON.parse(lal)?.map((item) => ({ label: item.functionName, value: item.identifier })) | ||
438 | + : [], | ||
439 | + }; | ||
440 | + }, | ||
441 | + }, | ||
442 | + { | ||
397 | field: DataSourceField.EXTENSION_DESC, | 443 | field: DataSourceField.EXTENSION_DESC, |
398 | component: 'Input', | 444 | component: 'Input', |
399 | show: false, | 445 | show: false, |
1 | -import { ReceiveTsSubCmdsGroupMessageType } from '../index.type'; | 1 | +import { ReceiveTsSubCmdsGroupMessageType } from './socket/useSocket.type'; |
2 | 2 | ||
3 | export const useReceiveMessage = () => { | 3 | export const useReceiveMessage = () => { |
4 | const forEachGroupMessage = ( | 4 | const forEachGroupMessage = ( |
src/views/visual/packages/template/config.ts
deleted
100644 → 0
1 | -import cloneDeep from 'lodash-es/cloneDeep'; | ||
2 | -import { ComponentConfig } from '.'; | ||
3 | -import { | ||
4 | - ConfigType, | ||
5 | - CreateComponentType, | ||
6 | - PublicComponentOptions, | ||
7 | - PublicPresetOptions, | ||
8 | -} from '/@/views/visual/packages/index.type'; | ||
9 | -import { PublicConfigClass, componentInitConfig } from '/@/views/visual/packages/publicConfig'; | ||
10 | -import { ComponentConfigFieldEnum } from '/@/views/visual/packages/enum'; | ||
11 | - | ||
12 | -export const option: PublicPresetOptions = { | ||
13 | - [ComponentConfigFieldEnum.FONT_COLOR]: '#', | ||
14 | - [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, | ||
15 | -}; | ||
16 | - | ||
17 | -export default class Config extends PublicConfigClass implements CreateComponentType { | ||
18 | - public key: string = ComponentConfig.key; | ||
19 | - | ||
20 | - public attr = { ...componentInitConfig }; | ||
21 | - | ||
22 | - public componentConfig: ConfigType = cloneDeep(ComponentConfig); | ||
23 | - | ||
24 | - public persetOption = cloneDeep(option); | ||
25 | - | ||
26 | - public option: PublicComponentOptions; | ||
27 | - | ||
28 | - constructor(option: PublicComponentOptions) { | ||
29 | - super(); | ||
30 | - this.option = { ...option }; | ||
31 | - } | ||
32 | -} |
src/views/visual/packages/template/config.vue
deleted
100644 → 0
1 | -<script lang="ts" setup> | ||
2 | - import { ComponentConfigFieldEnum } from '/@/views/visual/packages/enum'; | ||
3 | - import { useForm, BasicForm } from '/@/components/Form'; | ||
4 | - import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type'; | ||
5 | - | ||
6 | - const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({ | ||
7 | - schemas: [ | ||
8 | - { | ||
9 | - field: ComponentConfigFieldEnum.FONT_COLOR, | ||
10 | - label: '数值字体颜色', | ||
11 | - component: 'ColorPicker', | ||
12 | - changeEvent: 'update:value', | ||
13 | - componentProps: { | ||
14 | - defaultValue: '#FD7347', | ||
15 | - }, | ||
16 | - }, | ||
17 | - { | ||
18 | - field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME, | ||
19 | - label: '显示设备名称', | ||
20 | - component: 'Checkbox', | ||
21 | - }, | ||
22 | - ], | ||
23 | - showActionButtonGroup: false, | ||
24 | - labelWidth: 120, | ||
25 | - baseColProps: { | ||
26 | - span: 12, | ||
27 | - }, | ||
28 | - }); | ||
29 | - | ||
30 | - const getFormValues = () => { | ||
31 | - return getFieldsValue(); | ||
32 | - }; | ||
33 | - | ||
34 | - const setFormValues = (data: Recordable) => { | ||
35 | - return setFieldsValue(data); | ||
36 | - }; | ||
37 | - | ||
38 | - defineExpose({ | ||
39 | - getFormValues, | ||
40 | - setFormValues, | ||
41 | - resetFormValues: resetFields, | ||
42 | - } as PublicFormInstaceType); | ||
43 | -</script> | ||
44 | - | ||
45 | -<template> | ||
46 | - <BasicForm @register="register" /> | ||
47 | -</template> |
src/views/visual/packages/template/datasource.vue
deleted
100644 → 0
1 | -<script lang="ts" setup> | ||
2 | - import { CreateComponentType } from '/@/views/visual/packages/index.type'; | ||
3 | - import { BasicForm, useForm } from '/@/components/Form'; | ||
4 | - import { | ||
5 | - PublicComponentValueType, | ||
6 | - PublicFormInstaceType, | ||
7 | - } from '/@/views/visual/dataSourceBindPanel/index.type'; | ||
8 | - import { commonDataSourceSchemas } from '../config/common.config'; | ||
9 | - | ||
10 | - defineProps<{ | ||
11 | - values: PublicComponentValueType; | ||
12 | - componentConfig: CreateComponentType; | ||
13 | - }>(); | ||
14 | - | ||
15 | - const [register, { getFieldsValue, setFieldsValue, validate, resetFields }] = useForm({ | ||
16 | - labelWidth: 0, | ||
17 | - showActionButtonGroup: false, | ||
18 | - layout: 'horizontal', | ||
19 | - labelCol: { span: 0 }, | ||
20 | - schemas: commonDataSourceSchemas(), | ||
21 | - }); | ||
22 | - | ||
23 | - const getFormValues = () => { | ||
24 | - return getFieldsValue(); | ||
25 | - }; | ||
26 | - | ||
27 | - const setFormValues = (record: Recordable) => { | ||
28 | - return setFieldsValue(record); | ||
29 | - }; | ||
30 | - | ||
31 | - defineExpose({ | ||
32 | - getFormValues, | ||
33 | - setFormValues, | ||
34 | - validate, | ||
35 | - resetFormValues: resetFields, | ||
36 | - } as PublicFormInstaceType); | ||
37 | -</script> | ||
38 | - | ||
39 | -<template> | ||
40 | - <BasicForm @register="register" /> | ||
41 | -</template> |
src/views/visual/packages/template/index.ts
deleted
100644 → 0
1 | -import { useComponentKeys } from '/@/views/visual/packages/hook/useComponentKeys'; | ||
2 | -import { ConfigType, PackagesCategoryEnum } from '/@/views/visual/packages/index.type'; | ||
3 | - | ||
4 | -const componentKeys = useComponentKeys('componentKeys'); | ||
5 | - | ||
6 | -export const ComponentConfig: ConfigType = { | ||
7 | - ...componentKeys, | ||
8 | - title: '组件名', | ||
9 | - package: PackagesCategoryEnum.TEXT, | ||
10 | -}; |
src/views/visual/packages/template/index.vue
deleted
100644 → 0
1 | -<script lang="ts" setup> | ||
2 | - import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; | ||
3 | - import { option } from './config'; | ||
4 | - import { useDataFetch } from '../hook/socket/useSocket'; | ||
5 | - import { DataFetchUpdateFn } from '../hook/socket/useSocket.type'; | ||
6 | - | ||
7 | - const props = defineProps<{ | ||
8 | - config: ComponentPropsConfigType<typeof option>; | ||
9 | - }>(); | ||
10 | - | ||
11 | - const updateFn: DataFetchUpdateFn = (_message) => {}; | ||
12 | - | ||
13 | - useDataFetch(props, updateFn); | ||
14 | -</script> | ||
15 | - | ||
16 | -<template> | ||
17 | - <main class="w-full h-full flex flex-col justify-center items-center"> </main> | ||
18 | -</template> |
@@ -150,7 +150,6 @@ | @@ -150,7 +150,6 @@ | ||
150 | getIsSharePage, | 150 | getIsSharePage, |
151 | (value) => { | 151 | (value) => { |
152 | if (value) { | 152 | if (value) { |
153 | - console.log(unref(getDarkMode)); | ||
154 | const root = document.querySelector('#app'); | 153 | const root = document.querySelector('#app'); |
155 | (root as HTMLDivElement).style.backgroundColor = | 154 | (root as HTMLDivElement).style.backgroundColor = |
156 | unref(getDarkMode) === ThemeEnum.LIGHT ? '#F5F5F5' : '#1b1b1b'; | 155 | unref(getDarkMode) === ThemeEnum.LIGHT ? '#F5F5F5' : '#1b1b1b'; |
@@ -29,6 +29,9 @@ export interface DataSource { | @@ -29,6 +29,9 @@ export interface DataSource { | ||
29 | customCommand: CustomCommand; | 29 | customCommand: CustomCommand; |
30 | videoConfig?: VideoConfigType; | 30 | videoConfig?: VideoConfigType; |
31 | [key: string]: any; | 31 | [key: string]: any; |
32 | + lal?: string; | ||
33 | + latitude?: string | number; | ||
34 | + longitude?: string | number; | ||
32 | } | 35 | } |
33 | 36 | ||
34 | export interface ExtraDataSource extends DataSource, PublicComponentOptions { | 37 | export interface ExtraDataSource extends DataSource, PublicComponentOptions { |
@@ -32,7 +32,6 @@ app.ws.use( | @@ -32,7 +32,6 @@ app.ws.use( | ||
32 | }); | 32 | }); |
33 | ctx.websocket.send(data); | 33 | ctx.websocket.send(data); |
34 | } | 34 | } |
35 | - console.log(message); | ||
36 | }); | 35 | }); |
37 | }) | 36 | }) |
38 | ); | 37 | ); |
@@ -59,5 +58,6 @@ app.use(router.allowedMethods()); | @@ -59,5 +58,6 @@ app.use(router.allowedMethods()); | ||
59 | app.use(koaStatic(path.join(__dirname))); | 58 | app.use(koaStatic(path.join(__dirname))); |
60 | 59 | ||
61 | app.listen(PORT, () => { | 60 | app.listen(PORT, () => { |
61 | + // eslint-disable-next-line no-console | ||
62 | console.log(`Application started successfully: http://localhost:${PORT}`); | 62 | console.log(`Application started successfully: http://localhost:${PORT}`); |
63 | }); | 63 | }); |