Commit 222a16b9b1a019231eb5bb7173783d69dec0f20a

Authored by fengtao
2 parents 97e7c6e1 195ab9cb

Merge branch 'main' into local_dev_ft

@@ -69,6 +69,7 @@ export interface ComponentInfo { @@ -69,6 +69,7 @@ export interface ComponentInfo {
69 icon: string; 69 icon: string;
70 value?: string | number; 70 value?: string | number;
71 updateTime?: number; 71 updateTime?: number;
  72 + showDeviceName: boolean;
72 } 73 }
73 74
74 export interface DataSource { 75 export interface DataSource {
@@ -14,7 +14,7 @@ enum Api { @@ -14,7 +14,7 @@ enum Api {
14 * @description: Get user menu based on id 14 * @description: Get user menu based on id
15 */ 15 */
16 16
17 -export const getMenuList = (args) => { 17 +export const getMenuList = (args?: number) => {
18 const userStore = useUserStore(); 18 const userStore = useUserStore();
19 let url = Api.GetMenuList; 19 let url = Api.GetMenuList;
20 try { 20 try {
@@ -94,3 +94,9 @@ export function forgetPasswordApi(data) { @@ -94,3 +94,9 @@ export function forgetPasswordApi(data) {
94 data, 94 data,
95 }); 95 });
96 } 96 }
  97 +
  98 +export const getUserToken = (id: string) => {
  99 + return defHttp.get<Record<'token' | 'refreshToken', string>>({
  100 + url: `/third/login/id/${id}`,
  101 + });
  102 +};
  1 +<svg t="1671693733059" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="25398" width="200" height="200"><path d="M585.290213 343.524914c0-37.136805-33.106002-67.357084-73.789587-67.357084-40.684608 0-73.78754 30.220279-73.78754 67.357084 0 37.120432 33.102932 67.329455 73.78754 67.329455C552.184211 410.854369 585.290213 380.645346 585.290213 343.524914zM467.227284 343.524914c0-22.289656 19.860327-40.417525 44.273343-40.417525 24.415063 0 44.273343 18.127869 44.273343 40.417525 0 22.271236-19.85828 40.389896-44.273343 40.389896C487.087611 383.91481 467.227284 365.79615 467.227284 343.524914zM511.141446 741.92667l11.455913-12.768815c8.013511-8.92937 204.344015-220.213447 203.697285-358.458021-0.506537-111.529119-101.375875-208.420867-214.795041-208.420867-113.923656 0-215.816301 96.907097-215.816301 208.483288 0 138.182153 196.101283 349.432461 204.055442 358.356714L511.141446 741.92667zM511.500627 189.219549c97.206926 0 184.830589 84.850503 185.278797 181.601034 0.517793 109.87034-144.55121 279.638885-185.553043 328.016709-40.799218-48.428989-186.026834-218.179115-186.026834-328.072991C325.199547 274.042423 413.845493 189.219549 511.500627 189.219549zM946.101839 789.395798 832.104505 600.221274c-10.316973-17.114796-30.019711-27.752064-51.421136-27.752064L673.835875 572.46921c-8.156774 0-14.759145 6.03239-14.759145 13.472849 0 7.436366 6.601348 13.46671 14.759145 13.46671l106.848517 0c10.636245 0 20.437471 5.287423 25.566282 13.795191L920.250054 802.37746c5.013177 8.337899 4.856611 18.201547-0.448208 26.380834-5.303796 8.190543-14.699794 13.077853-25.120121 13.077853L128.318504 841.836147c-10.41828 0-19.814278-4.88731-25.119097-13.077853-5.302773-8.179286-5.462408-18.042935-0.446162-26.380834l113.997334-189.174524c5.130857-8.507768 14.930037-13.795191 25.566282-13.795191L349.166401 599.407746c8.15575 0 14.757099-6.030343 14.757099-13.46671 0-7.440459-6.601348-13.472849-14.757099-13.472849L242.317884 572.468187c-21.401426 0-41.10314 10.638291-51.42216 27.752064L76.898391 789.395798c-10.102079 16.758686-9.769504 36.600593 0.89437 53.073776 10.665921 16.476253 29.5582 26.307156 50.526767 26.307156L894.680702 868.776729c20.968567 0 39.862893-9.830903 50.528813-26.307156C955.87339 825.99639 956.204941 806.154483 946.101839 789.395798z" fill="#bfbfbf" p-id="25399"></path></svg>
1 -<script lang="ts" setup></script> 1 +<script lang="ts" setup>
  2 + import { Dropdown, Menu, Popconfirm } from 'ant-design-vue';
  3 + import { computed, useSlots } from 'vue';
  4 + import Icon from '../Icon';
  5 + import { usePermission } from '/@/hooks/web/usePermission';
2 6
3 -<template> <div></div></template> 7 + export interface AuthDropDownProps {
  8 + dropMenuList: AuthDropMenuList[];
  9 + trigger?: ('contextmenu' | 'click' | 'hover')[];
  10 + }
  11 +
  12 + export interface AuthDropMenuList {
  13 + icon?: string;
  14 + event: string | number;
  15 + text: string;
  16 + disabled?: boolean;
  17 + divider?: boolean;
  18 + auth?: string;
  19 + onClick?: Fn;
  20 + popconfirm?: {
  21 + cancelText?: string;
  22 + okText?: string;
  23 + okType?: string;
  24 + title?: string;
  25 + icon?: string;
  26 + disabled?: boolean;
  27 + onCancel?: Fn;
  28 + onConfirm?: Fn;
  29 + onVisibleChange?: Fn;
  30 + };
  31 + }
  32 +
  33 + const props = defineProps<AuthDropDownProps>();
  34 +
  35 + const slot = useSlots();
  36 +
  37 + const { hasPermission } = usePermission();
  38 +
  39 + const getMenuList = computed(() => {
  40 + const { dropMenuList } = props;
  41 + return dropMenuList.filter((menu) => (menu.auth ? hasPermission(menu.auth) : true));
  42 + });
  43 +
  44 + const hasDefaultSlot = computed(() => {
  45 + return !!slot.default;
  46 + });
  47 +</script>
  48 +
  49 +<template>
  50 + <Dropdown :trigger="$props.trigger">
  51 + <template #overlay>
  52 + <Menu v-if="getMenuList.length">
  53 + <template v-for="item in getMenuList" :key="item.event">
  54 + <Menu.Divider v-if="item.divider" />
  55 + <Menu.Item v-if="!item.popconfirm" @click="item.onClick">
  56 + <span class="flex justify-center items-center">
  57 + <Icon :icon="item.icon" />
  58 + <span class="ml-2">{{ item.text }}</span>
  59 + </span>
  60 + </Menu.Item>
  61 + <Menu.Item v-if="item.popconfirm">
  62 + <Popconfirm v-bind="item.popconfirm">
  63 + <template v-if="item.popconfirm.icon" #icon>
  64 + <Icon :icon="item.popconfirm.icon" />
  65 + </template>
  66 + <span class="flex justify-center items-center">
  67 + <Icon :icon="item.icon" />
  68 + <span class="ml-2">{{ item.text }}</span>
  69 + </span>
  70 + </Popconfirm>
  71 + </Menu.Item>
  72 + </template>
  73 + </Menu>
  74 + </template>
  75 + <Icon
  76 + v-if="!hasDefaultSlot"
  77 + class="items-center justify-center"
  78 + icon="ant-design:ellipsis-outlined"
  79 + :class="!getMenuList.length ? '!text-gray-200 !cursor-not-allowed' : ''"
  80 + />
  81 + <slot name="default"></slot>
  82 + </Dropdown>
  83 +</template>
  1 +<script lang="ts" setup>
  2 + import { Icon } from '/@/components/Icon';
  3 + import { computed, ExtractPropTypes, unref } from 'vue';
  4 + import { usePermission } from '/@/hooks/web/usePermission';
  5 +
  6 + interface AuthIconProps extends ExtractPropTypes<typeof Icon> {
  7 + auth?: string;
  8 + }
  9 +
  10 + const props = defineProps<AuthIconProps>();
  11 +
  12 + const emit = defineEmits(['click']);
  13 +
  14 + const { hasPermission } = usePermission();
  15 +
  16 + const getHasPermission = computed(() => {
  17 + const { auth } = props;
  18 + return auth ? hasPermission(auth) : true;
  19 + });
  20 +
  21 + const getBindProps = computed(() => {
  22 + return {
  23 + ...props,
  24 + ...(unref(getHasPermission) ? { onClick: (event: Event) => emit('click', event) } : {}),
  25 + };
  26 + });
  27 +</script>
  28 +
  29 +<template>
  30 + <Icon
  31 + v-bind="getBindProps"
  32 + class="justify-center items-center"
  33 + :class="getHasPermission ? '' : '!cursor-not-allowed !text-gray-200'"
  34 + />
  35 +</template>
1 export { default as ModeSwitchButton } from './ModeSwitchButton.vue'; 1 export { default as ModeSwitchButton } from './ModeSwitchButton.vue';
2 export { default as CardLayoutButton } from './CardLayoutButton.vue'; 2 export { default as CardLayoutButton } from './CardLayoutButton.vue';
  3 +export { default as AuthIcon } from './AuthIcon.vue';
3 export { 4 export {
4 EnumTableCardMode, 5 EnumTableCardMode,
5 EnumTableChartMode, 6 EnumTableChartMode,
@@ -26,3 +26,26 @@ export function buildShortUUID(prefix = ''): string { @@ -26,3 +26,26 @@ export function buildShortUUID(prefix = ''): string {
26 unique++; 26 unique++;
27 return prefix + '_' + random + unique + String(time); 27 return prefix + '_' + random + unique + String(time);
28 } 28 }
  29 +
  30 +export function getlowerCaseChars() {
  31 + return Array.from({ length: 26 }).map((_, index) => String.fromCharCode(index + 97));
  32 +}
  33 +
  34 +export function getUpperCaseChars() {
  35 + return Array.from({ length: 26 }).map((_, index) => String.fromCharCode(index + 65));
  36 +}
  37 +
  38 +export function randomString(length = 20) {
  39 + const upperCaseChars = getUpperCaseChars();
  40 + const lowerCaseChars = getlowerCaseChars();
  41 + const numberChars = Array.from({ length: 10 }).map((_, index) => index);
  42 + const allChars = [...numberChars, ...upperCaseChars, ...lowerCaseChars].sort(
  43 + () => 0.5 - Math.random()
  44 + );
  45 +
  46 + const rangeFn = () => (Math.random() * 63) | 0;
  47 +
  48 + return Array.from({ length })
  49 + .map(() => allChars[rangeFn()])
  50 + .join('');
  51 +}
1 <script setup lang="ts"> 1 <script setup lang="ts">
2 import { List, Card, Button, PaginationProps, Popover, Slider, Tooltip } from 'ant-design-vue'; 2 import { List, Card, Button, PaginationProps, Popover, Slider, Tooltip } from 'ant-design-vue';
3 - import {  
4 - ReloadOutlined,  
5 - AppstoreOutlined,  
6 - EyeOutlined,  
7 - EditOutlined,  
8 - EllipsisOutlined,  
9 - } from '@ant-design/icons-vue'; 3 + import { ReloadOutlined, AppstoreOutlined } from '@ant-design/icons-vue';
10 import { computed, onMounted, reactive, ref, unref } from 'vue'; 4 import { computed, onMounted, reactive, ref, unref } from 'vue';
11 import { OrganizationIdTree, useResetOrganizationTree } from '../../common/organizationIdTree'; 5 import { OrganizationIdTree, useResetOrganizationTree } from '../../common/organizationIdTree';
12 import { 6 import {
@@ -15,7 +9,6 @@ @@ -15,7 +9,6 @@
15 } from '/@/api/configuration/center/configurationCenter'; 9 } from '/@/api/configuration/center/configurationCenter';
16 import { ConfigurationCenterItemsModal } from '/@/api/configuration/center/model/configurationCenterModal'; 10 import { ConfigurationCenterItemsModal } from '/@/api/configuration/center/model/configurationCenterModal';
17 import { PageWrapper } from '/@/components/Page'; 11 import { PageWrapper } from '/@/components/Page';
18 - import { Dropdown } from '/@/components/Dropdown';  
19 import { BasicForm, useForm } from '/@/components/Form'; 12 import { BasicForm, useForm } from '/@/components/Form';
20 import { ConfigurationPermission, searchFormSchema } from './center.data'; 13 import { ConfigurationPermission, searchFormSchema } from './center.data';
21 import { useMessage } from '/@/hooks/web/useMessage'; 14 import { useMessage } from '/@/hooks/web/useMessage';
@@ -23,12 +16,13 @@ @@ -23,12 +16,13 @@
23 import { isDevMode } from '/@/utils/env'; 16 import { isDevMode } from '/@/utils/env';
24 import ConfigurationCenterDrawer from './ConfigurationCenterDrawer.vue'; 17 import ConfigurationCenterDrawer from './ConfigurationCenterDrawer.vue';
25 import { useDrawer } from '/@/components/Drawer'; 18 import { useDrawer } from '/@/components/Drawer';
26 - import { useSyncConfirm } from '/@/hooks/component/useSyncConfirm';  
27 import { getBoundingClientRect } from '/@/utils/domUtils'; 19 import { getBoundingClientRect } from '/@/utils/domUtils';
28 import configurationSrc from '/@/assets/icons/configuration.svg'; 20 import configurationSrc from '/@/assets/icons/configuration.svg';
29 import { cloneDeep } from 'lodash'; 21 import { cloneDeep } from 'lodash';
30 import { usePermission } from '/@/hooks/web/usePermission'; 22 import { usePermission } from '/@/hooks/web/usePermission';
31 import { useGlobSetting } from '/@/hooks/setting'; 23 import { useGlobSetting } from '/@/hooks/setting';
  24 + import { AuthIcon } from '/@/components/Widget';
  25 + import AuthDropDown from '/@/components/Widget/AuthDropDown.vue';
32 26
33 const listColumn = ref(5); 27 const listColumn = ref(5);
34 28
@@ -136,10 +130,8 @@ @@ -136,10 +130,8 @@
136 window.open(`${configurationPrefix}/${isDev ? '?dev=1&' : '?'}configurationId=${record!.id}`); 130 window.open(`${configurationPrefix}/${isDev ? '?dev=1&' : '?'}configurationId=${record!.id}`);
137 }; 131 };
138 132
139 - const { createSyncConfirm } = useSyncConfirm();  
140 const handleDelete = async (record: ConfigurationCenterItemsModal) => { 133 const handleDelete = async (record: ConfigurationCenterItemsModal) => {
141 try { 134 try {
142 - await createSyncConfirm({ iconType: 'warning', content: '是否确认删除操作?' });  
143 await deleteConfigurationCenter([record.id]); 135 await deleteConfigurationCenter([record.id]);
144 createMessage.success('删除成功'); 136 createMessage.success('删除成功');
145 await getListData(); 137 await getListData();
@@ -227,20 +219,44 @@ @@ -227,20 +219,44 @@
227 </template> 219 </template>
228 <template class="ant-card-actions" #actions> 220 <template class="ant-card-actions" #actions>
229 <Tooltip title="预览"> 221 <Tooltip title="预览">
230 - <EyeOutlined  
231 - :class="getPreviewFlag ? '' : '!cursor-not-allowed !text-gray-200'"  
232 - key="setting" 222 + <AuthIcon
  223 + :auth="ConfigurationPermission.PREVIEW"
  224 + class="!text-lg"
  225 + icon="ant-design:eye-outlined"
233 @click="handlePreview(item)" 226 @click="handlePreview(item)"
234 /> 227 />
235 </Tooltip> 228 </Tooltip>
236 <Tooltip title="设计"> 229 <Tooltip title="设计">
237 - <EditOutlined  
238 - :class="getDesignFlag ? '' : '!cursor-not-allowed !text-gray-200'"  
239 - key="edit" 230 + <AuthIcon
  231 + :auth="ConfigurationPermission.DESIGN"
  232 + class="!text-lg"
  233 + icon="ant-design:edit-outlined"
240 @click="handleDesign(item)" 234 @click="handleDesign(item)"
241 /> 235 />
242 </Tooltip> 236 </Tooltip>
243 - <Dropdown 237 + <AuthDropDown
  238 + :dropMenuList="[
  239 + {
  240 + text: '编辑',
  241 + auth: ConfigurationPermission.UPDATE,
  242 + icon: 'clarity:note-edit-line',
  243 + event: '',
  244 + onClick: handleCreateOrUpdate.bind(null, item),
  245 + },
  246 + {
  247 + text: '删除',
  248 + auth: ConfigurationPermission.DELETE,
  249 + icon: 'ant-design:delete-outlined',
  250 + event: '',
  251 + popconfirm: {
  252 + title: '是否确认删除操作?',
  253 + onConfirm: handleDelete.bind(null, item),
  254 + },
  255 + },
  256 + ]"
  257 + :trigger="['hover']"
  258 + />
  259 + <!-- <Dropdown
244 :dropMenuList="[ 260 :dropMenuList="[
245 { 261 {
246 text: '编辑', 262 text: '编辑',
@@ -261,7 +277,7 @@ @@ -261,7 +277,7 @@
261 :trigger="['hover']" 277 :trigger="['hover']"
262 > 278 >
263 <EllipsisOutlined key="ellipsis" /> 279 <EllipsisOutlined key="ellipsis" />
264 - </Dropdown> 280 + </Dropdown> -->
265 </template> 281 </template>
266 <Card.Meta> 282 <Card.Meta>
267 <template #title> 283 <template #title>
@@ -80,6 +80,9 @@ export const step1Schemas: FormSchema[] = [ @@ -80,6 +80,9 @@ export const step1Schemas: FormSchema[] = [
80 gatewayId: null, 80 gatewayId: null,
81 }); 81 });
82 }, 82 },
  83 + showSearch: true,
  84 + filterOption: (inputValue: string, option: Record<'label' | 'value', string>) =>
  85 + option.label.includes(inputValue),
83 }; 86 };
84 }, 87 },
85 }, 88 },
@@ -399,6 +402,7 @@ export const step2Schemas: FormSchema[] = [ @@ -399,6 +402,7 @@ export const step2Schemas: FormSchema[] = [
399 field: 'credentialsId', 402 field: 'credentialsId',
400 required: true, 403 required: true,
401 ifShow: false, 404 ifShow: false,
  405 + slot: 'credentialsId',
402 componentProps: { 406 componentProps: {
403 maxLength: 36, 407 maxLength: 36,
404 placeholder: '请输入访问令牌', 408 placeholder: '请输入访问令牌',
@@ -421,6 +425,7 @@ export const step2Schemas: FormSchema[] = [ @@ -421,6 +425,7 @@ export const step2Schemas: FormSchema[] = [
421 field: 'clientId', 425 field: 'clientId',
422 required: true, 426 required: true,
423 ifShow: false, 427 ifShow: false,
  428 + slot: 'clientId',
424 componentProps: { 429 componentProps: {
425 maxLength: 36, 430 maxLength: 36,
426 placeholder: '请输入客户端ID', 431 placeholder: '请输入客户端ID',
@@ -597,6 +602,7 @@ export const TokenSchemas: FormSchema[] = [ @@ -597,6 +602,7 @@ export const TokenSchemas: FormSchema[] = [
597 field: 'credentialsId', 602 field: 'credentialsId',
598 required: true, 603 required: true,
599 ifShow: false, 604 ifShow: false,
  605 + slot: 'credentialsId',
600 componentProps: { 606 componentProps: {
601 maxLength: 36, 607 maxLength: 36,
602 placeholder: '请输入访问令牌', 608 placeholder: '请输入访问令牌',
@@ -90,6 +90,7 @@ export const searchFormSchema: FormSchema[] = [ @@ -90,6 +90,7 @@ export const searchFormSchema: FormSchema[] = [
90 { label: '直连设备', value: DeviceTypeEnum.DIRECT_CONNECTION }, 90 { label: '直连设备', value: DeviceTypeEnum.DIRECT_CONNECTION },
91 { label: '网关子设备', value: DeviceTypeEnum.SENSOR }, 91 { label: '网关子设备', value: DeviceTypeEnum.SENSOR },
92 ], 92 ],
  93 + placeholder: '请选择设备类型',
93 }, 94 },
94 colProps: { span: 6 }, 95 colProps: { span: 6 },
95 }, 96 },
@@ -103,13 +104,14 @@ export const searchFormSchema: FormSchema[] = [ @@ -103,13 +104,14 @@ export const searchFormSchema: FormSchema[] = [
103 { label: '在线', value: DeviceState.ONLINE }, 104 { label: '在线', value: DeviceState.ONLINE },
104 { label: '离线', value: DeviceState.OFFLINE }, 105 { label: '离线', value: DeviceState.OFFLINE },
105 ], 106 ],
  107 + placeholder: '请选择设备状态',
106 }, 108 },
107 colProps: { span: 6 }, 109 colProps: { span: 6 },
108 }, 110 },
109 { 111 {
110 field: 'deviceProfileId', 112 field: 'deviceProfileId',
111 label: '产品', 113 label: '产品',
112 - component: 'ApiSearchSelect', 114 + component: 'ApiSelect',
113 colProps: { span: 6 }, 115 colProps: { span: 6 },
114 componentProps: () => { 116 componentProps: () => {
115 return { 117 return {
@@ -118,26 +120,9 @@ export const searchFormSchema: FormSchema[] = [ @@ -118,26 +120,9 @@ export const searchFormSchema: FormSchema[] = [
118 valueField: 'id', 120 valueField: 'id',
119 resultField: 'data', 121 resultField: 'data',
120 placeholder: '请选择产品', 122 placeholder: '请选择产品',
121 - api: async () => {  
122 - const data = await deviceProfile({ params: '' });  
123 - const returnData = data.map((m) => {  
124 - return {  
125 - name: m.name,  
126 - id: m.id,  
127 - };  
128 - });  
129 - return returnData;  
130 - },  
131 - searchApi: async (params: Recordable) => {  
132 - const data = await deviceProfile({ textSearch: params.text });  
133 - const returnData = data.map((m) => {  
134 - return {  
135 - name: m.name,  
136 - id: m.id,  
137 - };  
138 - });  
139 - return returnData;  
140 - }, 123 + api: deviceProfile,
  124 + filterOption: (inputValue: string, option: Record<'label' | 'value', string>) =>
  125 + option.label.includes(inputValue),
141 }; 126 };
142 }, 127 },
143 }, 128 },
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 @open-gateway-device="handleOpenGatewayDevice" 16 @open-gateway-device="handleOpenGatewayDevice"
17 /> 17 />
18 </TabPane> 18 </TabPane>
19 - <TabPane key="modelOfMatter" tab="物模型"> 19 + <TabPane key="modelOfMatter" tab="物模型数据">
20 <ModelOfMatter :deviceDetail="deviceDetail" /> 20 <ModelOfMatter :deviceDetail="deviceDetail" />
21 </TabPane> 21 </TabPane>
22 <!-- <TabPane key="2" tab="实时数据" v-if="deviceDetail?.deviceType !== 'GATEWAY'"> 22 <!-- <TabPane key="2" tab="实时数据" v-if="deviceDetail?.deviceType !== 'GATEWAY'">
@@ -12,7 +12,17 @@ @@ -12,7 +12,17 @@
12 <template #clientId="{ field, model }"> 12 <template #clientId="{ field, model }">
13 <div class="flex items-center"> 13 <div class="flex items-center">
14 <Input v-model:value="model[field]" placeholder="请输入客户端ID" /> 14 <Input v-model:value="model[field]" placeholder="请输入客户端ID" />
15 - <ReloadOutlined class="ml-3 !text-blue-600" @click="handleCreateUUID" /> 15 + <Tooltip title="刷新客户端ID">
  16 + <ReloadOutlined class="ml-3 !text-blue-600" @click="handleCreateUUID" />
  17 + </Tooltip>
  18 + </div>
  19 + </template>
  20 + <template #credentialsId="{ field, model }">
  21 + <div class="flex items-center">
  22 + <Input v-model:value="model[field]" placeholder="请输入访问令牌" />
  23 + <Tooltip title="刷新访问令牌">
  24 + <ReloadOutlined class="ml-3 !text-blue-600" @click="handleCreateCredentialsId" />
  25 + </Tooltip>
16 </div> 26 </div>
17 </template> 27 </template>
18 </BasicForm> 28 </BasicForm>
@@ -26,8 +36,8 @@ @@ -26,8 +36,8 @@
26 import { TokenSchemas, credentialTypeEnum } from '../../config/data'; 36 import { TokenSchemas, credentialTypeEnum } from '../../config/data';
27 import { saveDeviceToken } from '/@/api/device/deviceManager'; 37 import { saveDeviceToken } from '/@/api/device/deviceManager';
28 import { useMessage } from '/@/hooks/web/useMessage'; 38 import { useMessage } from '/@/hooks/web/useMessage';
29 - import { Input } from 'ant-design-vue';  
30 - import { buildUUID } from '/@/utils/uuid'; 39 + import { Input, Tooltip } from 'ant-design-vue';
  40 + import { buildUUID, randomString } from '/@/utils/uuid';
31 import { ReloadOutlined } from '@ant-design/icons-vue'; 41 import { ReloadOutlined } from '@ant-design/icons-vue';
32 export default defineComponent({ 42 export default defineComponent({
33 components: { 43 components: {
@@ -35,6 +45,7 @@ @@ -35,6 +45,7 @@
35 BasicForm, 45 BasicForm,
36 Input, 46 Input,
37 ReloadOutlined, 47 ReloadOutlined,
  48 + Tooltip,
38 }, 49 },
39 emits: ['register'], 50 emits: ['register'],
40 setup() { 51 setup() {
@@ -224,6 +235,10 @@ @@ -224,6 +235,10 @@
224 const handleCreateUUID = () => { 235 const handleCreateUUID = () => {
225 setFieldsValue({ clientId: buildUUID() }); 236 setFieldsValue({ clientId: buildUUID() });
226 }; 237 };
  238 +
  239 + const handleCreateCredentialsId = () => {
  240 + setFieldsValue({ credentialsId: randomString() });
  241 + };
227 return { 242 return {
228 registerModal, 243 registerModal,
229 registerForm, 244 registerForm,
@@ -231,6 +246,7 @@ @@ -231,6 +246,7 @@
231 handleCancel, 246 handleCancel,
232 handleOk, 247 handleOk,
233 handleCreateUUID, 248 handleCreateUUID,
  249 + handleCreateCredentialsId,
234 }; 250 };
235 }, 251 },
236 }); 252 });
@@ -4,6 +4,30 @@ @@ -4,6 +4,30 @@
4 <template #addAgree="{ model, field }"> 4 <template #addAgree="{ model, field }">
5 <Checkbox v-model:checked="model[field]" @change="checkedChange">添加协议</Checkbox> 5 <Checkbox v-model:checked="model[field]" @change="checkedChange">添加协议</Checkbox>
6 </template> 6 </template>
  7 + <template #clientId="{ model, field }">
  8 + <div class="flex justify-center items-center">
  9 + <Input v-model:value="model[field]" placeholder="请输入客户端ID" />
  10 + <Tooltip title="刷新客户端ID">
  11 + <Icon
  12 + class="ml-3 cursor-pointer !text-blue-600"
  13 + icon="ant-design:reload-outlined"
  14 + @click="handleGenerateClientId"
  15 + />
  16 + </Tooltip>
  17 + </div>
  18 + </template>
  19 + <template #credentialsId="{ model, field }">
  20 + <div class="flex justify-center items-center">
  21 + <Input v-model:value="model[field]" placeholder="请输入访问令牌" />
  22 + <Tooltip title="刷新访问令牌">
  23 + <Icon
  24 + class="ml-3 cursor-pointer !text-blue-600"
  25 + icon="ant-design:reload-outlined"
  26 + @click="handleGenerateCredentialsId"
  27 + />
  28 + </Tooltip>
  29 + </div>
  30 + </template>
7 </BasicForm> 31 </BasicForm>
8 <div> 32 <div>
9 <a-button @click="prevStep">上一步</a-button> 33 <a-button @click="prevStep">上一步</a-button>
@@ -13,13 +37,18 @@ @@ -13,13 +37,18 @@
13 <script lang="ts"> 37 <script lang="ts">
14 import { defineComponent } from 'vue'; 38 import { defineComponent } from 'vue';
15 39
16 - import { Checkbox } from 'ant-design-vue'; 40 + import { Checkbox, Input, Tooltip } from 'ant-design-vue';
17 import { BasicForm, useForm } from '/@/components/Form'; 41 import { BasicForm, useForm } from '/@/components/Form';
18 import { step2Schemas } from '../../config/data'; 42 import { step2Schemas } from '../../config/data';
  43 + import { Icon } from '/@/components/Icon';
  44 + import { buildUUID, randomString } from '/@/utils/uuid';
19 export default defineComponent({ 45 export default defineComponent({
20 components: { 46 components: {
21 BasicForm, 47 BasicForm,
22 Checkbox, 48 Checkbox,
  49 + Input,
  50 + Icon,
  51 + Tooltip,
23 }, 52 },
24 53
25 emits: ['prev', 'next'], 54 emits: ['prev', 'next'],
@@ -105,6 +134,14 @@ @@ -105,6 +134,14 @@
105 validate(); 134 validate();
106 } 135 }
107 136
  137 + const handleGenerateClientId = () => {
  138 + setFieldsValue({ clientId: buildUUID() });
  139 + };
  140 +
  141 + const handleGenerateCredentialsId = () => {
  142 + setFieldsValue({ credentialsId: randomString() });
  143 + };
  144 +
108 return { 145 return {
109 prevStep, 146 prevStep,
110 registerForm, 147 registerForm,
@@ -113,6 +150,8 @@ @@ -113,6 +150,8 @@
113 validate, 150 validate,
114 resetFieldsValueAndStatus, 151 resetFieldsValueAndStatus,
115 validateStep2Method, 152 validateStep2Method,
  153 + handleGenerateClientId,
  154 + handleGenerateCredentialsId,
116 }; 155 };
117 }, 156 },
118 }); 157 });
@@ -55,15 +55,23 @@ @@ -55,15 +55,23 @@
55 <a-button type="primary" class="mr-4" @click="manageDeviceToken">管理设备凭证</a-button> 55 <a-button type="primary" class="mr-4" @click="manageDeviceToken">管理设备凭证</a-button>
56 <ManageDeviceTokenModal @register="registerModal" /> 56 <ManageDeviceTokenModal @register="registerModal" />
57 </div> 57 </div>
58 - <div v-if="deviceDetail?.deviceInfo?.address" class="mt-4"> 58 + <div class="mt-4">
59 <p>设备位置</p> 59 <p>设备位置</p>
60 - <div ref="mapWrapRef" style="height: 550px; width: 100%"></div> 60 + <div v-if="deviceDetail?.deviceInfo?.address">
  61 + <div ref="mapWrapRef" style="height: 550px; width: 100%"></div>
  62 + </div>
  63 + <Empty
  64 + v-if="!deviceDetail?.deviceInfo?.address"
  65 + :image="locationImage"
  66 + :imageStyle="{ display: 'flex', 'justify-content': 'center', height: '150px' }"
  67 + description="请添加设备地理位置"
  68 + />
61 </div> 69 </div>
62 </div> 70 </div>
63 </template> 71 </template>
64 <script lang="ts"> 72 <script lang="ts">
65 import { defineComponent, ref, unref, nextTick } from 'vue'; 73 import { defineComponent, ref, unref, nextTick } from 'vue';
66 - import { Image, Tooltip } from 'ant-design-vue'; 74 + import { Empty, Image, Tooltip } from 'ant-design-vue';
67 import { descSchema } from '../../config/detail.config'; 75 import { descSchema } from '../../config/detail.config';
68 import { useAsyncScript } from '/@/hooks/web/useAsyncScript'; 76 import { useAsyncScript } from '/@/hooks/web/useAsyncScript';
69 import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard'; 77 import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
@@ -78,6 +86,8 @@ @@ -78,6 +86,8 @@
78 86
79 import wz from '/@/assets/images/wz.png'; 87 import wz from '/@/assets/images/wz.png';
80 import { useAsyncQueue } from '../../../localtion/useAsyncQueue'; 88 import { useAsyncQueue } from '../../../localtion/useAsyncQueue';
  89 + import locationImage from '/@/assets/icons/location.svg';
  90 +
81 export default defineComponent({ 91 export default defineComponent({
82 components: { 92 components: {
83 Image, 93 Image,
@@ -86,6 +96,7 @@ @@ -86,6 +96,7 @@
86 QuestionCircleOutlined, 96 QuestionCircleOutlined,
87 BasicModal, 97 BasicModal,
88 Tooltip, 98 Tooltip,
  99 + Empty,
89 }, 100 },
90 props: { 101 props: {
91 deviceDetail: { 102 deviceDetail: {
@@ -197,6 +208,7 @@ @@ -197,6 +208,7 @@
197 DeviceTypeEnum, 208 DeviceTypeEnum,
198 copyTopic, 209 copyTopic,
199 remoteConnectiondGateway, 210 remoteConnectiondGateway,
  211 + locationImage,
200 }; 212 };
201 }, 213 },
202 }); 214 });
@@ -286,7 +286,7 @@ @@ -286,7 +286,7 @@
286 setTableData(items); 286 setTableData(items);
287 const { setFieldsValue, resetFields } = getForm(); 287 const { setFieldsValue, resetFields } = getForm();
288 setFieldsValue({ 288 setFieldsValue({
289 - deviceProfileId: deviceProfileId.value, 289 + deviceProfileId: deviceProfileId.value || null,
290 }); 290 });
291 if (onCloseVal.value == 1) { 291 if (onCloseVal.value == 1) {
292 resetFields(); 292 resetFields();
@@ -2,9 +2,14 @@ @@ -2,9 +2,14 @@
2 import { PageWrapper } from '/@/components/Page'; 2 import { PageWrapper } from '/@/components/Page';
3 import { BasicForm, useForm } from '/@/components/Form'; 3 import { BasicForm, useForm } from '/@/components/Form';
4 import { List, Button, Tooltip, Card, PaginationProps, Image } from 'ant-design-vue'; 4 import { List, Button, Tooltip, Card, PaginationProps, Image } from 'ant-design-vue';
5 - import { ReloadOutlined, EyeOutlined, FormOutlined, MoreOutlined } from '@ant-design/icons-vue'; 5 + import { ReloadOutlined } from '@ant-design/icons-vue';
6 import { computed, onMounted, reactive, ref, unref } from 'vue'; 6 import { computed, onMounted, reactive, ref, unref } from 'vue';
7 - import { CardLayoutButton, EnumTableCardMode, ModeSwitchButton } from '/@/components/Widget'; 7 + import {
  8 + AuthIcon,
  9 + CardLayoutButton,
  10 + EnumTableCardMode,
  11 + ModeSwitchButton,
  12 + } from '/@/components/Widget';
8 import { Authority } from '/@/components/Authority'; 13 import { Authority } from '/@/components/Authority';
9 import { 14 import {
10 deviceConfigDelete, 15 deviceConfigDelete,
@@ -12,7 +17,6 @@ @@ -12,7 +17,6 @@
12 setDeviceProfileIsDefaultApi, 17 setDeviceProfileIsDefaultApi,
13 } from '/@/api/device/deviceConfigApi'; 18 } from '/@/api/device/deviceConfigApi';
14 import { ProfileRecord } from '/@/api/device/model/deviceConfigModel'; 19 import { ProfileRecord } from '/@/api/device/model/deviceConfigModel';
15 - import { Dropdown } from '/@/components/Dropdown';  
16 import { 20 import {
17 defaultObj, 21 defaultObj,
18 searchFormSchema, 22 searchFormSchema,
@@ -20,14 +24,13 @@ @@ -20,14 +24,13 @@
20 ProductPermission, 24 ProductPermission,
21 } from './device.profile.data'; 25 } from './device.profile.data';
22 import { useMessage } from '/@/hooks/web/useMessage'; 26 import { useMessage } from '/@/hooks/web/useMessage';
23 - import { useSyncConfirm } from '/@/hooks/component/useSyncConfirm';  
24 import DeviceProfileModal from './DeviceProfileModal.vue'; 27 import DeviceProfileModal from './DeviceProfileModal.vue';
25 import DeviceProfileDrawer from './DeviceProfileDrawer.vue'; 28 import DeviceProfileDrawer from './DeviceProfileDrawer.vue';
26 import { useModal } from '/@/components/Modal'; 29 import { useModal } from '/@/components/Modal';
27 import { useDrawer } from '/@/components/Drawer'; 30 import { useDrawer } from '/@/components/Drawer';
28 import productDefault from '/@/assets/icons/product-default.svg'; 31 import productDefault from '/@/assets/icons/product-default.svg';
29 - import { usePermission } from '/@/hooks/web/usePermission';  
30 import { useRoute } from 'vue-router'; 32 import { useRoute } from 'vue-router';
  33 + import AuthDropDown from '/@/components/Widget/AuthDropDown.vue';
31 34
32 defineProps<{ 35 defineProps<{
33 mode: EnumTableCardMode; 36 mode: EnumTableCardMode;
@@ -42,7 +45,6 @@ @@ -42,7 +45,6 @@
42 const IMAGE_FALLBACK = productDefault; 45 const IMAGE_FALLBACK = productDefault;
43 46
44 const { createMessage } = useMessage(); 47 const { createMessage } = useMessage();
45 - const { createSyncConfirm } = useSyncConfirm();  
46 48
47 const [register, { getFieldsValue, setFieldsValue }] = useForm({ 49 const [register, { getFieldsValue, setFieldsValue }] = useForm({
48 showAdvancedButton: true, 50 showAdvancedButton: true,
@@ -72,7 +74,7 @@ @@ -72,7 +74,7 @@
72 74
73 const dataSource = ref<ProfileRecord[]>([]); 75 const dataSource = ref<ProfileRecord[]>([]);
74 76
75 - const colNumber = ref(4); 77 + const colNumber = ref(5);
76 78
77 const getSelectAllFlag = computed(() => { 79 const getSelectAllFlag = computed(() => {
78 return unref(dataSource).every((item) => item.checked); 80 return unref(dataSource).every((item) => item.checked);
@@ -105,40 +107,6 @@ @@ -105,40 +107,6 @@
105 } 107 }
106 }; 108 };
107 109
108 - const { hasPermission } = usePermission();  
109 -  
110 - const getHasDeleteFlag = computed(() => {  
111 - return hasPermission(ProductPermission.DELETE);  
112 - });  
113 -  
114 - const getHasDetailFlag = computed(() => {  
115 - return hasPermission(ProductPermission.DETAIL);  
116 - });  
117 -  
118 - const getHasUpdateFlag = computed(() => {  
119 - return hasPermission(ProductPermission.UPDATE);  
120 - });  
121 -  
122 - const getDropDownList = (record: ProfileRecord) => {  
123 - const list = [  
124 - {  
125 - text: '默认',  
126 - event: DropMenuEvent.SET_DEFAULT,  
127 - icon: 'ant-design:unordered-list-outlined',  
128 - onClick: handleSetDefault.bind(null, record),  
129 - },  
130 - ];  
131 - if (unref(getHasDeleteFlag)) {  
132 - list.push({  
133 - text: '删除',  
134 - event: DropMenuEvent.DELETE,  
135 - icon: 'ant-design:delete-outlined',  
136 - onClick: handleDelete.bind(null, [record.id]),  
137 - });  
138 - }  
139 - return list;  
140 - };  
141 -  
142 const handleModeChange = (mode: EnumTableCardMode) => { 110 const handleModeChange = (mode: EnumTableCardMode) => {
143 emit('changeMode', mode); 111 emit('changeMode', mode);
144 }; 112 };
@@ -163,12 +131,10 @@ @@ -163,12 +131,10 @@
163 }; 131 };
164 132
165 const handleShowDetail = (record: ProfileRecord) => { 133 const handleShowDetail = (record: ProfileRecord) => {
166 - if (!unref(getHasDetailFlag)) return;  
167 openDrawer(true, { record }); 134 openDrawer(true, { record });
168 }; 135 };
169 136
170 const handleUpdate = (record: ProfileRecord) => { 137 const handleUpdate = (record: ProfileRecord) => {
171 - if (!unref(getHasUpdateFlag)) return;  
172 openModal(true, { 138 openModal(true, {
173 record, 139 record,
174 isUpdate: true, 140 isUpdate: true,
@@ -177,7 +143,6 @@ @@ -177,7 +143,6 @@
177 143
178 const handleDelete = async (id: string[]) => { 144 const handleDelete = async (id: string[]) => {
179 try { 145 try {
180 - await createSyncConfirm({ iconType: 'warning', content: '是否确认删除操作?' });  
181 await deviceConfigDelete(id); 146 await deviceConfigDelete(id);
182 createMessage.success('删除成功'); 147 createMessage.success('删除成功');
183 await getDataSource(); 148 await getDataSource();
@@ -268,22 +233,43 @@ @@ -268,22 +233,43 @@
268 </template> 233 </template>
269 <template class="ant-card-actions" #actions> 234 <template class="ant-card-actions" #actions>
270 <Tooltip title="详情"> 235 <Tooltip title="详情">
271 - <EyeOutlined  
272 - :class="getHasDetailFlag ? '' : '!cursor-not-allowed !text-gray-200'"  
273 - key="setting" 236 + <AuthIcon
  237 + :auth="ProductPermission.DETAIL"
  238 + class="!text-lg"
  239 + icon="ant-design:eye-outlined"
274 @click.stop="handleShowDetail(item)" 240 @click.stop="handleShowDetail(item)"
275 /> 241 />
276 </Tooltip> 242 </Tooltip>
277 <Tooltip title="编辑"> 243 <Tooltip title="编辑">
278 - <FormOutlined  
279 - :class="getHasUpdateFlag ? '' : '!cursor-not-allowed !text-gray-200'"  
280 - key="edit" 244 + <AuthIcon
  245 + :auth="ProductPermission.UPDATE"
  246 + class="!text-lg"
  247 + icon="ant-design:form-outlined"
281 @click.stop="handleUpdate(item)" 248 @click.stop="handleUpdate(item)"
282 /> 249 />
283 </Tooltip> 250 </Tooltip>
284 - <Dropdown :trigger="['hover']" :drop-menu-list="getDropDownList(item)">  
285 - <MoreOutlined @click.stop class="transform rotate-90" />  
286 - </Dropdown> 251 + <AuthDropDown
  252 + @click.stop
  253 + :trigger="['hover']"
  254 + :drop-menu-list="[
  255 + {
  256 + text: '默认',
  257 + event: DropMenuEvent.SET_DEFAULT,
  258 + icon: 'ant-design:unordered-list-outlined',
  259 + onClick: handleSetDefault.bind(null, item),
  260 + },
  261 + {
  262 + text: '删除',
  263 + event: DropMenuEvent.DELETE,
  264 + auth: ProductPermission.DELETE,
  265 + icon: 'ant-design:delete-outlined',
  266 + popconfirm: {
  267 + title: '是否确认删除操作?',
  268 + onConfirm: handleDelete.bind(null, [item.id]),
  269 + },
  270 + },
  271 + ]"
  272 + />
287 </template> 273 </template>
288 <Card.Meta> 274 <Card.Meta>
289 <template #title> 275 <template #title>
@@ -308,7 +294,10 @@ @@ -308,7 +294,10 @@
308 294
309 <style lang="less" scoped> 295 <style lang="less" scoped>
310 .profile-list:deep(.ant-image-img) { 296 .profile-list:deep(.ant-image-img) {
311 - width: 100% !important;  
312 - height: 100% !important; 297 + @apply !w-full !h-full;
  298 + }
  299 +
  300 + .profile-list:deep(.ant-card-body) {
  301 + @apply !p-4;
313 } 302 }
314 </style> 303 </style>
@@ -28,10 +28,13 @@ @@ -28,10 +28,13 @@
28 field: 'scriptName', 28 field: 'scriptName',
29 label: '转换脚本', 29 label: '转换脚本',
30 render: (value: string) => { 30 render: (value: string) => {
31 - return h('div', [  
32 - h(Tag, { color: 'blue' }, () => value),  
33 - h(Button, { type: 'link', onClick: handleTestScript }, () => '测试脚本'),  
34 - ]); 31 + return (
  32 + value &&
  33 + h('div', [
  34 + h(Tag, { color: 'blue' }, () => value),
  35 + h(Button, { type: 'link', onClick: handleTestScript }, () => '测试脚本'),
  36 + ])
  37 + );
35 }, 38 },
36 }, 39 },
37 ], 40 ],
@@ -261,12 +261,14 @@ export const columns: BasicColumn[] = [ @@ -261,12 +261,14 @@ export const columns: BasicColumn[] = [
261 title: '默认配置', 261 title: '默认配置',
262 dataIndex: 'default', 262 dataIndex: 'default',
263 width: 80, 263 width: 80,
264 - format: (text) => (text ? '是' : '否'), 264 + customRender: ({ text }) =>
  265 + text ? h(Tag, { color: 'blue' }, () => '是') : h(Tag, { color: 'red' }, () => '否'),
265 }, 266 },
266 { 267 {
267 title: '描述', 268 title: '描述',
268 dataIndex: 'description', 269 dataIndex: 'description',
269 width: 90, 270 width: 90,
  271 + ellipsis: true,
270 }, 272 },
271 { 273 {
272 title: '创建时间', 274 title: '创建时间',
@@ -8,7 +8,9 @@ @@ -8,7 +8,9 @@
8 placeholder="请选择转换脚本" 8 placeholder="请选择转换脚本"
9 v-model:value="selectScript.script" 9 v-model:value="selectScript.script"
10 style="width: 305px" 10 style="width: 305px"
  11 + show-search
11 :options="selectOptions" 12 :options="selectOptions"
  13 + :filter-option="handleSearch"
12 allowClear 14 allowClear
13 /> 15 />
14 </div> 16 </div>
@@ -113,6 +115,11 @@ @@ -113,6 +115,11 @@
113 const setFormData = (v) => { 115 const setFormData = (v) => {
114 selectScript.script = v?.scriptId; 116 selectScript.script = v?.scriptId;
115 }; 117 };
  118 +
  119 + const handleSearch = (inputValue: string, option: Record<'label' | 'value', string>) => {
  120 + return option.label.includes(inputValue);
  121 + };
  122 +
116 defineExpose({ 123 defineExpose({
117 getFormData, 124 getFormData,
118 resetFormData, 125 resetFormData,
@@ -16,6 +16,14 @@ @@ -16,6 +16,14 @@
16 <TableAction 16 <TableAction
17 :actions="[ 17 :actions="[
18 { 18 {
  19 + label: '进入',
  20 + icon: 'ant-design:login-outlined',
  21 + tooltip: '以租户管理员身份登录',
  22 + onClick: handleLoginTenantAdmin.bind(null, record),
  23 + },
  24 + ]"
  25 + :drop-down-actions="[
  26 + {
19 label: '短信通知', 27 label: '短信通知',
20 icon: 'ant-design:send-outlined', 28 icon: 'ant-design:send-outlined',
21 tooltip: '发送通知短信', 29 tooltip: '发送通知短信',
@@ -94,6 +102,12 @@ @@ -94,6 +102,12 @@
94 import { MessageTypeEnum, SendResetPasswordEmailMsg } from '/@/api/tenant/tenantInfo'; 102 import { MessageTypeEnum, SendResetPasswordEmailMsg } from '/@/api/tenant/tenantInfo';
95 import { useMessage } from '/@/hooks/web/useMessage'; 103 import { useMessage } from '/@/hooks/web/useMessage';
96 import { Authority } from '/@/components/Authority'; 104 import { Authority } from '/@/components/Authority';
  105 + import { getMyInfo, getPermCode, getUserToken } from '/@/api/sys/user';
  106 + import { useUserStore } from '/@/store/modules/user';
  107 + import { usePermissionStore } from '/@/store/modules/permission';
  108 + import { RoleEnum } from '/@/enums/roleEnum';
  109 + import { useGo } from '/@/hooks/web/usePage';
  110 + import { PageEnum } from '/@/enums/pageEnum';
97 111
98 export default defineComponent({ 112 export default defineComponent({
99 name: 'TenantAdminDrawer', 113 name: 'TenantAdminDrawer',
@@ -198,10 +212,15 @@ @@ -198,10 +212,15 @@
198 fixed: 'right', 212 fixed: 'right',
199 }, 213 },
200 }); 214 });
  215 +
  216 + let firstEnterFlag = true;
201 //默认传递页面数据 217 //默认传递页面数据
202 const [tenantAdminDrawer, { closeDrawer }] = useDrawerInner(async (data) => { 218 const [tenantAdminDrawer, { closeDrawer }] = useDrawerInner(async (data) => {
203 tenantId.value = data.record.tenantId; 219 tenantId.value = data.record.tenantId;
204 - reload(); 220 + !firstEnterFlag && reload();
  221 + if (firstEnterFlag) {
  222 + firstEnterFlag = false;
  223 + }
205 }); 224 });
206 225
207 //提交按钮 226 //提交按钮
@@ -213,6 +232,24 @@ @@ -213,6 +232,24 @@
213 reload(); 232 reload();
214 } 233 }
215 234
  235 + const userStore = useUserStore();
  236 + const permissionStore = usePermissionStore();
  237 + const go = useGo();
  238 + async function handleLoginTenantAdmin(record: { tbUser: string; id: string }) {
  239 + try {
  240 + const { token, refreshToken } = await getUserToken(record.id);
  241 + userStore.storeToken(token, refreshToken);
  242 + const userInfo = await getMyInfo();
  243 + const permissionList = await getPermCode();
  244 + permissionStore.setPermCodeList(permissionList);
  245 + userStore.setUserInfo(userInfo);
  246 + userStore.setRoleList(userInfo.roles as RoleEnum[]);
  247 + go(PageEnum.BASE_HOME);
  248 + } catch (error) {
  249 + } finally {
  250 + }
  251 + }
  252 +
216 return { 253 return {
217 tenantAdminDrawer, 254 tenantAdminDrawer,
218 handleCreateTenantAdmin, 255 handleCreateTenantAdmin,
@@ -225,6 +262,7 @@ @@ -225,6 +262,7 @@
225 handleDelete, 262 handleDelete,
226 handleResetPassword, 263 handleResetPassword,
227 handleSendMsg, 264 handleSendMsg,
  265 + handleLoginTenantAdmin,
228 }; 266 };
229 }, 267 },
230 }); 268 });
@@ -72,7 +72,9 @@ @@ -72,7 +72,9 @@
72 > 72 >
73 <Tooltip :title="item.deviceName" placement="topLeft"> 73 <Tooltip :title="item.deviceName" placement="topLeft">
74 <div class="flex p-1"> 74 <div class="flex p-1">
75 - <div class="truncate font-bold">{{ item.deviceRename || item.deviceName }}</div> 75 + <div v-if="item.componentInfo.showDeviceName" class="truncate font-bold">
  76 + {{ item.deviceRename || item.deviceName }}
  77 + </div>
76 </div> 78 </div>
77 </Tooltip> 79 </Tooltip>
78 </div> 80 </div>
@@ -33,7 +33,7 @@ @@ -33,7 +33,7 @@
33 return decode((ROUTE.params as DataComponentRouteParams).boardId as string); 33 return decode((ROUTE.params as DataComponentRouteParams).boardId as string);
34 }); 34 });
35 35
36 - const frontId = ref(FrontComponent.TEXT_COMPONENT_1); 36 + const frontId = ref();
37 37
38 const isEdit = ref(false); 38 const isEdit = ref(false);
39 39
@@ -48,6 +48,7 @@ @@ -48,6 +48,7 @@
48 const [register, { closeModal, changeOkLoading }] = useModalInner( 48 const [register, { closeModal, changeOkLoading }] = useModalInner(
49 (data: { isEdit: boolean; record?: DataBoardLayoutInfo }) => { 49 (data: { isEdit: boolean; record?: DataBoardLayoutInfo }) => {
50 componentRecord.value = data.record || ({} as unknown as DataBoardLayoutInfo); 50 componentRecord.value = data.record || ({} as unknown as DataBoardLayoutInfo);
  51 + if (!unref(isEdit)) frontId.value = FrontComponent.TEXT_COMPONENT_1;
51 frontId.value = 52 frontId.value =
52 (data.record?.record?.frontId as FrontComponent) || FrontComponent.TEXT_COMPONENT_1; 53 (data.record?.record?.frontId as FrontComponent) || FrontComponent.TEXT_COMPONENT_1;
53 isEdit.value = data.isEdit || false; 54 isEdit.value = data.isEdit || false;
1 <script lang="ts" setup> 1 <script lang="ts" setup>
2 - import { ref, onMounted, unref } from 'vue'; 2 + import { ref, onMounted, unref, computed } from 'vue';
3 import { FrontComponent } from '../../../const/const'; 3 import { FrontComponent } from '../../../const/const';
4 import { DataSourceField, dataSourceSchema } from '../../config/basicConfiguration'; 4 import { DataSourceField, dataSourceSchema } from '../../config/basicConfiguration';
5 import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; 5 import { DeviceTypeEnum } from '/@/api/device/model/deviceModel';
@@ -7,12 +7,18 @@ @@ -7,12 +7,18 @@
7 import BasicForm from '/@/components/Form/src/BasicForm.vue'; 7 import BasicForm from '/@/components/Form/src/BasicForm.vue';
8 const formEl = ref<Nullable<FormActionType>>(null); 8 const formEl = ref<Nullable<FormActionType>>(null);
9 9
10 - defineProps<{ 10 + const props = defineProps<{
11 frontId?: FrontComponent; 11 frontId?: FrontComponent;
12 }>(); 12 }>();
13 13
14 defineExpose({ formActionType: formEl }); 14 defineExpose({ formActionType: formEl });
15 15
  16 + const getDataSchema = computed(() => {
  17 + const { frontId } = props;
  18 + if (!frontId) return [];
  19 + return dataSourceSchema(frontId);
  20 + });
  21 +
16 onMounted(() => { 22 onMounted(() => {
17 unref(formEl)?.setFieldsValue({ [DataSourceField.DEVICE_TYPE]: DeviceTypeEnum.SENSOR }); 23 unref(formEl)?.setFieldsValue({ [DataSourceField.DEVICE_TYPE]: DeviceTypeEnum.SENSOR });
18 }); 24 });
@@ -21,7 +27,7 @@ @@ -21,7 +27,7 @@
21 <template> 27 <template>
22 <BasicForm 28 <BasicForm
23 ref="formEl" 29 ref="formEl"
24 - :schemas="dataSourceSchema($props.frontId)" 30 + :schemas="getDataSchema"
25 class="w-full flex-1 data-source-form" 31 class="w-full flex-1 data-source-form"
26 :show-action-button-group="false" 32 :show-action-button-group="false"
27 :row-props="{ 33 :row-props="{
@@ -61,6 +61,7 @@ @@ -61,6 +61,7 @@
61 icon: value.icon || null, 61 icon: value.icon || null,
62 iconColor: value.iconColor || null, 62 iconColor: value.iconColor || null,
63 unit: value.unit || null, 63 unit: value.unit || null,
  64 + showDeviceName: value.showDeviceName,
64 gradientInfo: [ 65 gradientInfo: [
65 { key: Gradient.FIRST, value: value.firstPhaseValue, color: value.firstPhaseColor }, 66 { key: Gradient.FIRST, value: value.firstPhaseValue, color: value.firstPhaseColor },
66 { key: Gradient.SECOND, value: value.secondPhaseValue, color: value.secondPhaseColor }, 67 { key: Gradient.SECOND, value: value.secondPhaseValue, color: value.secondPhaseColor },
@@ -149,6 +149,7 @@ export const dataSourceSchema = (frontId?: FrontComponent): FormSchema[] => { @@ -149,6 +149,7 @@ export const dataSourceSchema = (frontId?: FrontComponent): FormSchema[] => {
149 const { setFieldsValue } = formActionType; 149 const { setFieldsValue } = formActionType;
150 const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID]; 150 const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID];
151 const deviceType = formModel[DataSourceField.DEVICE_TYPE]; 151 const deviceType = formModel[DataSourceField.DEVICE_TYPE];
  152 + if (![deviceType, deviceProfileId].every(Boolean)) return {};
152 return { 153 return {
153 api: async () => { 154 api: async () => {
154 if (!deviceType) return []; 155 if (!deviceType) return [];
@@ -253,6 +254,7 @@ export const dataSourceSchema = (frontId?: FrontComponent): FormSchema[] => { @@ -253,6 +254,7 @@ export const dataSourceSchema = (frontId?: FrontComponent): FormSchema[] => {
253 componentProps({ formModel }) { 254 componentProps({ formModel }) {
254 const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID]; 255 const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID];
255 const transportType = formModel[DataSourceField.TRANSPORT_TYPE]; 256 const transportType = formModel[DataSourceField.TRANSPORT_TYPE];
  257 + if (![deviceProfileId, transportType].every(Boolean)) return {};
256 return { 258 return {
257 api: async () => { 259 api: async () => {
258 try { 260 try {
@@ -12,6 +12,7 @@ export interface VisualOptionParams { @@ -12,6 +12,7 @@ export interface VisualOptionParams {
12 [visualOptionField.FIRST_PHASE_VALUE]: string; 12 [visualOptionField.FIRST_PHASE_VALUE]: string;
13 [visualOptionField.SECOND_PHASE_VALUE]: string; 13 [visualOptionField.SECOND_PHASE_VALUE]: string;
14 [visualOptionField.THIRD_PHASE_VALUE]: string; 14 [visualOptionField.THIRD_PHASE_VALUE]: string;
  15 + [visualOptionField.SHOW_DEVICE_NAME]: string;
15 } 16 }
16 17
17 export enum visualOptionField { 18 export enum visualOptionField {
@@ -25,6 +26,7 @@ export enum visualOptionField { @@ -25,6 +26,7 @@ export enum visualOptionField {
25 FIRST_PHASE_VALUE = 'firstPhaseValue', 26 FIRST_PHASE_VALUE = 'firstPhaseValue',
26 SECOND_PHASE_VALUE = 'secondPhaseValue', 27 SECOND_PHASE_VALUE = 'secondPhaseValue',
27 THIRD_PHASE_VALUE = 'thirdPhaseValue', 28 THIRD_PHASE_VALUE = 'thirdPhaseValue',
  29 + SHOW_DEVICE_NAME = 'showDeviceName',
28 } 30 }
29 31
30 export const modeOne: FormSchema[] = [ 32 export const modeOne: FormSchema[] = [
@@ -37,6 +39,11 @@ export const modeOne: FormSchema[] = [ @@ -37,6 +39,11 @@ export const modeOne: FormSchema[] = [
37 defaultValue: '#000', 39 defaultValue: '#000',
38 }, 40 },
39 }, 41 },
  42 + {
  43 + field: visualOptionField.SHOW_DEVICE_NAME,
  44 + label: '显示设备名称',
  45 + component: 'Checkbox',
  46 + },
40 ]; 47 ];
41 48
42 export const modeTwo: FormSchema[] = [ 49 export const modeTwo: FormSchema[] = [
@@ -78,6 +85,11 @@ export const modeTwo: FormSchema[] = [ @@ -78,6 +85,11 @@ export const modeTwo: FormSchema[] = [
78 }; 85 };
79 }, 86 },
80 }, 87 },
  88 + {
  89 + field: visualOptionField.SHOW_DEVICE_NAME,
  90 + label: '显示设备名称',
  91 + component: 'Checkbox',
  92 + },
81 ]; 93 ];
82 94
83 export const modeThree: FormSchema[] = [ 95 export const modeThree: FormSchema[] = [
@@ -156,6 +168,11 @@ export const modeThree: FormSchema[] = [ @@ -156,6 +168,11 @@ export const modeThree: FormSchema[] = [
156 }; 168 };
157 }, 169 },
158 }, 170 },
  171 + {
  172 + field: visualOptionField.SHOW_DEVICE_NAME,
  173 + label: '显示设备名称',
  174 + component: 'Checkbox',
  175 + },
159 ]; 176 ];
160 177
161 export const modeFour: FormSchema[] = [ 178 export const modeFour: FormSchema[] = [
@@ -176,6 +193,11 @@ export const modeFour: FormSchema[] = [ @@ -176,6 +193,11 @@ export const modeFour: FormSchema[] = [
176 placeholder: '请输入数值单位', 193 placeholder: '请输入数值单位',
177 }, 194 },
178 }, 195 },
  196 + {
  197 + field: visualOptionField.SHOW_DEVICE_NAME,
  198 + label: '显示设备名称',
  199 + component: 'Checkbox',
  200 + },
179 ]; 201 ];
180 202
181 export const modeFive: FormSchema[] = [ 203 export const modeFive: FormSchema[] = [
@@ -209,6 +231,11 @@ export const modeFive: FormSchema[] = [ @@ -209,6 +231,11 @@ export const modeFive: FormSchema[] = [
209 }; 231 };
210 }, 232 },
211 }, 233 },
  234 + {
  235 + field: visualOptionField.SHOW_DEVICE_NAME,
  236 + label: '显示设备名称',
  237 + component: 'Checkbox',
  238 + },
212 ]; 239 ];
213 240
214 export const schemasMap = new Map<FrontComponent, FormSchema[]>(); 241 export const schemasMap = new Map<FrontComponent, FormSchema[]>();