Commit f10a80cccd865e1955edbc643805cde72ab4c9b7

Authored by 黄 x
2 parents ca1b0773 1710a222

Merge remote-tracking branch 'origin/ww'

# Conflicts:
#	src/views/tenant/list/TenantDrawer.vue
... ... @@ -14,9 +14,9 @@ VITE_PUBLIC_PATH = /
14 14 # VITE_PROXY = [["/api","http://101.133.234.90:8080/api"]]
15 15 # 线上测试环境
16 16 # VITE_PROXY = [["/api","http://localhost:8080/api"],["/thingskit-drawio","http://localhost:3000/"]]
17   -VITE_PROXY = [["/api","http://222.180.200.114:48080/api"],["/thingskit-drawio","http://localhost:3000/"]]
  17 +# VITE_PROXY = [["/api","http://222.180.200.114:48080/api"],["/thingskit-drawio","http://localhost:3000/"]]
18 18 # VITE_PROXY = [["/api","http://121.37.251.8:8080/api"],["/thingskit-drawio","http://localhost:3000/"]]
19   -# VITE_PROXY = [["/api","http://192.168.10.103:8080/api"],["/thingskit-drawio","http://192.168.10.136:8080/api"]]
  19 +VITE_PROXY = [["/api","http://192.168.10.114:8080/api"],["/thingskit-drawio","http://192.168.10.136:8080/api"]]
20 20
21 21 # 实时数据的ws地址
22 22 # VITE_WEB_SOCKET = ws://localhost:8080/api/ws/plugins/telemetry?token=
... ...
... ... @@ -3,9 +3,10 @@ import { HistoryData } from './model';
3 3 import { defHttp } from '/@/utils/http/axios';
4 4
5 5 // 获取设备配置
6   -export const getDeviceProfile = () => {
  6 +export const getDeviceProfile = (deviceType?: string) => {
7 7 return defHttp.get<DeviceProfileModel[]>({
8 8 url: '/device_profile/me/list',
  9 + params: { deviceType },
9 10 });
10 11 };
11 12
... ...
... ... @@ -7,6 +7,7 @@ import {
7 7 DeviceAttributeParams,
8 8 DeviceAttributeRecord,
9 9 GetDataBoardParams,
  10 + GetMeetTheConditionsDeviceParams,
10 11 MasterDeviceList,
11 12 SendCommandParams,
12 13 UpdateDataBoardLayoutParams,
... ... @@ -39,9 +40,10 @@ enum SendCommand {
39 40 }
40 41
41 42 enum DeviceUrl {
42   - GET_DEVICE = '/device/list/master',
  43 + GET_DEVICE_MASTER = '/device/list/master',
43 44 GET_SLAVE_DEVICE = '/device/list/slave',
44 45 GET_DEVICE_ATTRIBUTE = '/device/attributes',
  46 + GET_DEVICE = '/device/list',
45 47 }
46 48
47 49 /**
... ... @@ -168,8 +170,20 @@ export const getShareBoardComponentInfo = (params: { boardId: string; tenantId:
168 170 */
169 171 export const getAllDeviceByOrg = (organizationId: string, deviceProfileId?: string) => {
170 172 return defHttp.get<MasterDeviceList[]>({
171   - url: `${DeviceUrl.GET_DEVICE}/${organizationId}`,
172   - params: { deviceProfileId },
  173 + url: DeviceUrl.GET_DEVICE_MASTER,
  174 + params: { deviceProfileId, organizationId },
  175 + });
  176 +};
  177 +
  178 +/**
  179 + * @description 获取满足条件的设备
  180 + * @param params
  181 + * @returns
  182 + */
  183 +export const getMeetTheConditionsDevice = (params: GetMeetTheConditionsDeviceParams) => {
  184 + return defHttp.get({
  185 + url: DeviceUrl.GET_DEVICE,
  186 + params,
173 187 });
174 188 };
175 189
... ...
... ... @@ -162,3 +162,10 @@ export interface SendCommandParams {
162 162 deviceId: string;
163 163 value: any;
164 164 }
  165 +
  166 +export interface GetMeetTheConditionsDeviceParams {
  167 + deviceLabel?: string;
  168 + deviceType?: string;
  169 + organizationId?: string;
  170 + deviceProfileId?: string;
  171 +}
... ...
... ... @@ -5,6 +5,8 @@ import {
5 5 DeviceProfileModel,
6 6 DeviceProfileQueryParam,
7 7 DeviceQueryParam,
  8 + DeviceRecord,
  9 + DeviceTypeEnum,
8 10 } from '/@/api/device/model/deviceModel';
9 11 import { ChildDeviceParams } from './model/deviceModel';
10 12 import { PaginationResult } from '/#/axios';
... ... @@ -27,6 +29,8 @@ enum DeviceManagerApi {
27 29 COMMAND_ISSUANCE = '/rpc',
28 30
29 31 DEVICE_ATTR = '/device/attributes',
  32 +
  33 + GATEWAY_DEVICE = '/device/gateway/list',
30 34 }
31 35
32 36 export const devicePage = (params: DeviceQueryParam) => {
... ... @@ -183,16 +187,34 @@ export const cancelDispatchCustomer = (data) => {
183 187 };
184 188
185 189 // 获取组织下的的所有网关设备
186   -export const getGATEWAYdevice = async (params: { organization: string }) => {
  190 +export const getGATEWAYdevice = async (params: {
  191 + organizationId: string;
  192 + deviceType: DeviceTypeEnum.GATEWAY;
  193 +}) => {
  194 + const { organizationId, deviceType } = params;
187 195 const res = await defHttp.get({
188   - url: `/device/list/GATEWAY`,
189   - params,
  196 + url: `/device/list`,
  197 + params: {
  198 + organizationId,
  199 + deviceType,
  200 + },
190 201 });
191 202 return Promise.resolve<{ label: string; value: string }[]>(
192 203 res.map((item) => ({ label: item.name, value: item.tbDeviceId }))
193 204 );
194 205 };
195 206
  207 +export const getGatewayDevice = (params: Record<'organizationId' | 'transportType', string>) => {
  208 + const { organizationId, transportType } = params;
  209 + return defHttp.get<DeviceRecord[]>({
  210 + url: DeviceManagerApi.GATEWAY_DEVICE,
  211 + params: {
  212 + organizationId,
  213 + transportType,
  214 + },
  215 + });
  216 +};
  217 +
196 218 // 获取网关设备
197 219 export const getGATEWAY = (tbDeviceId: string) => {
198 220 return defHttp.get({
... ...
... ... @@ -82,9 +82,9 @@
82 82 if (next) {
83 83 const value = next[valueField];
84 84 prev.push({
  85 + ...omit(next, [labelField, valueField]),
85 86 label: next[labelField],
86 87 value: numberToString ? `${value}` : value,
87   - ...omit(next, [labelField, valueField]),
88 88 });
89 89 }
90 90 return prev;
... ...
... ... @@ -62,7 +62,6 @@ export function useECharts(
62 62 }
63 63 nextTick(() => {
64 64 useTimeoutFn(() => {
65   - console.log(chartInstance);
66 65 if (!chartInstance) {
67 66 initCharts(getDarkMode.value as 'default');
68 67
... ... @@ -71,7 +70,6 @@ export function useECharts(
71 70 clear && chartInstance?.clear();
72 71
73 72 chartInstance?.setOption(unref(getOptions));
74   - chartInstance = null;
75 73 }, 30);
76 74 });
77 75 }
... ... @@ -105,10 +103,17 @@ export function useECharts(
105 103 return chartInstance;
106 104 }
107 105
  106 + function destory() {
  107 + if (!chartInstance) return;
  108 + chartInstance.dispose();
  109 + chartInstance = null;
  110 + }
  111 +
108 112 return {
109 113 setOptions,
110 114 resize,
111 115 echarts,
112 116 getInstance,
  117 + destory,
113 118 };
114 119 }
... ...
... ... @@ -117,15 +117,16 @@ const transform: AxiosTransform = {
117 117 const errorLogStore = useErrorLogStoreWithOut();
118 118 errorLogStore.addAjaxErrorInfo(error);
119 119 const { response, code, message, config } = error || {};
  120 +
120 121 const errorMessageMode = config?.requestOptions?.errorMessageMode || 'none';
121   - const errorMsgIsObj = typeof response.data === 'object';
  122 + const errorMsgIsObj = typeof response?.data === 'object';
122 123 const msg: string = errorMsgIsObj
123 124 ? response?.data?.message || response?.data?.msg
124   - : response.data;
  125 + : response?.data;
125 126 const err: string = error?.toString?.() ?? '';
126 127 let errMessage = '';
127 128 try {
128   - if (response.data.status == '401' || response.data.message == '"Authentication failed"') {
  129 + if (response?.data?.status == '401' || response?.data?.message == '"Authentication failed"') {
129 130 window.localStorage.clear();
130 131 window.sessionStorage.clear();
131 132 router.push(PageEnum.BASE_HOME);
... ...
1 1 import { FormSchema } from '/@/components/Form';
2 2 import { findDictItemByCode } from '/@/api/system/dict';
3   -import { deviceProfile, getGATEWAYdevice } from '/@/api/device/deviceManager';
  3 +import { deviceProfile, getGatewayDevice } from '/@/api/device/deviceManager';
4 4
5 5 export enum TypeEnum {
6 6 IS_GATEWAY = 'GATEWAY',
... ... @@ -73,7 +73,12 @@ export const step1Schemas: FormSchema[] = [
73 73 option: { deviceType: string; transportType: string; id: string }
74 74 ) {
75 75 const { deviceType, transportType, id } = option;
76   - setFieldsValue({ deviceType: deviceType, transportType, deviceProfileId: id });
  76 + setFieldsValue({
  77 + deviceType: deviceType,
  78 + transportType,
  79 + deviceProfileId: id,
  80 + gatewayId: null,
  81 + });
77 82 },
78 83 };
79 84 },
... ... @@ -125,7 +130,6 @@ export const step1Schemas: FormSchema[] = [
125 130 },
126 131 ifShow: ({ values }) => isGateWay(values.deviceType),
127 132 },
128   -
129 133 {
130 134 field: 'organizationId',
131 135 label: '所属组织',
... ... @@ -140,13 +144,20 @@ export const step1Schemas: FormSchema[] = [
140 144 component: 'ApiSelect',
141 145 ifShow: ({ values }) => values.deviceType === 'SENSOR' && values.organizationId,
142 146 componentProps: ({ formModel }) => {
143   - const { organizationId } = formModel;
  147 + const { organizationId, transportType } = formModel;
144 148 return {
145   - api: getGATEWAYdevice,
  149 + // api: async (params: Record<'transportType' | 'organizationId', string>) => {
  150 + // const options = await getGatewayDevice(params);
  151 + // return options.filter((item) => item.deviceType === DeviceTypeEnum.GATEWAY);
  152 + // },
  153 + api: getGatewayDevice,
146 154 showSearch: true,
147 155 params: {
148 156 organizationId,
  157 + transportType,
149 158 },
  159 + valueField: 'id',
  160 + labelField: 'name',
150 161 };
151 162 },
152 163 },
... ...
... ... @@ -18,6 +18,7 @@
18 18 import { computed } from '@vue/reactivity';
19 19 import { Specs, StructJSON } from '/@/api/device/model/modelOfMatterModel';
20 20 import { isArray, isObject } from '/@/utils/is';
  21 + import { DateTypeEnum } from '/@/components/Form/src/externalCompns/components/StructForm/config';
21 22
22 23 interface ReceiveMessage {
23 24 data: {
... ... @@ -89,6 +90,7 @@
89 90 );
90 91 await nextTick();
91 92 socketInfo.dataSource = data;
  93 +
92 94 setTableData(data);
93 95 } catch (error) {}
94 96 },
... ... @@ -127,14 +129,17 @@
127 129 const getUnit = (record: StructJSON) => {
128 130 const { dataType } = record;
129 131 const { specs } = dataType! || {};
130   -
131 132 return isObject(specs)
132 133 ? (specs as Specs).unitName && (specs as Specs).unit
133   - ? `${(specs as Specs).unitName}/${(specs as Specs).unit}`
  134 + ? `${(specs as Specs).unitName}`
134 135 : ''
135 136 : '';
136 137 };
137 138
  139 + const isStructAndTextType = (type: DateTypeEnum) => {
  140 + return [DateTypeEnum.IS_STRUCT, DateTypeEnum.IS_STRING].includes(type);
  141 + };
  142 +
138 143 const { send, close, data } = useWebSocket(socketInfo.origin, {
139 144 async onConnected() {
140 145 const { deviceProfileId } = props.deviceDetail;
... ... @@ -156,7 +161,18 @@
156 161 const { identifier: key, name, detail } = item;
157 162 const unit = getUnit(detail);
158 163 const [time, value] = socketInfo.message[key].at(0) || [];
159   - return { key, value, time, name, unit };
  164 + const dataInfo = socketInfo.attrKeys.find((item) => item.identifier === key);
  165 +
  166 + return {
  167 + key,
  168 + value,
  169 + time,
  170 + name,
  171 + unit,
  172 + showHistoryDataButton: !isStructAndTextType(
  173 + dataInfo?.detail.dataType as unknown as DateTypeEnum
  174 + ),
  175 + };
160 176 });
161 177
162 178 await nextTick();
... ... @@ -226,15 +242,21 @@
226 242 <span class="text-base font-normal">{{ item.name }}</span>
227 243 </template>
228 244 <template #extra>
229   - <Button type="link" class="!p-0" @click="handleShowDetail(item)">历史数据</Button>
  245 + <Button
  246 + v-if="item.showHistoryDataButton"
  247 + type="link"
  248 + class="!p-0"
  249 + @click="handleShowDetail(item)"
  250 + >历史数据</Button
  251 + >
230 252 </template>
231 253 <section class="min-h-16 flex flex-col justify-between">
232 254 <div class="flex font-bold text-lg mb-4 gap-2">
233 255 <div>{{ item.value || '--' }}</div>
234   - <div>{{ item.unit }}</div>
  256 + <div class="text-xs flex items-center">{{ item.unit }}</div>
235 257 </div>
236 258 <div class="text-dark-800 text-xs">
237   - {{ item.value ? formatToDateTime(item.time) : '--' }}
  259 + {{ item.value ? formatToDateTime(item.time, 'YYYY-MM-DD HH:mm:ss') : '--' }}
238 260 </div>
239 261 </section>
240 262 </Card>
... ...
... ... @@ -40,7 +40,6 @@
40 40 import { FileItem } from '/@/components/Upload/src/typing';
41 41 import { upload } from '/@/api/oss/ossFileUploader';
42 42 import { getTenantRoles, updateOrCreateTenant } from '/@/api/tenant/tenantApi';
43   - import { useMessage } from '/@/hooks/web/useMessage';
44 43 export default defineComponent({
45 44 name: 'TenantDrawer',
46 45 components: {
... ... @@ -120,8 +119,8 @@
120 119
121 120 //提交按钮
122 121 async function handleSubmit() {
  122 + setDrawerProps({ confirmLoading: true });
123 123 try {
124   - setDrawerProps({ confirmLoading: true });
125 124 const values = await validate();
126 125 const req = {
127 126 id: values.id,
... ... @@ -140,22 +139,16 @@
140 139 entityType: 'TENANT_PROFILE',
141 140 },
142 141 };
143   - updateOrCreateTenant(req)
144   - .then((res) => {
145   - console.log(res);
146   - closeDrawer(); //关闭侧框
147   - emit('success');
148   - setTimeout(() => {
149   - setDrawerProps({ confirmLoading: false });
150   - }, 300);
151   - })
152   - .catch((e) => {
153   - const { createMessage } = useMessage();
154   - createMessage.error(`${e.message}`);
155   - })
156   - .finally(() => {});
  142 + await updateOrCreateTenant(req);
  143 + emit('success');
  144 + closeDrawer(); //关闭侧框
157 145 } catch (e) {
  146 + if ((e as { code: string }).code === 'ECONNABORTED') {
  147 + emit('success');
  148 + closeDrawer(); //关闭侧框
  149 + }
158 150 } finally {
  151 + setDrawerProps({ confirmLoading: false });
159 152 }
160 153 }
161 154 return {
... ...
... ... @@ -7,7 +7,7 @@
7 7 } from '@ant-design/icons-vue';
8 8 import { Tooltip, Button, Alert } from 'ant-design-vue';
9 9 import { FormActionType, useForm } from '/@/components/Form';
10   - import { basicSchema, DataSourceField, isMapComponent } from '../config/basicConfiguration';
  10 + import { basicSchema, DataSourceField } from '../config/basicConfiguration';
11 11 import BasicForm from '/@/components/Form/src/BasicForm.vue';
12 12 import { ref, shallowReactive, unref, nextTick, watch, computed, onMounted } from 'vue';
13 13 import VisualOptionsModal from './VisualOptionsModal.vue';
... ... @@ -17,7 +17,7 @@
17 17 import { useMessage } from '/@/hooks/web/useMessage';
18 18 import { DataBoardLayoutInfo } from '../../types/type';
19 19 import { getDataSourceComponent } from './DataSourceForm/help';
20   - import { FrontComponent } from '../../const/const';
  20 + import { FrontComponent, FrontComponentCategory } from '../../const/const';
21 21 import { isNullAndUnDef } from '/@/utils/is';
22 22 import { useSortable } from '/@/hooks/web/useSortable';
23 23 import { cloneDeep } from 'lodash-es';
... ... @@ -32,6 +32,7 @@
32 32 record: DataBoardLayoutInfo;
33 33 frontId?: FrontComponent;
34 34 defaultConfig?: Partial<ComponentInfo>;
  35 + componentCategory?: FrontComponentCategory;
35 36 }>();
36 37
37 38 const { createMessage } = useMessage();
... ... @@ -94,10 +95,8 @@
94 95 const validateMapComponent = async (dataSource: Record<DataSourceField, string>[]) => {
95 96 if (dataSource.length) {
96 97 const firstRecord = dataSource.at(0)!;
97   - const { deviceId, slaveDeviceId } = firstRecord;
98   - const flag = dataSource.every(
99   - (item) => item.deviceId === deviceId && item.slaveDeviceId === slaveDeviceId
100   - );
  98 + const { deviceId } = firstRecord;
  99 + const flag = dataSource.every((item) => item.deviceId === deviceId);
101 100 if (!flag) {
102 101 createMessage.warning('地图组件绑定的数据源应该一致');
103 102 return Promise.reject(false);
... ... @@ -167,7 +166,15 @@
167 166 dataSourceEl[data.id] = null;
168 167 };
169 168
  169 + const isMapComponent = computed(() => {
  170 + return props.componentCategory === FrontComponentCategory.MAP;
  171 + });
  172 +
170 173 const handleAdd = () => {
  174 + if (unref(isMapComponent) && unref(dataSource).length === 2) {
  175 + createMessage.warning('地图组件只能绑定两条数据源');
  176 + return;
  177 + }
171 178 unref(dataSource).push({
172 179 id: buildUUID(),
173 180 componentInfo: props.defaultConfig || {},
... ... @@ -255,10 +262,6 @@
255 262 return isControlComponent(props.frontId as FrontComponent);
256 263 });
257 264
258   - const isMapCmp = computed(() => {
259   - return isMapComponent(props.frontId as FrontComponent);
260   - });
261   -
262 265 onMounted(() => handleSort());
263 266
264 267 defineExpose({
... ... @@ -283,7 +286,7 @@
283 286 </div>
284 287 </template>
285 288 </Alert>
286   - <Alert type="info" show-icon v-if="isMapCmp">
  289 + <Alert type="info" show-icon v-if="isMapComponent">
287 290 <template #description>
288 291 <div>
289 292 地图组件,需绑定两个数据源,且数据源为同一设备。第一数据源为经度,第二数据源为维度,否则地图组件不能正常显示。
... ...
... ... @@ -13,6 +13,7 @@
13 13 import { ComponentInfo } from '/@/api/dataBoard/model';
14 14 import { useCalcGridLayout } from '../../hook/useCalcGridLayout';
15 15 import { FrontComponent } from '../../const/const';
  16 + import { frontComponentMap } from '../../components/help';
16 17
17 18 interface DataComponentRouteParams extends RouteParams {
18 19 id: string;
... ... @@ -40,6 +41,10 @@
40 41
41 42 const componentDefaultConfig = ref<Partial<ComponentInfo>>({});
42 43
  44 + const getComponentCategory = computed(() => {
  45 + return frontComponentMap.get(unref(frontId))?.ComponentCategory;
  46 + });
  47 +
43 48 const [register, { closeModal, changeOkLoading }] = useModalInner(
44 49 (data: { isEdit: boolean; record?: DataBoardLayoutInfo }) => {
45 50 componentRecord.value = data.record || ({} as unknown as DataBoardLayoutInfo);
... ... @@ -149,6 +154,7 @@
149 154 :front-id="frontId"
150 155 :record="componentRecord"
151 156 :defaultConfig="componentDefaultConfig"
  157 + :componentCategory="getComponentCategory"
152 158 />
153 159 </Tabs.TabPane>
154 160 <Tabs.TabPane key="visualConfig" tab="可视化配置">
... ...
... ... @@ -28,7 +28,7 @@
28 28 const { deviceAttrs, getDeviceKeys, getSearchParams, setChartOptions, getDeviceAttribute } =
29 29 useHistoryData();
30 30
31   - const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
  31 + const { setOptions, destory } = useECharts(chartRef as Ref<HTMLDivElement>);
32 32
33 33 function hasDeviceAttr() {
34 34 if (!unref(deviceAttrs).length) {
... ... @@ -133,7 +133,7 @@
133 133 for (const item of dataSource) {
134 134 const { deviceName, gatewayDevice, slaveDeviceId, organizationId } = item;
135 135 let { deviceId } = item;
136   - if (gatewayDevice) {
  136 + if (gatewayDevice && slaveDeviceId) {
137 137 deviceId = slaveDeviceId;
138 138 }
139 139 if (record[deviceId]) continue;
... ... @@ -177,10 +177,22 @@
177 177
178 178 await handleModalOpen();
179 179 });
  180 +
  181 + const handleCancel = () => {
  182 + destory();
  183 + };
180 184 </script>
181 185
182 186 <template>
183   - <BasicModal @register="registerModal" :destroy-on-close="true" width="70%" title="历史趋势">
  187 + <BasicModal
  188 + @register="registerModal"
  189 + @cancel="handleCancel"
  190 + :destroy-on-close="true"
  191 + :show-ok-btn="false"
  192 + cancel-text="关闭"
  193 + width="70%"
  194 + title="历史趋势"
  195 + >
184 196 <section
185 197 class="flex flex-col p-4 h-full w-full min-w-7/10"
186 198 style="color: #f0f2f5; background-color: #f0f2f5"
... ...
1   -import { getAllDeviceByOrg, getDeviceAttributes, getGatewaySlaveDevice } from '/@/api/dataBoard';
  1 +import { getDeviceAttributes, getMeetTheConditionsDevice } from '/@/api/dataBoard';
2 2 import { getOrganizationList } from '/@/api/system/system';
3 3 import { FormSchema } from '/@/components/Form';
4 4 import { copyTransFun } from '/@/utils/fnUtils';
... ... @@ -6,6 +6,8 @@ import { DeviceAttributeParams, MasterDeviceList } from '/@/api/dataBoard/model'
6 6 import { FrontComponent } from '../../const/const';
7 7 import { getDeviceProfile } from '/@/api/alarm/position';
8 8 import { getModelServices } from '/@/api/device/modelOfMatter';
  9 +import { findDictItemByCode } from '/@/api/system/dict';
  10 +import { DeviceTypeEnum } from '/@/api/device/model/deviceModel';
9 11
10 12 export enum BasicConfigField {
11 13 NAME = 'name',
... ... @@ -31,10 +33,11 @@ const getDeviceService = async (deviceProfileId: string) => {
31 33
32 34 export enum DataSourceField {
33 35 IS_GATEWAY_DEVICE = 'gatewayDevice',
  36 + DEVICE_TYPE = 'deviceType',
34 37 TRANSPORT_TYPE = 'transportType',
35 38 ORIGINATION_ID = 'organizationId',
36 39 DEVICE_ID = 'deviceId',
37   - SLAVE_DEVICE_ID = 'slaveDeviceId',
  40 + // SLAVE_DEVICE_ID = 'slaveDeviceId',
38 41 DEVICE_PROFILE_ID = 'deviceProfileId',
39 42 ATTRIBUTE = 'attribute',
40 43 ATTRIBUTE_RENAME = 'attributeRename',
... ... @@ -107,6 +110,34 @@ export const dataSourceSchema = (frontId?: FrontComponent): FormSchema[] => {
107 110 show: false,
108 111 },
109 112 {
  113 + field: DataSourceField.DEVICE_TYPE,
  114 + component: 'ApiSelect',
  115 + label: '设备类型',
  116 + colProps: { span: 8 },
  117 + defaultValue: DeviceTypeEnum.SENSOR,
  118 + componentProps: ({ formActionType }) => {
  119 + const { setFieldsValue } = formActionType;
  120 + return {
  121 + api: findDictItemByCode,
  122 + params: {
  123 + dictCode: 'device_type',
  124 + },
  125 + valueField: 'itemValue',
  126 + labelField: 'itemText',
  127 + placeholder: '请选择设备类型',
  128 + onChange: (value: DeviceTypeEnum) => {
  129 + setFieldsValue({
  130 + [DataSourceField.IS_GATEWAY_DEVICE]: value === DeviceTypeEnum.GATEWAY,
  131 + [DataSourceField.DEVICE_PROFILE_ID]: null,
  132 + [DataSourceField.DEVICE_ID]: null,
  133 + [DataSourceField.ATTRIBUTE]: null,
  134 + [DataSourceField.TRANSPORT_TYPE]: null,
  135 + });
  136 + },
  137 + };
  138 + },
  139 + },
  140 + {
110 141 field: DataSourceField.DEVICE_PROFILE_ID,
111 142 component: 'ApiSelect',
112 143 label: '产品',
... ... @@ -115,9 +146,11 @@ export const dataSourceSchema = (frontId?: FrontComponent): FormSchema[] => {
115 146 componentProps: ({ formActionType, formModel }) => {
116 147 const { setFieldsValue } = formActionType;
117 148 const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID];
  149 + const deviceType = formModel[DataSourceField.DEVICE_TYPE];
118 150 return {
119 151 api: async () => {
120   - const list = await getDeviceProfile();
  152 + if (!deviceType) return [];
  153 + const list = await getDeviceProfile(deviceType);
121 154 if (deviceProfileId) {
122 155 const record = list.find((item) => item.id === deviceProfileId);
123 156 setFieldsValue({ [DataSourceField.TRANSPORT_TYPE]: record?.transportType });
... ... @@ -126,14 +159,12 @@ export const dataSourceSchema = (frontId?: FrontComponent): FormSchema[] => {
126 159 },
127 160 labelField: 'name',
128 161 valueField: 'id',
129   - onChange: (_, option: Record<'transportType', string>) => {
130   - console.log(option);
  162 + placeholder: '请选择产品',
  163 + onChange: (_, option = {} as Record<'transportType', string>) => {
131 164 setFieldsValue({
132 165 [DataSourceField.DEVICE_ID]: null,
133 166 [DataSourceField.ATTRIBUTE]: null,
134   - [DataSourceField.SLAVE_DEVICE_ID]: null,
135   - [DataSourceField.IS_GATEWAY_DEVICE]: false,
136   - [DataSourceField.TRANSPORT_TYPE]: option.transportType,
  167 + [DataSourceField.TRANSPORT_TYPE]: option[DataSourceField.TRANSPORT_TYPE],
137 168 });
138 169 },
139 170 };
... ... @@ -157,9 +188,6 @@ export const dataSourceSchema = (frontId?: FrontComponent): FormSchema[] => {
157 188 onChange() {
158 189 setFieldsValue({
159 190 [DataSourceField.DEVICE_ID]: null,
160   - [DataSourceField.ATTRIBUTE]: null,
161   - [DataSourceField.SLAVE_DEVICE_ID]: null,
162   - [DataSourceField.IS_GATEWAY_DEVICE]: false,
163 191 });
164 192 },
165 193 getPopupContainer: () => document.body,
... ... @@ -182,12 +210,17 @@ export const dataSourceSchema = (frontId?: FrontComponent): FormSchema[] => {
182 210 const { setFieldsValue } = formActionType;
183 211 const organizationId = formModel[DataSourceField.ORIGINATION_ID];
184 212 const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID];
  213 + const deviceType = formModel[DataSourceField.DEVICE_TYPE];
185 214
186 215 return {
187 216 api: async () => {
188 217 if (organizationId) {
189 218 try {
190   - const data = await getAllDeviceByOrg(organizationId, deviceProfileId);
  219 + const data = await getMeetTheConditionsDevice({
  220 + organizationId,
  221 + deviceProfileId,
  222 + deviceType,
  223 + });
191 224 if (data)
192 225 return data.map((item) => ({
193 226 ...item,
... ... @@ -202,9 +235,6 @@ export const dataSourceSchema = (frontId?: FrontComponent): FormSchema[] => {
202 235
203 236 onChange(_value, record: MasterDeviceList) {
204 237 setFieldsValue({
205   - [DataSourceField.ATTRIBUTE]: null,
206   - [DataSourceField.IS_GATEWAY_DEVICE]: record?.deviceType === 'GATEWAY',
207   - [DataSourceField.SLAVE_DEVICE_ID]: null,
208 238 [DataSourceField.DEVICE_NAME]: record?.label,
209 239 });
210 240 },
... ... @@ -214,58 +244,6 @@ export const dataSourceSchema = (frontId?: FrontComponent): FormSchema[] => {
214 244 },
215 245 },
216 246 {
217   - field: DataSourceField.SLAVE_DEVICE_ID,
218   - label: '网关子设备',
219   - component: 'ApiSelect',
220   - colProps: { span: 8 },
221   - rules: [{ required: true, message: '网关子设备为必填项' }],
222   - show: false,
223   - ifShow({ model }) {
224   - const transportType = model[DataSourceField.TRANSPORT_TYPE];
225   - return (
226   - !(isControlComponent(frontId as FrontComponent) && isTcpProfile(transportType)) &&
227   - model[DataSourceField.IS_GATEWAY_DEVICE]
228   - );
229   - },
230   - dynamicRules({ model }) {
231   - return [
232   - { required: model[DataSourceField.IS_GATEWAY_DEVICE], message: '请选择网关子设备' },
233   - ];
234   - },
235   - componentProps({ formModel, formActionType }) {
236   - const { setFieldsValue } = formActionType;
237   - const organizationId = formModel[DataSourceField.ORIGINATION_ID];
238   - const isGatewayDevice = formModel[DataSourceField.IS_GATEWAY_DEVICE];
239   - const deviceId = formModel[DataSourceField.DEVICE_ID];
240   -
241   - return {
242   - api: async () => {
243   - if (organizationId && isGatewayDevice) {
244   - try {
245   - const data = await getGatewaySlaveDevice({ organizationId, masterId: deviceId });
246   - if (data)
247   - return data.map((item) => ({
248   - ...item,
249   - label: item.name,
250   - value: item.id,
251   - deviceType: item.deviceType,
252   - }));
253   - } catch (error) {}
254   - }
255   - return [];
256   - },
257   - onChange(_value, record: MasterDeviceList) {
258   - setFieldsValue({
259   - [DataSourceField.ATTRIBUTE]: null,
260   - [DataSourceField.DEVICE_NAME]: record?.label,
261   - });
262   - },
263   - placeholder: '请选择网关子设备',
264   - getPopupContainer: () => document.body,
265   - };
266   - },
267   - },
268   - {
269 247 field: DataSourceField.ATTRIBUTE,
270 248 component: 'ApiSelect',
271 249 label: '属性',
... ... @@ -274,7 +252,6 @@ export const dataSourceSchema = (frontId?: FrontComponent): FormSchema[] => {
274 252 componentProps({ formModel }) {
275 253 const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID];
276 254 const transportType = formModel[DataSourceField.TRANSPORT_TYPE];
277   -
278 255 return {
279 256 api: async () => {
280 257 try {
... ... @@ -303,7 +280,7 @@ export const dataSourceSchema = (frontId?: FrontComponent): FormSchema[] => {
303 280 {
304 281 field: DataSourceField.DEVICE_RENAME,
305 282 component: 'Input',
306   - label: '设备',
  283 + label: '设备',
307 284 colProps: { span: 8 },
308 285 componentProps: {
309 286 placeholder: '设备重命名',
... ...