Commit 226aff840e1ae30fd8ffc56607022103c1e96d08

Authored by xp.Huang
2 parents 8e597b2e 1ea0731f

Merge branch 'ww' into 'main'

feat: add AuthIcon component replace ant-design icon

See merge request huang/yun-teng-iot-front!451
  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 1 export { default as ModeSwitchButton } from './ModeSwitchButton.vue';
2 2 export { default as CardLayoutButton } from './CardLayoutButton.vue';
  3 +export { default as AuthIcon } from './AuthIcon.vue';
3 4 export {
4 5 EnumTableCardMode,
5 6 EnumTableChartMode,
... ...
... ... @@ -26,3 +26,26 @@ export function buildShortUUID(prefix = ''): string {
26 26 unique++;
27 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 1 <script setup lang="ts">
2 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 4 import { computed, onMounted, reactive, ref, unref } from 'vue';
11 5 import { OrganizationIdTree, useResetOrganizationTree } from '../../common/organizationIdTree';
12 6 import {
... ... @@ -15,7 +9,6 @@
15 9 } from '/@/api/configuration/center/configurationCenter';
16 10 import { ConfigurationCenterItemsModal } from '/@/api/configuration/center/model/configurationCenterModal';
17 11 import { PageWrapper } from '/@/components/Page';
18   - import { Dropdown } from '/@/components/Dropdown';
19 12 import { BasicForm, useForm } from '/@/components/Form';
20 13 import { ConfigurationPermission, searchFormSchema } from './center.data';
21 14 import { useMessage } from '/@/hooks/web/useMessage';
... ... @@ -23,12 +16,13 @@
23 16 import { isDevMode } from '/@/utils/env';
24 17 import ConfigurationCenterDrawer from './ConfigurationCenterDrawer.vue';
25 18 import { useDrawer } from '/@/components/Drawer';
26   - import { useSyncConfirm } from '/@/hooks/component/useSyncConfirm';
27 19 import { getBoundingClientRect } from '/@/utils/domUtils';
28 20 import configurationSrc from '/@/assets/icons/configuration.svg';
29 21 import { cloneDeep } from 'lodash';
30 22 import { usePermission } from '/@/hooks/web/usePermission';
31 23 import { useGlobSetting } from '/@/hooks/setting';
  24 + import { AuthIcon } from '/@/components/Widget';
  25 + import AuthDropDown from '/@/components/Widget/AuthDropDown.vue';
32 26
33 27 const listColumn = ref(5);
34 28
... ... @@ -136,10 +130,8 @@
136 130 window.open(`${configurationPrefix}/${isDev ? '?dev=1&' : '?'}configurationId=${record!.id}`);
137 131 };
138 132
139   - const { createSyncConfirm } = useSyncConfirm();
140 133 const handleDelete = async (record: ConfigurationCenterItemsModal) => {
141 134 try {
142   - await createSyncConfirm({ iconType: 'warning', content: '是否确认删除操作?' });
143 135 await deleteConfigurationCenter([record.id]);
144 136 createMessage.success('删除成功');
145 137 await getListData();
... ... @@ -227,20 +219,44 @@
227 219 </template>
228 220 <template class="ant-card-actions" #actions>
229 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 226 @click="handlePreview(item)"
234 227 />
235 228 </Tooltip>
236 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 234 @click="handleDesign(item)"
241 235 />
242 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 260 :dropMenuList="[
245 261 {
246 262 text: '编辑',
... ... @@ -261,7 +277,7 @@
261 277 :trigger="['hover']"
262 278 >
263 279 <EllipsisOutlined key="ellipsis" />
264   - </Dropdown>
  280 + </Dropdown> -->
265 281 </template>
266 282 <Card.Meta>
267 283 <template #title>
... ...
... ... @@ -399,6 +399,7 @@ export const step2Schemas: FormSchema[] = [
399 399 field: 'credentialsId',
400 400 required: true,
401 401 ifShow: false,
  402 + slot: 'credentialsId',
402 403 componentProps: {
403 404 maxLength: 36,
404 405 placeholder: '请输入访问令牌',
... ... @@ -421,6 +422,7 @@ export const step2Schemas: FormSchema[] = [
421 422 field: 'clientId',
422 423 required: true,
423 424 ifShow: false,
  425 + slot: 'clientId',
424 426 componentProps: {
425 427 maxLength: 36,
426 428 placeholder: '请输入客户端ID',
... ... @@ -597,6 +599,7 @@ export const TokenSchemas: FormSchema[] = [
597 599 field: 'credentialsId',
598 600 required: true,
599 601 ifShow: false,
  602 + slot: 'credentialsId',
600 603 componentProps: {
601 604 maxLength: 36,
602 605 placeholder: '请输入访问令牌',
... ...
... ... @@ -12,7 +12,17 @@
12 12 <template #clientId="{ field, model }">
13 13 <div class="flex items-center">
14 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 26 </div>
17 27 </template>
18 28 </BasicForm>
... ... @@ -26,8 +36,8 @@
26 36 import { TokenSchemas, credentialTypeEnum } from '../../config/data';
27 37 import { saveDeviceToken } from '/@/api/device/deviceManager';
28 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 41 import { ReloadOutlined } from '@ant-design/icons-vue';
32 42 export default defineComponent({
33 43 components: {
... ... @@ -35,6 +45,7 @@
35 45 BasicForm,
36 46 Input,
37 47 ReloadOutlined,
  48 + Tooltip,
38 49 },
39 50 emits: ['register'],
40 51 setup() {
... ... @@ -224,6 +235,10 @@
224 235 const handleCreateUUID = () => {
225 236 setFieldsValue({ clientId: buildUUID() });
226 237 };
  238 +
  239 + const handleCreateCredentialsId = () => {
  240 + setFieldsValue({ credentialsId: randomString() });
  241 + };
227 242 return {
228 243 registerModal,
229 244 registerForm,
... ... @@ -231,6 +246,7 @@
231 246 handleCancel,
232 247 handleOk,
233 248 handleCreateUUID,
  249 + handleCreateCredentialsId,
234 250 };
235 251 },
236 252 });
... ...
... ... @@ -4,6 +4,30 @@
4 4 <template #addAgree="{ model, field }">
5 5 <Checkbox v-model:checked="model[field]" @change="checkedChange">添加协议</Checkbox>
6 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 31 </BasicForm>
8 32 <div>
9 33 <a-button @click="prevStep">上一步</a-button>
... ... @@ -13,13 +37,18 @@
13 37 <script lang="ts">
14 38 import { defineComponent } from 'vue';
15 39
16   - import { Checkbox } from 'ant-design-vue';
  40 + import { Checkbox, Input, Tooltip } from 'ant-design-vue';
17 41 import { BasicForm, useForm } from '/@/components/Form';
18 42 import { step2Schemas } from '../../config/data';
  43 + import { Icon } from '/@/components/Icon';
  44 + import { buildUUID, randomString } from '/@/utils/uuid';
19 45 export default defineComponent({
20 46 components: {
21 47 BasicForm,
22 48 Checkbox,
  49 + Input,
  50 + Icon,
  51 + Tooltip,
23 52 },
24 53
25 54 emits: ['prev', 'next'],
... ... @@ -105,6 +134,14 @@
105 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 145 return {
109 146 prevStep,
110 147 registerForm,
... ... @@ -113,6 +150,8 @@
113 150 validate,
114 151 resetFieldsValueAndStatus,
115 152 validateStep2Method,
  153 + handleGenerateClientId,
  154 + handleGenerateCredentialsId,
116 155 };
117 156 },
118 157 });
... ...
... ... @@ -55,15 +55,23 @@
55 55 <a-button type="primary" class="mr-4" @click="manageDeviceToken">管理设备凭证</a-button>
56 56 <ManageDeviceTokenModal @register="registerModal" />
57 57 </div>
58   - <div v-if="deviceDetail?.deviceInfo?.address" class="mt-4">
  58 + <div class="mt-4">
59 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 69 </div>
62 70 </div>
63 71 </template>
64 72 <script lang="ts">
65 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 75 import { descSchema } from '../../config/detail.config';
68 76 import { useAsyncScript } from '/@/hooks/web/useAsyncScript';
69 77 import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
... ... @@ -78,6 +86,8 @@
78 86
79 87 import wz from '/@/assets/images/wz.png';
80 88 import { useAsyncQueue } from '../../../localtion/useAsyncQueue';
  89 + import locationImage from '/@/assets/icons/location.svg';
  90 +
81 91 export default defineComponent({
82 92 components: {
83 93 Image,
... ... @@ -86,6 +96,7 @@
86 96 QuestionCircleOutlined,
87 97 BasicModal,
88 98 Tooltip,
  99 + Empty,
89 100 },
90 101 props: {
91 102 deviceDetail: {
... ... @@ -197,6 +208,7 @@
197 208 DeviceTypeEnum,
198 209 copyTopic,
199 210 remoteConnectiondGateway,
  211 + locationImage,
200 212 };
201 213 },
202 214 });
... ...
... ... @@ -2,9 +2,14 @@
2 2 import { PageWrapper } from '/@/components/Page';
3 3 import { BasicForm, useForm } from '/@/components/Form';
4 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 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 13 import { Authority } from '/@/components/Authority';
9 14 import {
10 15 deviceConfigDelete,
... ... @@ -12,7 +17,6 @@
12 17 setDeviceProfileIsDefaultApi,
13 18 } from '/@/api/device/deviceConfigApi';
14 19 import { ProfileRecord } from '/@/api/device/model/deviceConfigModel';
15   - import { Dropdown } from '/@/components/Dropdown';
16 20 import {
17 21 defaultObj,
18 22 searchFormSchema,
... ... @@ -20,14 +24,13 @@
20 24 ProductPermission,
21 25 } from './device.profile.data';
22 26 import { useMessage } from '/@/hooks/web/useMessage';
23   - import { useSyncConfirm } from '/@/hooks/component/useSyncConfirm';
24 27 import DeviceProfileModal from './DeviceProfileModal.vue';
25 28 import DeviceProfileDrawer from './DeviceProfileDrawer.vue';
26 29 import { useModal } from '/@/components/Modal';
27 30 import { useDrawer } from '/@/components/Drawer';
28 31 import productDefault from '/@/assets/icons/product-default.svg';
29   - import { usePermission } from '/@/hooks/web/usePermission';
30 32 import { useRoute } from 'vue-router';
  33 + import AuthDropDown from '/@/components/Widget/AuthDropDown.vue';
31 34
32 35 defineProps<{
33 36 mode: EnumTableCardMode;
... ... @@ -42,7 +45,6 @@
42 45 const IMAGE_FALLBACK = productDefault;
43 46
44 47 const { createMessage } = useMessage();
45   - const { createSyncConfirm } = useSyncConfirm();
46 48
47 49 const [register, { getFieldsValue, setFieldsValue }] = useForm({
48 50 showAdvancedButton: true,
... ... @@ -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 110 const handleModeChange = (mode: EnumTableCardMode) => {
143 111 emit('changeMode', mode);
144 112 };
... ... @@ -163,12 +131,10 @@
163 131 };
164 132
165 133 const handleShowDetail = (record: ProfileRecord) => {
166   - if (!unref(getHasDetailFlag)) return;
167 134 openDrawer(true, { record });
168 135 };
169 136
170 137 const handleUpdate = (record: ProfileRecord) => {
171   - if (!unref(getHasUpdateFlag)) return;
172 138 openModal(true, {
173 139 record,
174 140 isUpdate: true,
... ... @@ -177,7 +143,6 @@
177 143
178 144 const handleDelete = async (id: string[]) => {
179 145 try {
180   - await createSyncConfirm({ iconType: 'warning', content: '是否确认删除操作?' });
181 146 await deviceConfigDelete(id);
182 147 createMessage.success('删除成功');
183 148 await getDataSource();
... ... @@ -268,22 +233,43 @@
268 233 </template>
269 234 <template class="ant-card-actions" #actions>
270 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 240 @click.stop="handleShowDetail(item)"
275 241 />
276 242 </Tooltip>
277 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 248 @click.stop="handleUpdate(item)"
282 249 />
283 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 273 </template>
288 274 <Card.Meta>
289 275 <template #title>
... ... @@ -308,7 +294,10 @@
308 294
309 295 <style lang="less" scoped>
310 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 303 </style>
... ...
... ... @@ -28,10 +28,13 @@
28 28 field: 'scriptName',
29 29 label: '转换脚本',
30 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 261 title: '默认配置',
262 262 dataIndex: 'default',
263 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 268 title: '描述',
268 269 dataIndex: 'description',
269 270 width: 90,
  271 + ellipsis: true,
270 272 },
271 273 {
272 274 title: '创建时间',
... ...
... ... @@ -8,7 +8,9 @@
8 8 placeholder="请选择转换脚本"
9 9 v-model:value="selectScript.script"
10 10 style="width: 305px"
  11 + show-search
11 12 :options="selectOptions"
  13 + :filter-option="handleSearch"
12 14 allowClear
13 15 />
14 16 </div>
... ... @@ -113,6 +115,11 @@
113 115 const setFormData = (v) => {
114 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 123 defineExpose({
117 124 getFormData,
118 125 resetFormData,
... ...