Commit 31f0af438a5850711395b22d42c120dc2a8fdf70

Authored by fengwotao
2 parents 8139831e 08551861

Merge branch 'main_dev' into local_branch_devbyft

Showing 78 changed files with 406 additions and 441 deletions
... ... @@ -25,7 +25,7 @@ module.exports = defineConfig({
25 25 'plugin:jest/recommended',
26 26 ],
27 27 rules: {
28   - 'no-console': 'error',
  28 + 'no-console': ['error', { allow: ['warn', 'error'] }],
29 29 'vue/script-setup-uses-vars': 'error',
30 30 '@typescript-eslint/ban-ts-ignore': 'off',
31 31 '@typescript-eslint/explicit-function-return-type': 'off',
... ...
... ... @@ -65,3 +65,19 @@ export interface ImportModelOfMatterType {
65 65 tkDeviceProfileId?: string;
66 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 2 import {
3 3 GetModelTslParams,
4 4 ImportModelOfMatterType,
  5 + ModelOfMatterItemRecordType,
5 6 ModelOfMatterParams,
6 7 } from './model/modelOfMatterModel';
7 8 import { defHttp } from '/@/utils/http/axios';
... ... @@ -36,7 +37,7 @@ export const getModelList = (
36 37 id?: string;
37 38 }
38 39 ) => {
39   - return defHttp.get({
  40 + return defHttp.get<ModelOfMatterItemRecordType[]>({
40 41 url: `${ModelOfMatter.LIST}`,
41 42 params,
42 43 });
... ...
... ... @@ -14,7 +14,6 @@ export function saveMenuApi(
14 14 update = false,
15 15 mode: ErrorMessageMode = 'modal'
16 16 ) {
17   - console.log(params);
18 17 if (!update) {
19 18 return defHttp.post<MenuOperationApiResult>(
20 19 {
... ...
... ... @@ -48,13 +48,21 @@
48 48 <template #content>
49 49 <section class="flex flex-wrap w-36">
50 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 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 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 67 </td>
60 68 </tr>
... ...
... ... @@ -77,7 +77,6 @@
77 77 try {
78 78 const data = e.target && e.target.result;
79 79 const workbook = XLSX.read(data, { type: 'array' });
80   - // console.log(workbook);
81 80 /* DO SOMETHING WITH workbook HERE */
82 81 const excelData = getExcelData(workbook);
83 82 emit('success', excelData);
... ...
... ... @@ -90,7 +90,7 @@
90 90 () => {
91 91 !unref(isFirstLoad) && fetch();
92 92 },
93   - { deep: true },
  93 + { deep: true }
94 94 );
95 95
96 96 async function fetch() {
... ... @@ -110,6 +110,7 @@
110 110 }
111 111 emitChange();
112 112 } catch (error) {
  113 + // eslint-disable-next-line no-console
113 114 console.warn(error);
114 115 } finally {
115 116 loading.value = false;
... ...
... ... @@ -156,6 +156,7 @@
156 156 }
157 157 emitChange();
158 158 } catch (error) {
  159 + // eslint-disable-next-line no-console
159 160 console.warn(error);
160 161 } finally {
161 162 loading.value = false;
... ...
... ... @@ -113,7 +113,7 @@
113 113 const { TabPane } = Tabs;
114 114 const { prefixCls } = useDesign('easy-cron-inner');
115 115 provide('prefixCls', prefixCls);
116   - const emit = defineEmits([...cronEmits]);
  116 + const emit = defineEmits(cronEmits);
117 117 const props = defineProps({ ...cronProps });
118 118 const activeKey = ref(props.hideSecond ? 'minute' : 'second');
119 119 const second = ref('*');
... ... @@ -236,7 +236,7 @@
236 236 if (/^[0-7]$/.test(week)) {
237 237 return convert(week);
238 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 240 if (separator === '/') {
241 241 return convert(before) + separator + after;
242 242 } else {
... ...
... ... @@ -23,8 +23,8 @@
23 23
24 24 export default defineComponent({
25 25 name: 'EasyCronModal',
26   - inheritAttrs: false,
27 26 components: { BasicModal, EasyCron, Button },
  27 + inheritAttrs: false,
28 28 setup() {
29 29 const attrs = useAttrs();
30 30 const [registerModal, { closeModal }] = useModalInner();
... ...
... ... @@ -45,7 +45,7 @@ export function useTabSetup(props, context, options) {
45 45
46 46 // 根据不同的类型计算出的value
47 47 const computeValue = computed(() => {
48   - let valueArray: any[] = [];
  48 + const valueArray: any[] = [];
49 49 switch (type.value) {
50 50 case TypeEnum.unset:
51 51 valueArray.push('?');
... ... @@ -79,7 +79,7 @@ export function useTabSetup(props, context, options) {
79 79 });
80 80 // 指定值范围区间,介于最小值和最大值之间
81 81 const specifyRange = computed(() => {
82   - let range: number[] = [];
  82 + const range: number[] = [];
83 83 if (maxValue.value != null) {
84 84 for (let i = minValue.value; i <= maxValue.value; i++) {
85 85 range.push(i);
... ...
... ... @@ -159,7 +159,7 @@
159 159 }
160 160 emit('height-change', unref(realHeightRef));
161 161 } catch (error) {
162   - console.log(error);
  162 + console.error(error);
163 163 }
164 164 }
165 165
... ...
... ... @@ -207,7 +207,6 @@
207 207 });
208 208
209 209 function handleSearch(searchValue: string) {
210   - console.log('searchValue', searchValue);
211 210 if (searchValue !== searchText.value) searchText.value = searchValue;
212 211 emit('update:searchValue', searchValue);
213 212 if (!searchValue) {
... ...
... ... @@ -202,7 +202,6 @@
202 202 error: null,
203 203 };
204 204 } catch (e) {
205   - console.log(e);
206 205 item.status = UploadResultStatus.ERROR;
207 206 return {
208 207 success: false,
... ...
... ... @@ -16,8 +16,6 @@
16 16 import { computed, defineComponent, unref, ref } from 'vue';
17 17 import { Layout } from 'ant-design-vue';
18 18
19   - import { GithubFilled } from '@ant-design/icons-vue';
20   -
21 19 import { DOC_URL, GITHUB_URL, SITE_URL } from '/@/settings/siteSetting';
22 20 import { openWindow } from '/@/utils';
23 21
... ... @@ -29,7 +27,7 @@
29 27
30 28 export default defineComponent({
31 29 name: 'LayoutFooter',
32   - components: { Footer: Layout.Footer, GithubFilled },
  30 + components: { Footer: Layout.Footer },
33 31 setup() {
34 32 const { t } = useI18n();
35 33 const { getShowFooter } = useRootSetting();
... ...
... ... @@ -148,7 +148,6 @@
148 148
149 149 function renderMenu() {
150 150 const { menus, ...menuProps } = unref(getCommonProps);
151   - // console.log(menus);
152 151 if (!menus || !menus.length) return null;
153 152 return !props.isHorizontal ? (
154 153 <SimpleMenu {...menuProps} isSplitMenu={unref(getSplit)} items={menus} />
... ...
... ... @@ -100,7 +100,7 @@ export default defineComponent({
100 100 <>
101 101 <TypePicker
102 102 menuTypeList={menuTypeList}
103   - handler={(item: typeof menuTypeList[0]) => {
  103 + handler={(item: (typeof menuTypeList)[0]) => {
104 104 baseHandler(HandlerEnum.CHANGE_LAYOUT, {
105 105 mode: item.mode,
106 106 type: item.type,
... ...
... ... @@ -47,7 +47,7 @@ export function initAppConfigStore() {
47 47 grayMode && updateGrayMode(grayMode);
48 48 colorWeak && updateColorWeak(colorWeak);
49 49 } catch (error) {
50   - console.log(error);
  50 + console.error(error);
51 51 }
52 52 appStore.setProjectConfig(projCfg);
53 53
... ...
... ... @@ -4,7 +4,6 @@ import { defineStore } from 'pinia';
4 4
5 5 import { LOCK_INFO_KEY } from '/@/enums/cacheEnum';
6 6 import { Persistent } from '/@/utils/cache/persistent';
7   -import { useUserStore } from './user';
8 7
9 8 interface LockState {
10 9 lockInfo: Nullable<LockInfo>;
... ...
... ... @@ -111,7 +111,6 @@ export const usePermissionStore = defineStore({
111 111 * 否则不是超级管理员-获取对应角色的权限列表
112 112 */
113 113 const codeList = await getPermCode();
114   - // console.log('codeList', codeList);
115 114 this.setPermCodeList(codeList);
116 115 /**
117 116 * 如果是超级管理员则获取对应权限列表
... ...
... ... @@ -234,7 +234,6 @@ export const useUserStore = defineStore({
234 234 // try {
235 235 // await doLogout();
236 236 // } catch {
237   - // console.log('注销Token失败');
238 237 // }
239 238 // this.resetState();
240 239 // setAuthCache(JWT_TOKEN_KEY, undefined);
... ...
... ... @@ -85,9 +85,7 @@
85 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 86 if (reg.test(formData.mobile)) {
87 87 const sendRes = await passwordResetCode(formData.mobile);
88   - console.log(sendRes);
89 88 if (sendRes === '') {
90   - console.log('发送成功了');
91 89 return true;
92 90 }
93 91 return false;
... ...
... ... @@ -99,6 +99,5 @@
99 99 async function handleRegister() {
100 100 const data = await validForm();
101 101 if (!data) return;
102   - console.log(data);
103 102 }
104 103 </script>
... ...
... ... @@ -27,7 +27,6 @@
27 27 onMounted(() => {
28 28 // 记录当前的UserId
29 29 userId.value = userStore.getUserInfo?.userId;
30   - console.log('Mounted', userStore.getUserInfo);
31 30 });
32 31
33 32 onBeforeUnmount(() => {
... ...
... ... @@ -11,8 +11,7 @@
11 11 */
12 12 export function simpleDebounce(fn, delay = 100) {
13 13 let timer: any | null = null;
14   - return function () {
15   - let args = arguments;
  14 + return function (...args) {
16 15 if (timer) {
17 16 clearTimeout(timer);
18 17 }
... ... @@ -61,4 +60,3 @@ export function dateFormat(date, block) {
61 60 });
62 61 return format;
63 62 }
64   -
... ...
... ... @@ -36,7 +36,6 @@ export function checkStatus(
36 36 }
37 37 break;
38 38 case 403:
39   - // console.log('403', errMessage);
40 39 // errMessage = t('sys.api.errMsg403');
41 40 errMessage = errMessage;
42 41 break;
... ...
... ... @@ -8,7 +8,6 @@ export function listToTree(lists: getMenuListResultModel): getMenuListResultMode
8 8 lists.forEach((goods) => {
9 9 goods['menuName'] = t(goods.meta.title); // 为goods添加属性menuName
10 10
11   - // console.log(goods.children?.length);
12 11 if (goods.children?.length) {
13 12 listToTree(goods.children);
14 13 // goods.children.forEach((goodChildren) => {
... ...
... ... @@ -102,8 +102,7 @@
102 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 106 await setFieldsValue({ ...params });
108 107 } else {
109 108 editId.value = '';
... ...
... ... @@ -337,7 +337,6 @@
337 337 }
338 338 },
339 339 onDisconnected() {
340   - console.log('断开连接了');
341 340 close();
342 341 },
343 342 });
... ...
... ... @@ -354,7 +354,6 @@
354 354 }
355 355 },
356 356 onDisconnected() {
357   - console.log('断开连接了');
358 357 close();
359 358 },
360 359 });
... ...
... ... @@ -75,9 +75,7 @@ export const formSchema: FormSchema[] = [
75 75 }
76 76 },
77 77 // showUploadList: true,
78   - onDownload(file) {
79   - console.log(file);
80   - },
  78 + onDownload() {},
81 79 onPreview: (fileList: FileItem) => {
82 80 createImgPreview({ imageList: [fileList.url!] });
83 81 },
... ...
... ... @@ -153,7 +153,7 @@
153 153 <template #renderItem="{ item }: BasicCardListRenderItem<BigScreenCenterItemsModel>">
154 154 <Card
155 155 :style="{
156   - '--viewType': item.viewType === ViewType.PUBLIC_VIEW ? '#1890ff' : '#faad14',
  156 + '--viewType': item.viewType === ViewType.PUBLIC_VIEW ? '#faad14' : '#1890ff',
157 157 }"
158 158 class="card-container"
159 159 >
... ...
... ... @@ -192,7 +192,6 @@
192 192 getRestData.value = resp;
193 193 commonRest(resp, jsonEditorRef.value?.setJsonValue);
194 194 } catch (e) {
195   - console.log(e);
196 195 if (Object.prototype.toString.call(e) === '[object Object]') {
197 196 jsonEditorRef.value?.setJsonValue(e);
198 197 } else {
... ...
... ... @@ -61,7 +61,7 @@ export const useUtils = () => {
61 61 }
62 62 }
63 63 } catch (e) {
64   - console.log(`Post没有传递params${e}`);
  64 + console.error(`Post没有传递params${e}`);
65 65 }
66 66 return _result.join('&');
67 67 };
... ...
... ... @@ -10,6 +10,7 @@
10 10 ...basicProps,
11 11 value: {
12 12 required: true,
  13 + type: Object,
13 14 },
14 15 });
15 16
... ...
... ... @@ -48,8 +48,8 @@
48 48 }
49 49 };
50 50
51   - const insertDeviceTypeName = (
52   - deviceTypeName: string,
  51 + const insertProductionName = (
  52 + productionName: string,
53 53 fileParseValue: UploadFileParseValue,
54 54 columns: Record<'type', string>[]
55 55 ): { file: string; columns: Record<'type', string>[] } => {
... ... @@ -58,11 +58,11 @@
58 58
59 59 const csvArray = content.map((item) => header.map((key) => item[key]) as string[]);
60 60 for (const item of csvArray) {
61   - item.splice(insertIndex, 0, deviceTypeName);
  61 + item.splice(insertIndex, 0, productionName);
62 62 }
63 63
64 64 const _header = [...header];
65   - _header.splice(insertIndex, 0, deviceTypeName);
  65 + _header.splice(insertIndex, 0, productionName);
66 66 csvArray.unshift(_header);
67 67 const file = csvArray.map((item) => item.join(DelimiterEnum.COMMA)).join('\n');
68 68
... ... @@ -80,14 +80,14 @@
80 80 tkDeviceProfileId,
81 81 organizationId,
82 82 deviceTypeEnum,
83   - deviceTypeName,
  83 + productionName,
84 84 gateWayTbDeviceId,
85 85 tbDeviceProfileId,
86 86 isTcpDeviceProfile,
87 87 } = basicInfo;
88 88
89   - const { file, columns } = insertDeviceTypeName(
90   - deviceTypeName,
  89 + const { file, columns } = insertProductionName(
  90 + productionName,
91 91 fileParseValue,
92 92 columnConfiguration
93 93 );
... ...
... ... @@ -22,6 +22,7 @@ export enum FieldsEnum {
22 22 TB_DEVICE_PROFILE_ID = 'tbDeviceProfileId',
23 23 IS_TCP_DEVICE_PROFILE = 'isTcpDeviceProfile',
24 24 TRANSPORT_TYPE = 'transportType',
  25 + PRODUCTION_NAME = 'productionName',
25 26 }
26 27
27 28 export enum DelimiterEnum {
... ... @@ -171,7 +172,7 @@ export const basicInfoForm: FormSchema[] = [
171 172 placeholder: '请选择产品',
172 173 params: { deviceType },
173 174 getPopupContainer: () => document.body,
174   - onChange(value: string, options: DeviceRecord) {
  175 + onChange(value: string, options: DeviceRecord & Record<'label', string>) {
175 176 setFieldsValue({
176 177 [FieldsEnum.IS_TCP_DEVICE_PROFILE]: value
177 178 ? options.transportType === TransportTypeEnum.TCP
... ... @@ -179,6 +180,7 @@ export const basicInfoForm: FormSchema[] = [
179 180 [FieldsEnum.TB_DEVICE_PROFILE_ID]: value ? options.tbProfileId : null,
180 181 [FieldsEnum.GATEWAY_TB_DEVICE_ID]: null,
181 182 [FieldsEnum.TRANSPORT_TYPE]: options?.transportType,
  183 + [FieldsEnum.PRODUCTION_NAME]: options?.label,
182 184 });
183 185 },
184 186 showSearch: true,
... ... @@ -195,6 +197,12 @@ export const basicInfoForm: FormSchema[] = [
195 197 show: false,
196 198 },
197 199 {
  200 + field: FieldsEnum.PRODUCTION_NAME,
  201 + label: '',
  202 + component: 'Input',
  203 + show: false,
  204 + },
  205 + {
198 206 field: FieldsEnum.GATEWAY_TB_DEVICE_ID,
199 207 component: 'ApiSelect',
200 208 label: '网关设备',
... ...
... ... @@ -26,6 +26,7 @@ export type BasicInfoRecord = Record<
26 26 | 'deviceTypeName'
27 27 | 'gateWayTbDeviceId'
28 28 | 'gateWayTkDeviceId'
  29 + | 'productionName'
29 30 | 'tbDeviceProfileId',
30 31 string
31 32 > &
... ...
... ... @@ -100,11 +100,9 @@
100 100 const { send, close } = useWebSocket(state.server, {
101 101 onConnected() {
102 102 send(state.sendValue);
103   - console.log('建立连接了');
104 103 },
105 104 onMessage(_, e) {
106 105 const { data } = JSON.parse(e.data);
107   - console.log('来新消息了', '---data---', data);
108 106 const newArray: socketDataType[] = [];
109 107 for (const key in data) {
110 108 const [time, value] = data[key].flat(1);
... ... @@ -134,7 +132,6 @@
134 132 });
135 133 },
136 134 onDisconnected() {
137   - console.log('断开连接了');
138 135 close();
139 136 },
140 137 onError() {
... ...
... ... @@ -32,13 +32,12 @@
32 32 import { BasicTable, useTable, TableAction } from '/@/components/Table';
33 33 import { Switch } from 'ant-design-vue';
34 34 import { DeviceRecord } from '/@/api/device/model/deviceModel';
35   - import { watch } from 'vue';
36 35 import VideoModal from './videoModal.vue';
37 36 import { useModal } from '/@/components/Modal';
38 37 import { onMounted } from 'vue';
39 38 import { useMessage } from '/@/hooks/web/useMessage';
40 39
41   - const props = defineProps({
  40 + defineProps({
42 41 fromId: {
43 42 type: String,
44 43 default: '',
... ... @@ -49,13 +48,6 @@
49 48 },
50 49 });
51 50
52   - watch(
53   - () => props,
54   - () => {
55   - console.log(props, 'props');
56   - }
57   - );
58   -
59 51 const [registerModal, { openModal }] = useModal();
60 52
61 53 const [registerTable, { setTableData, setProps, setSelectedRowKeys, reload }] = useTable({
... ... @@ -68,14 +60,10 @@
68 60 labelWidth: 120,
69 61 schemas: searchFormSchema,
70 62 },
71   - beforeFetch: (params) => {
72   - console.log(params);
73   - },
74 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 67 setProps({
80 68 loading: true,
81 69 });
... ... @@ -281,7 +269,6 @@
281 269 });
282 270
283 271 const handlePlay = (record: Recordable) => {
284   - console.log(record);
285 272 openModal(true, {
286 273 record,
287 274 });
... ...
... ... @@ -346,7 +346,6 @@ export const schemas: FormSchema[] = [
346 346 return {
347 347 onChange(value) {
348 348 const { updateSchema } = formActionType;
349   - console.log(value);
350 349 formModel.interval = '';
351 350 updateSchema({
352 351 field: 'interval',
... ...
... ... @@ -235,7 +235,6 @@
235 235
236 236 function loadDataSuccess(excelDataList: ExcelData[]) {
237 237 tableListRef.value = [];
238   - console.log(excelDataList);
239 238 for (const excelData of excelDataList) {
240 239 const {
241 240 header,
... ... @@ -294,9 +293,7 @@
294 293 });
295 294 };
296 295 //导入
297   - function handleImport() {
298   - console.log('record');
299   - }
  296 + function handleImport() {}
300 297 function handleSuccess() {
301 298 reload();
302 299 }
... ...
... ... @@ -204,8 +204,7 @@
204 204 });
205 205 flag && createMessage.info(flag?.message);
206 206 } catch (msg) {
207   - // eslint-disable-next-line no-console
208   - console.log(msg, 'msg');
  207 + console.error(msg, 'msg');
209 208 } finally {
210 209 closeLoading();
211 210 closeModal();
... ...
... ... @@ -96,7 +96,6 @@
96 96 render: (_, data: Bootstrap) => (data.notifIfDisabled ? '启用' : '禁用'),
97 97 },
98 98 ];
99   - console.log(unref(getOtherSetting));
100 99 const [registerOtherSettings] = useDescription({
101 100 layout: 'vertical',
102 101 column: 2,
... ...
... ... @@ -68,21 +68,18 @@
68 68 <Button v-if="isShowBtn" class="!bg-gray-200" type="text" @click="handleReturn">
69 69 返回
70 70 </Button>
71   - <Authority :value="[ModelOfMatterPermission.DELETE, ModelCategoryPermission.DELETE]">
  71 + <Authority
  72 + v-if="isShowBtn"
  73 + :value="[ModelOfMatterPermission.DELETE, ModelCategoryPermission.DELETE]"
  74 + >
72 75 <Popconfirm
73 76 title="您确定要批量删除数据"
74 77 ok-text="确定"
75 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 83 </Popconfirm>
87 84 </Authority>
88 85 </div>
... ... @@ -120,11 +117,7 @@
120 117 />
121 118 </template>
122 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 121 <PhysicalModelTsl :record="$props.record" @register="registerModalTsl" />
129 122 <SelectImport
130 123 :record="$props.record"
... ... @@ -142,7 +135,6 @@
142 135 ModelCategoryPermission,
143 136 physicalColumn,
144 137 } from '../device.profile.data';
145   - import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
146 138 import { Authority } from '/@/components/Authority';
147 139 import PhysicalModelModal from './cpns/physical/PhysicalModelModal.vue';
148 140 import PhysicalModelTsl from './cpns/physical/PhysicalModelTsl.vue';
... ... @@ -156,8 +148,11 @@
156 148 releaseModel,
157 149 } from '/@/api/device/modelOfMatter';
158 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 156 import { isObject } from '/@/utils/is';
162 157 import { useRole } from '/@/hooks/business/useRole';
163 158 import { ExportModelCategory } from '/@/api/device/modelOfMatter';
... ... @@ -177,50 +172,45 @@
177 172 const [registerModalTsl, { openModal: openModalTsl }] = useModal();
178 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 215 const handleViewDetail = (record: ModelOfMatterParams) => {
226 216 if (record) {
... ... @@ -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 251 const handleOpenTsl = () => {
249 252 openModalTsl(true, {
250 253 isUpdate: true,
... ...
... ... @@ -30,9 +30,7 @@
30 30 import { SelectTypes } from 'ant-design-vue/es/select';
31 31
32 32 const emit = defineEmits(['register', 'emitSelect']);
33   - const [register] = useModalInner((data) => {
34   - console.log(data);
35   - });
  33 + const [register] = useModalInner(() => {});
36 34 const heightNum = ref(80);
37 35 const visible = ref(false);
38 36 const selectValue = ref('LwM2M');
... ...
... ... @@ -130,14 +130,13 @@
130 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 140 const [
142 141 registerSettings,
143 142 {
... ... @@ -152,14 +151,13 @@
152 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 161 const [registerModal, { openModal }] = useModal();
164 162
165 163 const handleAdd = () => {
... ... @@ -205,10 +203,6 @@
205 203 };
206 204
207 205 const getFormData = async () => {
208   - const objectListVal = getObjectListValue();
209   - const deviceVal = getDeviceValue();
210   - console.log('第一个tab', objectListVal);
211   - console.log('第四个tab', deviceVal);
212 206 getBootStrapFormValue();
213 207 const settingsVal = await settingsValidate();
214 208 if (!settingsVal) return;
... ...
... ... @@ -69,7 +69,7 @@
69 69 if (unref(copied)) createMessage.success('复制成功!');
70 70 else createMessage.error('复制失败!');
71 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 172 const record = await findMessageConfig(params);
173 173 return record.filter((item) => item.status === 1);
174 174 } catch (error) {
175   - // eslint-disable-next-line no-console
176   - console.log(error);
  175 + console.error(error);
177 176 return [];
178 177 }
179 178 },
... ...
... ... @@ -41,7 +41,7 @@
41 41 checksumAlgorithm: value.checksumAlgorithm,
42 42 });
43 43 } catch (error) {
44   - console.log(error);
  44 + console.error(error);
45 45 if ((error as { status: number }).status) {
46 46 await deleteOtaPackage(id);
47 47 }
... ...
... ... @@ -6,7 +6,7 @@
6 6 border-color: #6b7280;
7 7 }
8 8
9   -.vue-flow__handle:hover{
  9 +.vue-flow__handle:hover {
10 10 background-color: #000;
11 11 }
12 12
... ... @@ -15,7 +15,7 @@
15 15 }
16 16
17 17 .vue-flow__handle-left {
18   - left: -12px;
  18 + left: -12px;
19 19 }
20 20
21 21 .vue-flow__background.vue-flow__container {
... ... @@ -32,7 +32,7 @@
32 32 stroke-width: 4;
33 33 stroke: gray;
34 34 transition: stroke-width 0.3s;
35   -}
  35 +}
36 36
37 37 .connection-focus {
38 38 stroke-width: 6;
... ... @@ -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 48 stroke-width: 6 !important;
49 49 }
50 50
... ... @@ -54,18 +54,19 @@
54 54 }
55 55
56 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 64 /* selection 选择框 */
65   -.vue-flow__nodesselection-rect, .vue-flow__selection{
  65 +.vue-flow__nodesselection-rect,
  66 +.vue-flow__selection {
66 67 border-width: 3px;
67 68 }
68 69
69   -.vue-flow__nodesselection-rect {
  70 +.vue-flow__nodesselection-rect {
70 71 pointer-events: none;
71 72 }
... ...
... ... @@ -64,7 +64,10 @@
64 64 }
65 65
66 66 function handleOnOrganizationOptionsChange(options: OrganizationListItem[]) {
67   - if (unref(drawerMode) === DataActionModeEnum.CREATE) {
  67 + if (
  68 + unref(drawerMode) === DataActionModeEnum.CREATE &&
  69 + !basicFormActionType.getFieldsValue()?.[FormFieldsEnum.ORGANIZATION_ID]
  70 + ) {
68 71 const [firsetItem] = options;
69 72 organizationId.value = firsetItem?.id;
70 73 basicFormActionType.setFieldsValue({ [FormFieldsEnum.ORGANIZATION_ID]: firsetItem?.id });
... ...
... ... @@ -236,7 +236,7 @@
236 236 // 设置输出值
237 237 outputEditor.value.set(result);
238 238 } catch (e) {
239   - console.log(e);
  239 + console.error(e);
240 240 const { createMessage } = useMessage();
241 241 createMessage.error(e.toString());
242 242 }
... ...
... ... @@ -85,9 +85,7 @@
85 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 86 if (reg.test(formData.mobile)) {
87 87 const sendRes = await passwordResetCode(formData.mobile);
88   - console.log(sendRes);
89 88 if (sendRes === '') {
90   - console.log('发送成功了');
91 89 return true;
92 90 }
93 91 return false;
... ...
... ... @@ -99,6 +99,5 @@
99 99 async function handleRegister() {
100 100 const data = await validForm();
101 101 if (!data) return;
102   - console.log(data);
103 102 }
104 103 </script>
... ...
... ... @@ -27,7 +27,6 @@
27 27 onMounted(() => {
28 28 // 记录当前的UserId
29 29 userId.value = userStore.getUserInfo?.userId;
30   - console.log('Mounted', userStore.getUserInfo);
31 30 });
32 31
33 32 onBeforeUnmount(() => {
... ...
... ... @@ -14,7 +14,6 @@
14 14 Reflect.deleteProperty(params, 'path');
15 15
16 16 const _path = Array.isArray(path) ? path.join('/') : path;
17   - console.log(unref(currentRoute));
18 17 if (_redirect_type === 'name') {
19 18 replace({
20 19 name: _path,
... ...
... ... @@ -138,7 +138,6 @@
138 138 }
139 139 if (newFieldValue.codeTown == undefined) {
140 140 validateArray.push('prov');
141   - console.log(validateArray);
142 141 } else {
143 142 const findExistIndex1 = validateArray.findIndex((o) => o == 'prov');
144 143 if (findExistIndex1 !== -1) {
... ...
... ... @@ -5,7 +5,8 @@
5 5 <Tabs.TabPane
6 6 v-if="
7 7 isWhereAdmin == 'TENANT_ADMIN' ||
8   - (isWhereAdmin == 'SYS_ADMIN' || isWhereAdmin == 'CUSTOMER_USER')
  8 + isWhereAdmin == 'SYS_ADMIN' ||
  9 + isWhereAdmin == 'CUSTOMER_USER'
9 10 "
10 11 key="企业信息"
11 12 tab="企业信息"
... ...
... ... @@ -264,7 +264,6 @@
264 264 setProps({
265 265 loading: true,
266 266 });
267   - console.log(sendTime.value);
268 267 let startTime = null;
269 268 let endTime = null;
270 269 if (sendTime.value.length > 0) {
... ...
... ... @@ -49,6 +49,7 @@
49 49 font-size: 16px;
50 50 font-weight: 500;
51 51 }
  52 +
52 53 :deep(.vben-collapse-container__header) {
53 54 border-bottom: none;
54 55 }
... ...
... ... @@ -134,7 +134,7 @@
134 134 copyTransFun(data as any);
135 135 return data;
136 136 } catch (error) {
137   - console.log(error);
  137 + console.error(error);
138 138 return [];
139 139 }
140 140 },
... ...
... ... @@ -77,7 +77,7 @@
77 77 copyTransFun(data as any);
78 78 return data;
79 79 } catch (error) {
80   - console.log(error);
  80 + console.error(error);
81 81 return [];
82 82 }
83 83 },
... ...
... ... @@ -10,7 +10,8 @@
10 10
11 11 const alert = {
12 12 [PackagesCategoryEnum.MAP]: [
13   - '地图组件,需绑定两个数据源,且数据源为同一设备。第一数据源为经度,第二数据源为纬度,否则地图组件不能正常显示。',
  13 + '1、绑定数据源为结构体时,可以自行选择结构体里的属性作为经纬度',
  14 + '2、绑定数据源为非结构体时,第一数据源为经度,第二数据源为纬度,且数据源为同一设备,并同时上报。否则地图组件不能正常显示。',
14 15 ],
15 16 };
16 17
... ...
... ... @@ -34,14 +34,6 @@
34 34 const { unit, fontColor, showDeviceName } = item.componentInfo || {};
35 35 const { deviceName, deviceRename, attribute, attributeRename, deviceId, attributeName } =
36 36 item;
37   - // return {
38   - // unit: unit ?? persetUnit,
39   - // fontColor: fontColor ?? persetFontColor,
40   - // showDeviceName: showDeviceName ?? persetShowDeviceName,
41   - // attribute,
42   - // deviceName,
43   - // deviceRename,
44   - // };
45 37 return {
46 38 unit: unit ?? presetUnit,
47 39 fontColor: fontColor ?? presetFontColor,
... ... @@ -58,7 +50,6 @@
58 50 });
59 51
60 52 const getOffset = (length: number, index: number) => {
61   - // try {
62 53 const offsetList = ref<any>([]);
63 54 switch (length) {
64 55 case 1:
... ... @@ -147,7 +138,6 @@
147 138 break;
148 139 }
149 140 return unref(offsetList);
150   - // } catch {}
151 141 };
152 142
153 143 const series = ref(
... ... @@ -263,7 +253,6 @@
263 253 series.value.forEach((item) => {
264 254 if (item.id === deviceId && item.attribute === attribute && value) {
265 255 item.value = getNumberValue(value);
266   - // time.value = timespan;
267 256 }
268 257 });
269 258 });
... ...
... ... @@ -62,7 +62,6 @@
62 62 const options = (): EChartsOption => {
63 63 const { unit, fontColor, pointerColor, maxNumber, valueSize } = unref(getDesign);
64 64
65   - // getStageColor(gradientInfo);
66 65 return {
67 66 series: [
68 67 {
... ... @@ -103,14 +102,6 @@
103 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 105 title: {
115 106 show: false,
116 107 },
... ...
... ... @@ -3,7 +3,7 @@
3 3 import { BasicModal, useModalInner } from '/@/components/Modal';
4 4 import { formSchema, getHistorySearchParams, SchemaFiled } from './history.config';
5 5 import { HistoryModalOkEmitParams } from './type';
6   - import { ref } from 'vue';
  6 + import { ref, unref } from 'vue';
7 7 import { getAllDeviceByOrg } from '/@/api/dataBoard';
8 8 import { getDeviceHistoryInfo } from '/@/api/alarm/position';
9 9 import { DataSource } from '/@/views/visual/palette/types';
... ... @@ -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 103 } catch (error) {
66 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 167 const validEffective = (value = '') => {
71 168 return !!(value && !isNaN(value as unknown as number));
72 169 };
73   - const loading = ref(false);
74 170 const handleOk = async () => {
75 171 try {
76 172 await validate();
... ... @@ -84,33 +180,9 @@
84 180 ...value,
85 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 186 emit('ok', { track, value } as HistoryModalOkEmitParams);
115 187 closeModal();
116 188 } catch (error) {
... ...
... ... @@ -24,6 +24,14 @@
24 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 36 * @description 经度key
29 37 */
... ... @@ -42,7 +50,7 @@
42 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 54 if (unref(getDeviceId) !== deviceId) return;
47 55
48 56 const { data = {} } = message;
... ... @@ -51,7 +59,7 @@
51 59
52 60 const lngData = bindMessage[unref(getLngKey)] || [];
53 61 const [lngLatest] = lngData;
54   - const [, lng] = lngLatest;
  62 + const [, lng] = lngLatest || [];
55 63
56 64 const latData = bindMessage[unref(getLatKey)] || [];
57 65 const [latLatest] = latData;
... ... @@ -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 101 useMultipleDataFetch(props, updateFn);
66 102
67 103 const { drawLine } = useMapTrackPlayBack(mapInstance);
... ... @@ -100,11 +136,3 @@
100 136 <div v-show="!loading" ref="wrapRef" :id="wrapId" class="w-full h-full no-drag"> </div>
101 137 </main>
102 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 247 });
248 248 },
249 249 placeholder: '请选择设备',
250   - getPopupContainer: () => document.body,
251 250 ...createPickerSearch(),
252 251 };
253 252 },
... ... @@ -382,11 +381,18 @@ export const commonDataSourceSchemas = (): FormSchema[] => {
382 381 return [];
383 382 },
384 383 placeholder: '请选择属性',
385   - getPopupContainer: () => document.body,
386 384 onChange(value: string, option: Record<'label' | 'value' | any, string>) {
  385 + const { detail }: any = option || {};
387 386 setFieldsValue({
388 387 [DataSourceField.ATTRIBUTE_NAME]: value ? option.label : null,
389 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 398 ...createPickerSearch(),
... ... @@ -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 443 field: DataSourceField.EXTENSION_DESC,
398 444 component: 'Input',
399 445 show: false,
... ...
1   -import { ReceiveTsSubCmdsGroupMessageType } from '../index.type';
  1 +import { ReceiveTsSubCmdsGroupMessageType } from './socket/useSocket.type';
2 2
3 3 export const useReceiveMessage = () => {
4 4 const forEachGroupMessage = (
... ...
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   -}
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>
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>
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   -};
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 150 getIsSharePage,
151 151 (value) => {
152 152 if (value) {
153   - console.log(unref(getDarkMode));
154 153 const root = document.querySelector('#app');
155 154 (root as HTMLDivElement).style.backgroundColor =
156 155 unref(getDarkMode) === ThemeEnum.LIGHT ? '#F5F5F5' : '#1b1b1b';
... ...
... ... @@ -29,6 +29,9 @@ export interface DataSource {
29 29 customCommand: CustomCommand;
30 30 videoConfig?: VideoConfigType;
31 31 [key: string]: any;
  32 + lal?: string;
  33 + latitude?: string | number;
  34 + longitude?: string | number;
32 35 }
33 36
34 37 export interface ExtraDataSource extends DataSource, PublicComponentOptions {
... ...
... ... @@ -32,7 +32,6 @@ app.ws.use(
32 32 });
33 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 58 app.use(koaStatic(path.join(__dirname)));
60 59
61 60 app.listen(PORT, () => {
  61 + // eslint-disable-next-line no-console
62 62 console.log(`Application started successfully: http://localhost:${PORT}`);
63 63 });
... ...