Commit ea33b4b91bc25be8ad2b15a8b2825e7436c959d7

Authored by xp.Huang
2 parents 690b31fc 292e0ae7

Merge branch 'ww' into 'main'

fix: BUG in teambition

See merge request huang/yun-teng-iot-front!377
Showing 37 changed files with 729 additions and 289 deletions
1 import { defHttp } from '/@/utils/http/axios'; 1 import { defHttp } from '/@/utils/http/axios';
2 import type { 2 import type {
3 queryPageParams, 3 queryPageParams,
4 - ConfigurationModal,  
5 ConfigurationCenterParams, 4 ConfigurationCenterParams,
6 ConfigurationCenterInfo, 5 ConfigurationCenterInfo,
  6 + ConfigurationCenterItemsModal,
7 } from './model/configurationCenterModal'; 7 } from './model/configurationCenterModal';
8 import { getPageData } from '../../base'; 8 import { getPageData } from '../../base';
9 enum API { 9 enum API {
@@ -11,7 +11,7 @@ enum API { @@ -11,7 +11,7 @@ enum API {
11 } 11 }
12 12
13 export const getPage = (params: queryPageParams) => { 13 export const getPage = (params: queryPageParams) => {
14 - return getPageData<ConfigurationModal>(params, API.basicUrl); 14 + return getPageData<ConfigurationCenterItemsModal>(params, API.basicUrl);
15 }; 15 };
16 16
17 export const saveConfigurationCenter = (params: ConfigurationCenterParams) => { 17 export const saveConfigurationCenter = (params: ConfigurationCenterParams) => {
1 import { BasicPageParams } from '/@/api/model/baseModel'; 1 import { BasicPageParams } from '/@/api/model/baseModel';
2 -import { ContactParams } from '/@/api/alarm/contact/model/alarmContactModal';  
3 2
4 -interface ConfigurationCenterItemsModal { 3 +export interface ConfigurationCenterItemsModal {
5 id: string; 4 id: string;
6 name: string; 5 name: string;
7 createTime: string; 6 createTime: string;
8 creator: string; 7 creator: string;
9 remark: string; 8 remark: string;
10 } 9 }
11 -export type queryPageParams = BasicPageParams & { name: string; organizationId: string }; 10 +export type queryPageParams = BasicPageParams & {
  11 + name?: Nullable<string>;
  12 + organizationId?: Nullable<number>;
  13 +};
12 14
13 export interface ConfigurationModal { 15 export interface ConfigurationModal {
14 items: ConfigurationCenterItemsModal[]; 16 items: ConfigurationCenterItemsModal[];
@@ -12,5 +12,5 @@ export const PageEnum = { @@ -12,5 +12,5 @@ export const PageEnum = {
12 //消息配置 12 //消息配置
13 MESSAGE_CONFIG: '/message/config', 13 MESSAGE_CONFIG: '/message/config',
14 //设备配置 14 //设备配置
15 - DEVICE_PROFILE: '/device/profiles', 15 + DEVICE_PROFILE: '/product/profiles',
16 }; 16 };
@@ -47,8 +47,8 @@ export default defineComponent({ @@ -47,8 +47,8 @@ export default defineComponent({
47 const { 47 const {
48 getContentMode, 48 getContentMode,
49 getShowFooter, 49 getShowFooter,
50 - getShowBreadCrumb,  
51 - getShowBreadCrumbIcon, 50 + // getShowBreadCrumb,
  51 + // getShowBreadCrumbIcon,
52 getShowLogo, 52 getShowLogo,
53 getFullContent, 53 getFullContent,
54 getColorWeak, 54 getColorWeak,
@@ -281,7 +281,7 @@ export default defineComponent({ @@ -281,7 +281,7 @@ export default defineComponent({
281 function renderContent() { 281 function renderContent() {
282 return ( 282 return (
283 <> 283 <>
284 - <SwitchItem 284 + {/* <SwitchItem
285 title={t('layout.setting.breadcrumb')} 285 title={t('layout.setting.breadcrumb')}
286 event={HandlerEnum.SHOW_BREADCRUMB} 286 event={HandlerEnum.SHOW_BREADCRUMB}
287 def={unref(getShowBreadCrumb)} 287 def={unref(getShowBreadCrumb)}
@@ -299,7 +299,7 @@ export default defineComponent({ @@ -299,7 +299,7 @@ export default defineComponent({
299 title={t('layout.setting.tabs')} 299 title={t('layout.setting.tabs')}
300 event={HandlerEnum.TABS_SHOW} 300 event={HandlerEnum.TABS_SHOW}
301 def={unref(getShowMultipleTab)} 301 def={unref(getShowMultipleTab)}
302 - /> 302 + /> */}
303 303
304 <SwitchItem 304 <SwitchItem
305 title={t('layout.setting.tabsRedoBtn')} 305 title={t('layout.setting.tabsRedoBtn')}
@@ -17,7 +17,7 @@ export default { @@ -17,7 +17,7 @@ export default {
17 device: { 17 device: {
18 deviceManagement: '设备管理', 18 deviceManagement: '设备管理',
19 device: '设备列表', 19 device: '设备列表',
20 - deviceProfile: '设备配置', 20 + product: '产品',
21 }, 21 },
22 22
23 tenant: { 23 tenant: {
@@ -250,7 +250,7 @@ export const DeviceProfileIdMaxLength: Rule[] = [ @@ -250,7 +250,7 @@ export const DeviceProfileIdMaxLength: Rule[] = [
250 required: true, 250 required: true,
251 validator: (_, value: string) => { 251 validator: (_, value: string) => {
252 if (String(value).length > 36) { 252 if (String(value).length > 36) {
253 - return Promise.reject('设备配置长度不超过36字'); 253 + return Promise.reject('所属产品长度不超过36字');
254 } 254 }
255 return Promise.resolve(); 255 return Promise.resolve();
256 }, 256 },
@@ -22,8 +22,8 @@ export enum AlarmPermissionKey { @@ -22,8 +22,8 @@ export enum AlarmPermissionKey {
22 export function useAlarmNotify(params: UseAlarmNotifyParams = {}) { 22 export function useAlarmNotify(params: UseAlarmNotifyParams = {}) {
23 const { 23 const {
24 alarmNotifyStatus = AlarmStatus.ACTIVE_UN_ACK, 24 alarmNotifyStatus = AlarmStatus.ACTIVE_UN_ACK,
25 - interval = import.meta.env.VITE_ALARM_NOTIFY_POLLING_INTERVAL_TIME,  
26 - duration = import.meta.env.VITE_ALARM_NOTIFY_DURATION, 25 + interval = import.meta.env.VITE_ALARM_NOTIFY_POLLING_INTERVAL_TIME || 60000,
  26 + duration = import.meta.env.VITE_ALARM_NOTIFY_DURATION || 5,
27 color = 'orange', 27 color = 'orange',
28 } = params; 28 } = params;
29 const alarmNotifyStatusMean = AlarmStatusMean[alarmNotifyStatus]; 29 const alarmNotifyStatusMean = AlarmStatusMean[alarmNotifyStatus];
@@ -59,6 +59,8 @@ @@ -59,6 +59,8 @@
59 icon: 'clarity:note-edit-line', 59 icon: 'clarity:note-edit-line',
60 onClick: handleCreateOrEdit.bind(null, record), 60 onClick: handleCreateOrEdit.bind(null, record),
61 }, 61 },
  62 + ]"
  63 + :drop-down-actions="[
62 { 64 {
63 label: '删除', 65 label: '删除',
64 auth: 'api:yt:video:delete', 66 auth: 'api:yt:video:delete',
1 <script setup lang="ts"> 1 <script setup lang="ts">
2 import { PageWrapper } from '/@/components/Page'; 2 import { PageWrapper } from '/@/components/Page';
3 import OrganizationIdTree from '../../common/organizationIdTree/src/OrganizationIdTree.vue'; 3 import OrganizationIdTree from '../../common/organizationIdTree/src/OrganizationIdTree.vue';
4 - import { computed, onMounted, reactive, ref, unref, watch } from 'vue';  
5 - import { Tabs, Row, Col, Spin, Button, Pagination, Empty } from 'ant-design-vue'; 4 + import { onMounted, reactive, ref, unref, watch } from 'vue';
  5 + import { Spin, Button, Pagination, Space, List } from 'ant-design-vue';
6 import { cameraPage } from '/@/api/camera/cameraManager'; 6 import { cameraPage } from '/@/api/camera/cameraManager';
7 import { CameraRecord } from '/@/api/camera/model/cameraModel'; 7 import { CameraRecord } from '/@/api/camera/model/cameraModel';
8 import { videoPlay as VideoPlay } from 'vue3-video-play'; 8 import { videoPlay as VideoPlay } from 'vue3-video-play';
@@ -14,6 +14,7 @@ @@ -14,6 +14,7 @@
14 import SvgIcon from '/@/components/Icon/src/SvgIcon.vue'; 14 import SvgIcon from '/@/components/Icon/src/SvgIcon.vue';
15 import { isDef } from '/@/utils/is'; 15 import { isDef } from '/@/utils/is';
16 import { getStreamingPlayUrl } from '/@/api/camera/cameraManager'; 16 import { getStreamingPlayUrl } from '/@/api/camera/cameraManager';
  17 + import { buildUUID } from '/@/utils/uuid';
17 18
18 type CameraRecordItem = CameraRecord & { 19 type CameraRecordItem = CameraRecord & {
19 canPlay?: boolean; 20 canPlay?: boolean;
@@ -67,15 +68,11 @@ @@ -67,15 +68,11 @@
67 getCameraList(); 68 getCameraList();
68 }; 69 };
69 70
70 - const getColLayout = computed(() => {  
71 - const totalSpan = 24;  
72 - return totalSpan / pagination.colNumber;  
73 - });  
74 -  
75 const getCameraList = async () => { 71 const getCameraList = async () => {
76 try { 72 try {
  73 + cameraList.value = [];
77 loading.value = true; 74 loading.value = true;
78 - const { items, total } = await cameraPage({ 75 + let { items, total } = await cameraPage({
79 page: pagination.page, 76 page: pagination.page,
80 pageSize: pagination.pageSize, 77 pageSize: pagination.pageSize,
81 organizationId: unref(organizationId)!, 78 organizationId: unref(organizationId)!,
@@ -87,6 +84,14 @@ @@ -87,6 +84,14 @@
87 (item as CameraRecordItem).isTransform = false; 84 (item as CameraRecordItem).isTransform = false;
88 beforeVideoPlay(item); 85 beforeVideoPlay(item);
89 } 86 }
  87 + if (items.length < pagination.pageSize) {
  88 + const fillArr: any = Array.from({ length: pagination.pageSize - items.length }).map(() => ({
  89 + id: buildUUID(),
  90 + placeholder: true,
  91 + }));
  92 + items = [...items, ...fillArr];
  93 + console.log(fillArr);
  94 + }
90 cameraList.value = items; 95 cameraList.value = items;
91 } catch (error) { 96 } catch (error) {
92 } finally { 97 } finally {
@@ -128,7 +133,10 @@ @@ -128,7 +133,10 @@
128 } 133 }
129 }; 134 };
130 135
  136 + const gridLayout = ref({ gutter: 1, column: 2 });
  137 +
131 const handleSwitchLayoutWay = (pageSize: number, layout: number) => { 138 const handleSwitchLayoutWay = (pageSize: number, layout: number) => {
  139 + gridLayout.value = { gutter: 1, column: Math.sqrt(pageSize) };
132 pagination.colNumber = layout; 140 pagination.colNumber = layout;
133 pagination.pageSize = pageSize; 141 pagination.pageSize = pageSize;
134 pagination.page = 1; 142 pagination.page = 1;
@@ -185,7 +193,7 @@ @@ -185,7 +193,7 @@
185 <PageWrapper dense contentFullHeight contentClass="flex"> 193 <PageWrapper dense contentFullHeight contentClass="flex">
186 <OrganizationIdTree @select="handleSelect" ref="organizationIdTreeRef" /> 194 <OrganizationIdTree @select="handleSelect" ref="organizationIdTreeRef" />
187 <section class="p-4 pl-9 split-screen-mode flex flex-col flex-auto w-3/4 xl:w-4/5"> 195 <section class="p-4 pl-9 split-screen-mode flex flex-col flex-auto w-3/4 xl:w-4/5">
188 - <div class="p-3 bg-light-50 flex justify-between mb-4"> 196 + <div class="p-3 bg-light-50 flex justify-between mb-4 dark:bg-dark-900">
189 <div class="flex gap-4 cursor-pointer items-center"> 197 <div class="flex gap-4 cursor-pointer items-center">
190 <div 198 <div
191 class="w-8 h-8 flex justify-center items-center" 199 class="w-8 h-8 flex justify-center items-center"
@@ -225,14 +233,67 @@ @@ -225,14 +233,67 @@
225 <div class="flex"> 233 <div class="flex">
226 <Button type="primary" @click="handleAddCamera">新增视频</Button> 234 <Button type="primary" @click="handleAddCamera">新增视频</Button>
227 </div> 235 </div>
228 - <Tabs type="card" v-model:activeKey="activeKey" @change="handleChangeMode">  
229 - <Tabs.TabPane :key="PageMode.SPLIT_SCREEN_MODE" tab="分屏模式" />  
230 - <Tabs.TabPane :key="PageMode.LIST_MODE" tab="列表模式" />  
231 - <Tabs.TabPane :key="PageMode.FULL_SCREEN_MODE" tab="全屏" />  
232 - </Tabs> 236 + <Space>
  237 + <Button type="primary" @click="handleChangeMode(PageMode.SPLIT_SCREEN_MODE)">
  238 + 分屏模式
  239 + </Button>
  240 + <Button type="primary" @click="handleChangeMode(PageMode.LIST_MODE)">
  241 + 列表模式
  242 + </Button>
  243 + <Button type="primary" @click="handleChangeMode(PageMode.FULL_SCREEN_MODE)">
  244 + 全屏
  245 + </Button>
  246 + </Space>
233 </div> 247 </div>
234 </div> 248 </div>
235 - <section ref="videoContainer" class="bg-light-50 flex-auto"> 249 + <List
  250 + :loading="loading"
  251 + :data-source="cameraList"
  252 + class="bg-light-50 flex-auto dark:bg-dark-900 split-mode-list"
  253 + :grid="gridLayout"
  254 + :style="{ '--height': `${100 / pagination.colNumber}%` }"
  255 + >
  256 + <template #renderItem="{ item }">
  257 + <List.Item>
  258 + <div class="box-border w-full h-full p-1px">
  259 + <div
  260 + v-if="item.placeholder"
  261 + class="bg-black w-full h-full overflow-hidden relative"
  262 + ></div>
  263 + <div
  264 + v-if="!item.placeholder"
  265 + class="bg-black w-full h-full overflow-hidden relative video-container"
  266 + >
  267 + <Spin v-show="!item.isTransform" :spinning="!item.isTransform">
  268 + <div class="bg-black text-light-50"> </div>
  269 + </Spin>
  270 + <VideoPlay
  271 + v-show="item.isTransform"
  272 + @loadstart="handleLoadStart(item)"
  273 + @loadeddata="handleLoadData(item)"
  274 + v-bind="options"
  275 + :src="item.videoUrl"
  276 + :title="item.name"
  277 + :type="item.type"
  278 + />
  279 + <div
  280 + v-if="item.isTransform && isDef(item.canPlay) && !item.canPlay"
  281 + class="video-container-error-msk absolute top-0 left-0 text-lg w-full h-full text-light-50 flex justify-center items-center z-50 bg-black"
  282 + >
  283 + 视频加载出错了!
  284 + </div>
  285 + <div
  286 + class="video-container-mask absolute top-0 left-0 z-50 text-lg w-full text-light-50 flex justify-center items-center"
  287 + style="height: 100%; background-color: rgba(0, 0, 0, 0.5)"
  288 + >
  289 + <span>{{ item.name }}</span>
  290 + </div>
  291 + </div>
  292 + </div>
  293 + </List.Item>
  294 + </template>
  295 + </List>
  296 + <!-- <section ref="videoContainer" class="bg-light-50 flex-auto dark:bg-dark-900">
236 <Spin :spinning="loading" class="h-full"> 297 <Spin :spinning="loading" class="h-full">
237 <Empty 298 <Empty
238 class="h-full flex flex-col justify-center items-center" 299 class="h-full flex flex-col justify-center items-center"
@@ -277,7 +338,7 @@ @@ -277,7 +338,7 @@
277 </Col> 338 </Col>
278 </Row> 339 </Row>
279 </Spin> 340 </Spin>
280 - </section> 341 + </section> -->
281 </section> 342 </section>
282 </PageWrapper> 343 </PageWrapper>
283 <CameraDrawer @register="registerDrawer" @success="getCameraList" /> 344 <CameraDrawer @register="registerDrawer" @success="getCameraList" />
@@ -334,4 +395,20 @@ @@ -334,4 +395,20 @@
334 } 395 }
335 } 396 }
336 } 397 }
  398 +
  399 + .split-mode-list:deep(.ant-row) {
  400 + width: 100%;
  401 + height: 100%;
  402 + }
  403 +
  404 + .split-mode-list:deep(.ant-list-item) {
  405 + width: 100%;
  406 + height: 100%;
  407 + }
  408 +
  409 + .split-mode-list:deep(.ant-col) {
  410 + width: 100%;
  411 + // height: var(--height);
  412 + height: 100%;
  413 + }
337 </style> 414 </style>
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 <div class="organization-tree flex relative"> 2 <div class="organization-tree flex relative">
3 <div class="cursor-pointer flex py-4 fold-icon" :class="foldFlag ? 'absolute' : ''"> 3 <div class="cursor-pointer flex py-4 fold-icon" :class="foldFlag ? 'absolute' : ''">
4 <div @click="handleFold"> 4 <div @click="handleFold">
5 - <DoubleRightOutlined :class="[foldFlag ? '' : 'rotate-180']" class="text-xl transform" /> 5 + <CaretRightOutlined :class="[foldFlag ? '' : 'rotate-180']" class="text-xl transform" />
6 </div> 6 </div>
7 </div> 7 </div>
8 <div 8 <div
@@ -29,7 +29,7 @@ @@ -29,7 +29,7 @@
29 import { onMounted, ref, unref } from 'vue'; 29 import { onMounted, ref, unref } from 'vue';
30 import { BasicTree, TreeItem } from '/@/components/Tree'; 30 import { BasicTree, TreeItem } from '/@/components/Tree';
31 import { getOrganizationList } from '/@/api/system/system'; 31 import { getOrganizationList } from '/@/api/system/system';
32 - import { DoubleRightOutlined } from '@ant-design/icons-vue'; 32 + import { CaretRightOutlined } from '@ant-design/icons-vue';
33 33
34 const emit = defineEmits(['select']); 34 const emit = defineEmits(['select']);
35 const treeData = ref<TreeItem[]>([]); 35 const treeData = ref<TreeItem[]>([]);
  1 +<template>
  2 + <div>
  3 + <PageWrapper dense contentFullHeight contentClass="flex">
  4 + <OrganizationIdTree @select="handleSelect" ref="organizationIdTreeRef" />
  5 + <BasicTable
  6 + style="flex: auto"
  7 + :clickToRowSelect="false"
  8 + @register="registerTable"
  9 + :searchInfo="searchInfo"
  10 + class="w-3/4 xl:w-4/5"
  11 + >
  12 + <template #platform="{ record }">
  13 + <Tag :color="record.platform === Platform.PHONE ? 'cyan' : 'blue'">
  14 + {{ record.platform === Platform.PHONE ? '移动端' : 'PC端' }}
  15 + </Tag>
  16 + </template>
  17 + <template #toolbar>
  18 + <Authority value="api:yt:configuration:center:post">
  19 + <a-button type="primary" @click="handleCreateOrEdit(null)"> 新增组态 </a-button>
  20 + </Authority>
  21 + <Authority value="api:yt:configuration:center:delete">
  22 + <Popconfirm
  23 + title="您确定要批量删除数据"
  24 + ok-text="确定"
  25 + cancel-text="取消"
  26 + @confirm="handleDeleteOrBatchDelete(null)"
  27 + >
  28 + <a-button type="primary" color="error" :disabled="hasBatchDelete">
  29 + 批量删除
  30 + </a-button>
  31 + </Popconfirm>
  32 + </Authority>
  33 + </template>
  34 + <template #action="{ record }">
  35 + <TableAction
  36 + :actions="[
  37 + {
  38 + label: '设计',
  39 + auth: 'api:yt:configuration:center:get_configuration_info:get',
  40 + icon: 'clarity:note-edit-line',
  41 + onClick: handleDesign.bind(null, record),
  42 + },
  43 + {
  44 + label: '预览',
  45 + auth: 'api:yt:configuration:center:get_configuration_info:get',
  46 + icon: 'ant-design:eye-outlined',
  47 + onClick: handlePreview.bind(null, record),
  48 + },
  49 + {
  50 + label: '编辑',
  51 + auth: 'api:yt:configuration:center:update',
  52 + icon: 'clarity:note-edit-line',
  53 + onClick: handleCreateOrEdit.bind(null, record),
  54 + },
  55 + {
  56 + label: '删除',
  57 + auth: 'api:yt:configuration:center:delete',
  58 + icon: 'ant-design:delete-outlined',
  59 + color: 'error',
  60 + popConfirm: {
  61 + title: '是否确认删除',
  62 + confirm: handleDeleteOrBatchDelete.bind(null, record),
  63 + },
  64 + },
  65 + ]"
  66 + />
  67 + </template>
  68 + </BasicTable>
  69 + </PageWrapper>
  70 + <ContactDrawer @register="registerDrawer" @success="handleSuccess" />
  71 + </div>
  72 +</template>
  73 +
  74 +<script lang="ts">
  75 + import { defineComponent, reactive, nextTick } from 'vue';
  76 + import { BasicTable, useTable, TableAction } from '/@/components/Table';
  77 + import { PageWrapper } from '/@/components/Page';
  78 + import { useDrawer } from '/@/components/Drawer';
  79 + import ContactDrawer from './ConfigurationCenterDrawer.vue';
  80 + import { useResetOrganizationTree, OrganizationIdTree } from '/@/views/common/organizationIdTree';
  81 + import { searchFormSchema, columns, Platform } from './center.data';
  82 + import {
  83 + getPage,
  84 + deleteConfigurationCenter,
  85 + } from '/@/api/configuration/center/configurationCenter';
  86 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
  87 + import { getAppEnvConfig, isDevMode } from '/@/utils/env';
  88 + import { Authority } from '/@/components/Authority';
  89 + import { Popconfirm } from 'ant-design-vue';
  90 + import { Tag } from 'ant-design-vue';
  91 + export default defineComponent({
  92 + components: {
  93 + PageWrapper,
  94 + OrganizationIdTree,
  95 + BasicTable,
  96 + TableAction,
  97 + ContactDrawer,
  98 + Authority,
  99 + Popconfirm,
  100 + Tag,
  101 + },
  102 + setup() {
  103 + const { VITE_GLOB_CONFIGURATION } = getAppEnvConfig();
  104 + const isDev = isDevMode();
  105 + const searchInfo = reactive<Recordable>({});
  106 + const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo);
  107 + // 表格hooks
  108 + const [registerTable, { reload, setProps }] = useTable({
  109 + title: '组态中心列表',
  110 + api: getPage,
  111 + columns,
  112 + clickToRowSelect: false,
  113 + formConfig: {
  114 + labelWidth: 120,
  115 + schemas: searchFormSchema,
  116 + resetFunc: resetFn,
  117 + },
  118 + showIndexColumn: false,
  119 + useSearchForm: true,
  120 + showTableSetting: true,
  121 + bordered: true,
  122 + rowKey: 'id',
  123 + actionColumn: {
  124 + width: 200,
  125 + title: '操作',
  126 + dataIndex: 'action',
  127 + slots: { customRender: 'action' },
  128 + fixed: 'right',
  129 + },
  130 + });
  131 + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
  132 + deleteConfigurationCenter,
  133 + handleSuccess,
  134 + setProps
  135 + );
  136 + nextTick(() => {
  137 + setProps(selectionOptions);
  138 + });
  139 +
  140 + // 弹框
  141 + const [registerDrawer, { openDrawer }] = useDrawer();
  142 +
  143 + // 刷新
  144 + function handleSuccess() {
  145 + reload();
  146 + }
  147 + // 新增或编辑
  148 + const handleCreateOrEdit = (record: Recordable | null) => {
  149 + if (record) {
  150 + openDrawer(true, {
  151 + isUpdate: true,
  152 + record,
  153 + });
  154 + } else {
  155 + openDrawer(true, {
  156 + isUpdate: false,
  157 + });
  158 + }
  159 + };
  160 + // 树形选择器
  161 + const handleSelect = (organizationId: string) => {
  162 + searchInfo.organizationId = organizationId;
  163 + handleSuccess();
  164 + };
  165 +
  166 + const handlePreview = (record: Recordable | null) => {
  167 + window.open(
  168 + `${VITE_GLOB_CONFIGURATION}/${isDev ? '?dev=1&' : '?'}configurationId=${
  169 + record!.id
  170 + }&lightbox=1`
  171 + );
  172 + };
  173 + const handleDesign = (record: Recordable | null) => {
  174 + window.open(
  175 + `${VITE_GLOB_CONFIGURATION}/${isDev ? '?dev=1&' : '?'}configurationId=${record!.id}`
  176 + );
  177 + };
  178 +
  179 + return {
  180 + Platform,
  181 + searchInfo,
  182 + hasBatchDelete,
  183 + handleCreateOrEdit,
  184 + handleDeleteOrBatchDelete,
  185 + handleSelect,
  186 + handleSuccess,
  187 + handlePreview,
  188 + handleDesign,
  189 + registerTable,
  190 + registerDrawer,
  191 + organizationIdTreeRef,
  192 + };
  193 + },
  194 + });
  195 +</script>
1 -<template>  
2 - <div>  
3 - <PageWrapper dense contentFullHeight contentClass="flex">  
4 - <OrganizationIdTree @select="handleSelect" ref="organizationIdTreeRef" />  
5 - <BasicTable  
6 - style="flex: auto"  
7 - :clickToRowSelect="false"  
8 - @register="registerTable"  
9 - :searchInfo="searchInfo"  
10 - class="w-3/4 xl:w-4/5"  
11 - >  
12 - <template #platform="{ record }">  
13 - <Tag :color="record.platform === Platform.PHONE ? 'cyan' : 'blue'">  
14 - {{ record.platform === Platform.PHONE ? '移动端' : 'PC端' }}  
15 - </Tag>  
16 - </template>  
17 - <template #toolbar>  
18 - <Authority value="api:yt:configuration:center:post">  
19 - <a-button type="primary" @click="handleCreateOrEdit(null)"> 新增组态 </a-button>  
20 - </Authority>  
21 - <Authority value="api:yt:configuration:center:delete">  
22 - <Popconfirm  
23 - title="您确定要批量删除数据"  
24 - ok-text="确定"  
25 - cancel-text="取消"  
26 - @confirm="handleDeleteOrBatchDelete(null)"  
27 - >  
28 - <a-button type="primary" color="error" :disabled="hasBatchDelete">  
29 - 批量删除  
30 - </a-button>  
31 - </Popconfirm>  
32 - </Authority>  
33 - </template>  
34 - <template #action="{ record }">  
35 - <TableAction  
36 - :actions="[  
37 - {  
38 - label: '设计',  
39 - auth: 'api:yt:configuration:center:get_configuration_info:get',  
40 - icon: 'clarity:note-edit-line',  
41 - onClick: handleDesign.bind(null, record),  
42 - },  
43 - {  
44 - label: '预览',  
45 - auth: 'api:yt:configuration:center:get_configuration_info:get',  
46 - icon: 'ant-design:eye-outlined',  
47 - onClick: handlePreview.bind(null, record),  
48 - },  
49 - {  
50 - label: '编辑',  
51 - auth: 'api:yt:configuration:center:update',  
52 - icon: 'clarity:note-edit-line',  
53 - onClick: handleCreateOrEdit.bind(null, record),  
54 - },  
55 - {  
56 - label: '删除',  
57 - auth: 'api:yt:configuration:center:delete',  
58 - icon: 'ant-design:delete-outlined',  
59 - color: 'error',  
60 - popConfirm: {  
61 - title: '是否确认删除',  
62 - confirm: handleDeleteOrBatchDelete.bind(null, record),  
63 - },  
64 - },  
65 - ]"  
66 - />  
67 - </template>  
68 - </BasicTable>  
69 - </PageWrapper>  
70 - <ContactDrawer @register="registerDrawer" @success="handleSuccess" />  
71 - </div>  
72 -</template>  
73 -  
74 -<script lang="ts">  
75 - import { defineComponent, reactive, nextTick } from 'vue';  
76 - import { BasicTable, useTable, TableAction } from '/@/components/Table';  
77 - import { PageWrapper } from '/@/components/Page';  
78 - import { useDrawer } from '/@/components/Drawer';  
79 - import ContactDrawer from './ConfigurationCenterDrawer.vue';  
80 - import { useResetOrganizationTree, OrganizationIdTree } from '/@/views/common/organizationIdTree';  
81 - import { searchFormSchema, columns, Platform } from './center.data'; 1 +<script setup lang="ts">
  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';
  10 + import { onMounted, reactive, ref, unref } from 'vue';
  11 + import { OrganizationIdTree, useResetOrganizationTree } from '../../common/organizationIdTree';
82 import { 12 import {
83 - getPage,  
84 deleteConfigurationCenter, 13 deleteConfigurationCenter,
  14 + getPage,
85 } from '/@/api/configuration/center/configurationCenter'; 15 } from '/@/api/configuration/center/configurationCenter';
86 - import { useBatchDelete } from '/@/hooks/web/useBatchDelete';  
87 - import { getAppEnvConfig, isDevMode } from '/@/utils/env'; 16 + import { ConfigurationCenterItemsModal } from '/@/api/configuration/center/model/configurationCenterModal';
  17 + import { PageWrapper } from '/@/components/Page';
  18 + import { Dropdown } from '/@/components/Dropdown';
  19 + import { BasicForm, useForm } from '/@/components/Form';
  20 + import { searchFormSchema } from './center.data';
  21 + import { useMessage } from '/@/hooks/web/useMessage';
88 import { Authority } from '/@/components/Authority'; 22 import { Authority } from '/@/components/Authority';
89 - import { Popconfirm } from 'ant-design-vue';  
90 - import { Tag } from 'ant-design-vue';  
91 - export default defineComponent({  
92 - components: {  
93 - PageWrapper,  
94 - OrganizationIdTree,  
95 - BasicTable,  
96 - TableAction,  
97 - ContactDrawer,  
98 - Authority,  
99 - Popconfirm,  
100 - Tag, 23 + import { isDevMode } from '/@/utils/env';
  24 + import ConfigurationCenterDrawer from './ConfigurationCenterDrawer.vue';
  25 + import { useDrawer } from '/@/components/Drawer';
  26 + import { useSyncConfirm } from '/@/hooks/component/useSyncConfirm';
  27 + import { getBoundingClientRect } from '/@/utils/domUtils';
  28 +
  29 + const listColumn = ref(4);
  30 +
  31 + const { createMessage } = useMessage();
  32 +
  33 + const organizationId = ref<Nullable<number>>(null);
  34 +
  35 + const pagination = reactive<PaginationProps>({
  36 + size: 'small',
  37 + showTotal: (total: number) => `共 ${total} 条数据`,
  38 + current: 1,
  39 + onChange: (page: number) => {
  40 + pagination.current = page;
  41 + getListData();
  42 + },
  43 + });
  44 +
  45 + const loading = ref(false);
  46 +
  47 + const dataSource = ref<ConfigurationCenterItemsModal[]>([]);
  48 +
  49 + const [registerForm, { getFieldsValue }] = useForm({
  50 + schemas: searchFormSchema,
  51 + showAdvancedButton: true,
  52 + labelWidth: 100,
  53 + compact: true,
  54 + resetFunc: () => {
  55 + resetFn();
  56 + organizationId.value = null;
  57 + return getListData();
101 }, 58 },
102 - setup() {  
103 - const { VITE_GLOB_CONFIGURATION } = getAppEnvConfig();  
104 - const isDev = isDevMode();  
105 - const searchInfo = reactive<Recordable>({});  
106 - const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo);  
107 - // 表格hooks  
108 - const [registerTable, { reload, setProps }] = useTable({  
109 - title: '组态中心列表',  
110 - api: getPage,  
111 - columns,  
112 - clickToRowSelect: false,  
113 - formConfig: {  
114 - labelWidth: 120,  
115 - schemas: searchFormSchema,  
116 - resetFunc: resetFn,  
117 - },  
118 - showIndexColumn: false,  
119 - useSearchForm: true,  
120 - showTableSetting: true,  
121 - bordered: true,  
122 - rowKey: 'id',  
123 - actionColumn: {  
124 - width: 200,  
125 - title: '操作',  
126 - dataIndex: 'action',  
127 - slots: { customRender: 'action' },  
128 - fixed: 'right',  
129 - }, 59 + submitFunc: async () => {
  60 + const value = getFieldsValue();
  61 + getListData(value);
  62 + },
  63 + });
  64 +
  65 + async function getListData(value: Recordable = {}) {
  66 + try {
  67 + loading.value = true;
  68 + const pageSize = 4 * unref(listColumn);
  69 + const { items, total } = await getPage({
  70 + organizationId: unref(organizationId),
  71 + ...value,
  72 + page: pagination.current!,
  73 + pageSize,
  74 + });
  75 + dataSource.value = items;
  76 + pagination.total = total;
  77 + pagination.pageSize = pageSize;
  78 + } catch (error) {
  79 + } finally {
  80 + loading.value = false;
  81 + }
  82 + }
  83 +
  84 + onMounted(() => {
  85 + getListData();
  86 + });
  87 +
  88 + const searchInfo = reactive<Recordable>({});
  89 + const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo);
  90 + const handleSelect = (orgId: number) => {
  91 + organizationId.value = orgId;
  92 + getListData();
  93 + };
  94 +
  95 + const [registerDrawer, { openDrawer }] = useDrawer();
  96 +
  97 + const handleCreateOrUpdate = (record?: ConfigurationCenterItemsModal) => {
  98 + if (record) {
  99 + openDrawer(true, {
  100 + isUpdate: true,
  101 + record,
130 }); 102 });
131 - const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(  
132 - deleteConfigurationCenter,  
133 - handleSuccess,  
134 - setProps  
135 - );  
136 - nextTick(() => {  
137 - setProps(selectionOptions); 103 + } else {
  104 + openDrawer(true, {
  105 + isUpdate: false,
138 }); 106 });
  107 + }
  108 + };
139 109
140 - // 弹框  
141 - const [registerDrawer, { openDrawer }] = useDrawer();  
142 -  
143 - // 刷新  
144 - function handleSuccess() {  
145 - reload();  
146 - }  
147 - // 新增或编辑  
148 - const handleCreateOrEdit = (record: Recordable | null) => {  
149 - if (record) {  
150 - openDrawer(true, {  
151 - isUpdate: true,  
152 - record,  
153 - });  
154 - } else {  
155 - openDrawer(true, {  
156 - isUpdate: false,  
157 - });  
158 - }  
159 - };  
160 - // 树形选择器  
161 - const handleSelect = (organizationId: string) => {  
162 - searchInfo.organizationId = organizationId;  
163 - handleSuccess();  
164 - };  
165 -  
166 - const handlePreview = (record: Recordable | null) => {  
167 - window.open(  
168 - `${VITE_GLOB_CONFIGURATION}/${isDev ? '?dev=1&' : '?'}configurationId=${  
169 - record!.id  
170 - }&lightbox=1`  
171 - );  
172 - };  
173 - const handleDesign = (record: Recordable | null) => {  
174 - window.open(  
175 - `${VITE_GLOB_CONFIGURATION}/${isDev ? '?dev=1&' : '?'}configurationId=${record!.id}`  
176 - );  
177 - };  
178 -  
179 - return {  
180 - Platform,  
181 - searchInfo,  
182 - hasBatchDelete,  
183 - handleCreateOrEdit,  
184 - handleDeleteOrBatchDelete,  
185 - handleSelect,  
186 - handleSuccess,  
187 - handlePreview,  
188 - handleDesign,  
189 - registerTable,  
190 - registerDrawer,  
191 - organizationIdTreeRef,  
192 - };  
193 - }, 110 + const { VITE_GLOB_CONFIGURATION } = import.meta.env;
  111 + const isDev = isDevMode();
  112 +
  113 + const handlePreview = (record: ConfigurationCenterItemsModal) => {
  114 + console.log(record);
  115 + window.open(
  116 + `${VITE_GLOB_CONFIGURATION}/${isDev ? '?dev=1&' : '?'}configurationId=${
  117 + record!.id
  118 + }&lightbox=1`
  119 + );
  120 + };
  121 +
  122 + const handleDesign = (record: ConfigurationCenterItemsModal) => {
  123 + window.open(
  124 + `${VITE_GLOB_CONFIGURATION}/${isDev ? '?dev=1&' : '?'}configurationId=${record!.id}`
  125 + );
  126 + };
  127 +
  128 + const { createSyncConfirm } = useSyncConfirm();
  129 + const handleDelete = async (record: ConfigurationCenterItemsModal) => {
  130 + try {
  131 + await createSyncConfirm({ iconType: 'warning', content: '是否确认删除操作?' });
  132 + await deleteConfigurationCenter([record.id]);
  133 + createMessage.success('删除成功');
  134 + await getListData();
  135 + } catch (error) {}
  136 + };
  137 +
  138 + const listEl = ref<Nullable<ComponentElRef>>(null);
  139 +
  140 + onMounted(() => {
  141 + const clientHeight = document.documentElement.clientHeight;
  142 + const rect = getBoundingClientRect(unref(listEl)!.$el!) as DOMRect;
  143 + // margin-top 24 height 24
  144 + const paginationHeight = 24 + 24 + 8;
  145 + // list pading top 8 maring-top 8 extra slot 56
  146 + const listContainerMarginBottom = 8 + 8 + 56;
  147 + const listContainerHeight =
  148 + clientHeight - rect.top - paginationHeight - listContainerMarginBottom;
  149 + const listContainerEl = (unref(listEl)!.$el as HTMLElement).querySelector(
  150 + '.ant-spin-container'
  151 + ) as HTMLElement;
  152 + listContainerEl &&
  153 + (listContainerEl.style.height = listContainerHeight + 'px') &&
  154 + (listContainerEl.style.overflowY = 'auto') &&
  155 + (listContainerEl.style.overflowX = 'hidden');
194 }); 156 });
195 </script> 157 </script>
  158 +
  159 +<template>
  160 + <PageWrapper dense contentFullHeight contentClass="flex">
  161 + <OrganizationIdTree @select="handleSelect" ref="organizationIdTreeRef" />
  162 + <section class="flex-auto pl-9 p-4 configuration-list">
  163 + <div class="flex-auto w-full bg-light-50 dark:bg-dark-900 p-4">
  164 + <BasicForm @register="registerForm" />
  165 + </div>
  166 + <List
  167 + ref="listEl"
  168 + :loading="loading"
  169 + class="flex-auto bg-light-50 dark:bg-dark-900 !p-2 !mt-4"
  170 + position="bottom"
  171 + :pagination="pagination"
  172 + :data-source="dataSource"
  173 + :grid="{ gutter: 4, column: listColumn }"
  174 + >
  175 + <template #header>
  176 + <div class="flex gap-3 justify-end">
  177 + <Button type="primary" @click="handleCreateOrUpdate()">新增组态</Button>
  178 + <Popover :trigger="['hover']">
  179 + <template #content>
  180 + <div class="w-50">
  181 + <div>每行显示数量</div>
  182 + <Slider
  183 + v-model:value="listColumn"
  184 + :max="12"
  185 + :min="4"
  186 + :marks="{ 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10, 11: 11, 12: 12 }"
  187 + @change="getListData"
  188 + />
  189 + </div>
  190 + </template>
  191 + <Button type="primary">
  192 + <AppstoreOutlined />
  193 + </Button>
  194 + </Popover>
  195 + <Tooltip title="刷新">
  196 + <Button type="primary" @click="getListData">
  197 + <ReloadOutlined @click="getListData" />
  198 + </Button>
  199 + </Tooltip>
  200 + </div>
  201 + </template>
  202 + <template #renderItem="{ item }">
  203 + <List.Item>
  204 + <Card hoverable>
  205 + <template #cover>
  206 + <img
  207 + alt="example"
  208 + src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"
  209 + />
  210 + </template>
  211 + <template class="ant-card-actions" #actions>
  212 + <Authority value="api:yt:configuration:center:get_configuration_info:get">
  213 + <Tooltip title="预览">
  214 + <EyeOutlined key="setting" @click="handlePreview(item)" />
  215 + </Tooltip>
  216 + </Authority>
  217 + <Authority value="api:yt:configuration:center:update">
  218 + <Tooltip title="编辑">
  219 + <EditOutlined key="edit" @click="handleCreateOrUpdate(item)" />
  220 + </Tooltip>
  221 + </Authority>
  222 + <Dropdown
  223 + :dropMenuList="[
  224 + {
  225 + text: '设计',
  226 + auth: 'api:yt:configuration:center:get_configuration_info:get',
  227 + icon: 'clarity:note-edit-line',
  228 + onClick: handleDesign.bind(null, item),
  229 + },
  230 + {
  231 + text: '删除',
  232 + auth: 'api:yt:configuration:center:delete',
  233 + icon: 'ant-design:delete-outlined',
  234 + color: 'error',
  235 + onClick: handleDelete.bind(null, item),
  236 + },
  237 + ]"
  238 + :trigger="['hover']"
  239 + >
  240 + <EllipsisOutlined key="ellipsis" />
  241 + </Dropdown>
  242 + </template>
  243 + <Card.Meta :title="item.name">
  244 + <template #description>
  245 + <div class="truncate">{{ item.organizationDTO.name }}</div>
  246 + <div class="truncate">{{ item.remark }} </div>
  247 + </template>
  248 + </Card.Meta>
  249 + </Card>
  250 + </List.Item>
  251 + </template>
  252 + </List>
  253 + </section>
  254 + <ConfigurationCenterDrawer @register="registerDrawer" @success="getListData" />
  255 + </PageWrapper>
  256 +</template>
  257 +
  258 +<style lang="less" scoped>
  259 + .configuration-list:deep(.ant-list-header) {
  260 + border-bottom: none !important;
  261 + }
  262 +
  263 + .configuration-list:deep(.ant-list-pagination) {
  264 + height: 24px;
  265 + }
  266 +</style>
@@ -206,7 +206,7 @@ @@ -206,7 +206,7 @@
206 target: '_blank ', 206 target: '_blank ',
207 }, 207 },
208 { 208 {
209 - title: '什么是设备配置?', 209 + title: '什么是产品?',
210 href: 'https://docs.thingskit.com/thingskit-link/operation-guide/device-manage.html#%E8%AE%BE%E5%A4%87%E9%85%8D%E7%BD%AE', 210 href: 'https://docs.thingskit.com/thingskit-link/operation-guide/device-manage.html#%E8%AE%BE%E5%A4%87%E9%85%8D%E7%BD%AE',
211 target: '_blank ', 211 target: '_blank ',
212 }, 212 },
@@ -51,8 +51,8 @@ @@ -51,8 +51,8 @@
51 series: [ 51 series: [
52 { 52 {
53 name: '告警数', 53 name: '告警数',
54 - barWidth: '10%',  
55 - type: 'bar', 54 + // barWidth: '10%',
  55 + type: 'line',
56 stack: 'Total', 56 stack: 'Total',
57 data: props.alarmList, 57 data: props.alarmList,
58 color: '#3C78FF', 58 color: '#3C78FF',
@@ -63,6 +63,7 @@ @@ -63,6 +63,7 @@
63 watch( 63 watch(
64 () => props.alarmList, 64 () => props.alarmList,
65 (newValue) => { 65 (newValue) => {
  66 + console.log({ newValue, props });
66 let alarmTotal = 0; 67 let alarmTotal = 0;
67 for (const item of props.alarmList) { 68 for (const item of props.alarmList) {
68 alarmTotal += Number(item[1]); 69 alarmTotal += Number(item[1]);
@@ -91,10 +92,10 @@ @@ -91,10 +92,10 @@
91 series: [ 92 series: [
92 { 93 {
93 name: '告警数', 94 name: '告警数',
94 - type: 'bar', 95 + type: 'line',
95 stack: 'Total', 96 stack: 'Total',
96 color: '#3C78FF', 97 color: '#3C78FF',
97 - barWidth: '10%', 98 + // barWidth: '10%',
98 data: newValue, 99 data: newValue,
99 }, 100 },
100 ], 101 ],
@@ -63,17 +63,17 @@ @@ -63,17 +63,17 @@
63 series: [ 63 series: [
64 { 64 {
65 name: '传输数据点', 65 name: '传输数据点',
66 - type: 'bar', 66 + type: 'line',
67 stack: 'total', 67 stack: 'total',
68 data: newValue, 68 data: newValue,
69 - barWidth: '10%', 69 + // barWidth: '10%',
70 color: '#5AEEED', 70 color: '#5AEEED',
71 }, 71 },
72 { 72 {
73 name: '传输消息量', 73 name: '传输消息量',
74 - type: 'bar', 74 + type: 'line',
75 stack: 'total', 75 stack: 'total',
76 - barWidth: '10%', 76 + // barWidth: '10%',
77 data: newValue1, 77 data: newValue1,
78 color: '#3C78FF', 78 color: '#3C78FF',
79 }, 79 },
@@ -35,7 +35,7 @@ export const step1Schemas: FormSchema[] = [ @@ -35,7 +35,7 @@ export const step1Schemas: FormSchema[] = [
35 }, 35 },
36 { 36 {
37 field: 'profileId', 37 field: 'profileId',
38 - label: '设备配置', 38 + label: '所属产品',
39 required: true, 39 required: true,
40 component: 'ApiSelect', 40 component: 'ApiSelect',
41 componentProps: ({ formActionType }) => { 41 componentProps: ({ formActionType }) => {
@@ -57,7 +57,7 @@ export const step1Schemas: FormSchema[] = [ @@ -57,7 +57,7 @@ export const step1Schemas: FormSchema[] = [
57 required: true, 57 required: true,
58 component: 'ApiSelect', 58 component: 'ApiSelect',
59 dynamicDisabled: true, 59 dynamicDisabled: true,
60 - helpMessage: ['选择设备配置,自动关联设备类型'], 60 + helpMessage: ['选择所属产品,自动关联设备类型'],
61 componentProps: { 61 componentProps: {
62 placeholder: '设备类型', 62 placeholder: '设备类型',
63 api: findDictItemByCode, 63 api: findDictItemByCode,
@@ -21,7 +21,7 @@ export const descSchema: DescItem[] = [ @@ -21,7 +21,7 @@ export const descSchema: DescItem[] = [
21 }, 21 },
22 { 22 {
23 field: 'deviceProfile.name', 23 field: 'deviceProfile.name',
24 - label: '设备配置', 24 + label: '产品',
25 }, 25 },
26 { 26 {
27 field: 'gatewayName', 27 field: 'gatewayName',
@@ -32,7 +32,7 @@ export const columns: BasicColumn[] = [ @@ -32,7 +32,7 @@ export const columns: BasicColumn[] = [
32 slots: { customRender: 'deviceType' }, 32 slots: { customRender: 'deviceType' },
33 }, 33 },
34 { 34 {
35 - title: '设备配置', 35 + title: '所属产品',
36 dataIndex: 'deviceProfile.name', 36 dataIndex: 'deviceProfile.name',
37 width: 160, 37 width: 160,
38 slots: { customRender: 'deviceProfile' }, 38 slots: { customRender: 'deviceProfile' },
@@ -103,6 +103,21 @@ @@ -103,6 +103,21 @@
103 <template #action="{ record }"> 103 <template #action="{ record }">
104 <TableAction 104 <TableAction
105 :actions="[ 105 :actions="[
  106 + {
  107 + label: '详情',
  108 + icon: 'ant-design:eye-outlined',
  109 + auth: 'api:yt:device:get',
  110 + onClick: handleDetail.bind(null, record),
  111 + },
  112 + {
  113 + label: '编辑',
  114 + auth: 'api:yt:device:update',
  115 + icon: 'clarity:note-edit-line',
  116 + ifShow: authBtn(role) && record.customerId === undefined,
  117 + onClick: handleEdit.bind(null, record),
  118 + },
  119 + ]"
  120 + :dropDownActions="[
106 record.customerId 121 record.customerId
107 ? { 122 ? {
108 label: '取消分配', 123 label: '取消分配',
@@ -119,20 +134,6 @@ @@ -119,20 +134,6 @@
119 ifShow: authBtn(role), 134 ifShow: authBtn(role),
120 onClick: handleDispatchCustomer.bind(null, record), 135 onClick: handleDispatchCustomer.bind(null, record),
121 }, 136 },
122 -  
123 - {  
124 - label: '详情',  
125 - icon: 'ant-design:eye-outlined',  
126 - auth: 'api:yt:device:get',  
127 - onClick: handleDetail.bind(null, record),  
128 - },  
129 - {  
130 - label: '编辑',  
131 - auth: 'api:yt:device:update',  
132 - icon: 'clarity:note-edit-line',  
133 - ifShow: authBtn(role) && record.customerId === undefined,  
134 - onClick: handleEdit.bind(null, record),  
135 - },  
136 { 137 {
137 label: '删除', 138 label: '删除',
138 auth: 'api:yt:device:delete', 139 auth: 'api:yt:device:delete',
@@ -235,7 +236,7 @@ @@ -235,7 +236,7 @@
235 searchInfo: searchInfo, 236 searchInfo: searchInfo,
236 clickToRowSelect: false, 237 clickToRowSelect: false,
237 actionColumn: { 238 actionColumn: {
238 - width: 300, 239 + width: 200,
239 title: '操作', 240 title: '操作',
240 slots: { customRender: 'action' }, 241 slots: { customRender: 'action' },
241 fixed: 'right', 242 fixed: 'right',
@@ -33,7 +33,7 @@ export const formSchema: FormSchema[] = [ @@ -33,7 +33,7 @@ export const formSchema: FormSchema[] = [
33 component: 'ApiSelect', 33 component: 'ApiSelect',
34 componentProps: { 34 componentProps: {
35 api: getDeviceProfile, 35 api: getDeviceProfile,
36 - placeholder: '请选择设备配置', 36 + placeholder: '请选择产品',
37 labelField: 'name', 37 labelField: 'name',
38 valueField: 'id', 38 valueField: 'id',
39 }, 39 },
  1 +<template>
  2 + <BasicDrawer v-bind="$attrs" title="产品详情" @register="register" width="50%">
  3 + <Tabs :animated="true" v-model:activeKey="activeKey">
  4 + <TabPane forceRender key="1" tab="产品">
  5 + <div class="relative">
  6 + <DeviceConfigurationStep :ifShowBtn="false" ref="DevConStRef" />
  7 + <div class="absolute w-full h-full top-0 cursor-not-allowed"></div>
  8 + </div>
  9 + </TabPane>
  10 + <TabPane forceRender key="2" tab="传输配置">
  11 + <div class="relative">
  12 + <TransportConfigurationStep :ifShowBtn="false" ref="TransConStRef" />
  13 + <div class="absolute w-full h-full top-0 cursor-not-allowed"></div>
  14 + </div>
  15 + </TabPane>
  16 + <TabPane forceRender key="3" tab="物模型管理">
  17 + <PhysicalModelManagementStep />
  18 + </TabPane>
  19 + </Tabs>
  20 + </BasicDrawer>
  21 +</template>
  22 +<script lang="ts" setup>
  23 + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
  24 + import { Tabs, TabPane } from 'ant-design-vue';
  25 + import DeviceConfigurationStep from './step/DeviceConfigurationStep.vue';
  26 + import TransportConfigurationStep from './step/TransportConfigurationStep.vue';
  27 + import PhysicalModelManagementStep from './step/PhysicalModelManagementStep.vue';
  28 + import { ref, unref } from 'vue';
  29 + import { deviceConfigGetDetail } from '/@/api/device/deviceConfigApi';
  30 +
  31 + defineEmits(['register']);
  32 +
  33 + const activeKey = ref('1');
  34 +
  35 + const DevConStRef = ref<InstanceType<typeof DeviceConfigurationStep>>();
  36 + const TransConStRef = ref<InstanceType<typeof TransportConfigurationStep>>();
  37 + // const PhysicalModManRef = ref<InstanceType<typeof PhysicalModelManagementStep>>();
  38 +
  39 + const setDeviceConfFormData = async (res: Recordable) => {
  40 + unref(DevConStRef)?.setFormData(res);
  41 + };
  42 + const setTransConfFormData = async (res: Recordable) => {
  43 + unref(TransConStRef)?.setFormData(res);
  44 + };
  45 +
  46 + const [register, {}] = useDrawerInner(async (data: Recordable) => {
  47 + activeKey.value = '1';
  48 + const res = await deviceConfigGetDetail(data.record.id);
  49 + setDeviceConfFormData(res);
  50 + setTransConfFormData(res);
  51 + });
  52 +</script>
  53 +
  54 +<style lang="less" scope></style>
@@ -33,7 +33,7 @@ @@ -33,7 +33,7 @@
33 :size="size" 33 :size="size"
34 @change="handleChange" 34 @change="handleChange"
35 > 35 >
36 - <TabPane forceRender key="1" tab="设备配置"> 36 + <TabPane forceRender key="1" tab="产品">
37 <div class="relative"> 37 <div class="relative">
38 <DeviceConfigurationStep 38 <DeviceConfigurationStep
39 :ifShowBtn="isViewDetail ? false : true" 39 :ifShowBtn="isViewDetail ? false : true"
@@ -109,7 +109,7 @@ @@ -109,7 +109,7 @@
109 isEditCreatTime.value = data.record !== undefined ? data.record.createTime : null; 109 isEditCreatTime.value = data.record !== undefined ? data.record.createTime : null;
110 if (!unref(isViewDetail)) { 110 if (!unref(isViewDetail)) {
111 dynamicWidth.value = 55 + 'rem'; 111 dynamicWidth.value = 55 + 'rem';
112 - const title = !unref(isUpdate) ? '编辑设备配置' : '新增设备配置'; 112 + const title = !unref(isUpdate) ? '编辑产品' : '新增产品';
113 setModalProps({ title, showOkBtn: true, showCancelBtn: true }); 113 setModalProps({ title, showOkBtn: true, showCancelBtn: true });
114 if (!unref(isUpdate)) { 114 if (!unref(isUpdate)) {
115 await setDeviceConfEditFormData(res); 115 await setDeviceConfEditFormData(res);
@@ -118,7 +118,7 @@ @@ -118,7 +118,7 @@
118 } 118 }
119 } else { 119 } else {
120 dynamicWidth.value = 60 + 'rem'; 120 dynamicWidth.value = 60 + 'rem';
121 - setModalProps({ showOkBtn: false, showCancelBtn: false, title: '设备配置详情' }); 121 + setModalProps({ showOkBtn: false, showCancelBtn: false, title: '产品详情' });
122 await setDeviceConfEditFormData(res); 122 await setDeviceConfEditFormData(res);
123 await setTransConfEditFormData(res); 123 await setTransConfEditFormData(res);
124 handleStepNext(false, res); 124 handleStepNext(false, res);
@@ -10,7 +10,7 @@ import { deviceConfigGetRuleChain } from '/@/api/device/deviceConfigApi'; @@ -10,7 +10,7 @@ import { deviceConfigGetRuleChain } from '/@/api/device/deviceConfigApi';
10 10
11 export const steps = [ 11 export const steps = [
12 { 12 {
13 - title: '设备配置', 13 + title: '产品',
14 content: 'First-content', 14 content: 'First-content',
15 }, 15 },
16 { 16 {
@@ -8,11 +8,11 @@ @@ -8,11 +8,11 @@
8 > 8 >
9 <template #toolbar> 9 <template #toolbar>
10 <Authority value="api:yt:deviceProfile:post"> 10 <Authority value="api:yt:deviceProfile:post">
11 - <a-button type="primary" @click="handleCreate"> 新增设备配置 </a-button> 11 + <a-button type="primary" @click="handleCreate"> 新增产品 </a-button>
12 </Authority> 12 </Authority>
13 <Authority value="api:yt:deviceProfile:import"> 13 <Authority value="api:yt:deviceProfile:import">
14 <ImpExcel @success="loadDataSuccess" dateFormat="YYYY-MM-DD"> 14 <ImpExcel @success="loadDataSuccess" dateFormat="YYYY-MM-DD">
15 - <a-button @click="handleImport"> 导入设备配置 </a-button> 15 + <a-button @click="handleImport"> 导入产品 </a-button>
16 </ImpExcel> 16 </ImpExcel>
17 </Authority> 17 </Authority>
18 <Authority value="api:yt:deviceProfile:delete"> 18 <Authority value="api:yt:deviceProfile:delete">
@@ -42,14 +42,6 @@ @@ -42,14 +42,6 @@
42 <TableAction 42 <TableAction
43 :actions="[ 43 :actions="[
44 { 44 {
45 - label: '默认',  
46 - icon: 'ant-design:profile-outlined',  
47 - onClick: handleSetDefault.bind(null, record),  
48 - ifShow: () => {  
49 - return record.default === false;  
50 - },  
51 - },  
52 - {  
53 label: '详情', 45 label: '详情',
54 auth: 'api:yt:deviceProfile:get', 46 auth: 'api:yt:deviceProfile:get',
55 icon: 'ant-design:eye-outlined', 47 icon: 'ant-design:eye-outlined',
@@ -64,6 +56,16 @@ @@ -64,6 +56,16 @@
64 return record.name !== 'default' ? true : false; 56 return record.name !== 'default' ? true : false;
65 }, 57 },
66 }, 58 },
  59 + ]"
  60 + :drop-down-actions="[
  61 + {
  62 + label: '默认',
  63 + icon: 'ant-design:profile-outlined',
  64 + onClick: handleSetDefault.bind(null, record),
  65 + ifShow: () => {
  66 + return record.default === false;
  67 + },
  68 + },
67 { 69 {
68 label: '导出', 70 label: '导出',
69 auth: 'api:yt:deviceProfile:export', 71 auth: 'api:yt:deviceProfile:export',
@@ -88,6 +90,7 @@ @@ -88,6 +90,7 @@
88 </template> 90 </template>
89 </BasicTable> 91 </BasicTable>
90 <DeviceProfileModal @register="registerModal" @success="handleSuccess" /> 92 <DeviceProfileModal @register="registerModal" @success="handleSuccess" />
  93 + <DeviceProfileDrawer @register="registerDrawer" />
91 <ExpExcelModal 94 <ExpExcelModal
92 ref="expExcelModalRef" 95 ref="expExcelModalRef"
93 @register="registerExportModal" 96 @register="registerExportModal"
@@ -106,12 +109,14 @@ @@ -106,12 +109,14 @@
106 setDeviceProfileIsDefaultApi, 109 setDeviceProfileIsDefaultApi,
107 } from '/@/api/device/deviceConfigApi'; 110 } from '/@/api/device/deviceConfigApi';
108 import { useModal } from '/@/components/Modal'; 111 import { useModal } from '/@/components/Modal';
  112 + import { useDrawer } from '/@/components/Drawer';
109 import DeviceProfileModal from '/@/views/device/profiles/DeviceProfileModal.vue'; 113 import DeviceProfileModal from '/@/views/device/profiles/DeviceProfileModal.vue';
110 import { ImpExcel, ExcelData } from '/@/components/Excel'; 114 import { ImpExcel, ExcelData } from '/@/components/Excel';
111 import { jsonToSheetXlsx, ExpExcelModal, ExportModalResult } from '/@/components/Excel'; 115 import { jsonToSheetXlsx, ExpExcelModal, ExportModalResult } from '/@/components/Excel';
112 import { Authority } from '/@/components/Authority'; 116 import { Authority } from '/@/components/Authority';
113 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 117 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
114 import { Popconfirm } from 'ant-design-vue'; 118 import { Popconfirm } from 'ant-design-vue';
  119 + import DeviceProfileDrawer from './DeviceProfileDrawer.vue';
115 120
116 const exportData: any = ref([]); 121 const exportData: any = ref([]);
117 const expExcelModalRef: any = ref(null); 122 const expExcelModalRef: any = ref(null);
@@ -124,7 +129,7 @@ @@ -124,7 +129,7 @@
124 const [registerModal, { openModal }] = useModal(); 129 const [registerModal, { openModal }] = useModal();
125 const [registerExportModal, { openModal: openModalExcel }] = useModal(); 130 const [registerExportModal, { openModal: openModalExcel }] = useModal();
126 const [registerTable, { setProps, reload, setTableData, getForm }] = useTable({ 131 const [registerTable, { setProps, reload, setTableData, getForm }] = useTable({
127 - title: '设备配置列表', 132 + title: '产品列表',
128 clickToRowSelect: false, 133 clickToRowSelect: false,
129 api: deviceConfigGetQuery, 134 api: deviceConfigGetQuery,
130 immediate: immediateStatus.value, 135 immediate: immediateStatus.value,
@@ -139,7 +144,7 @@ @@ -139,7 +144,7 @@
139 bordered: true, 144 bordered: true,
140 showIndexColumn: false, 145 showIndexColumn: false,
141 actionColumn: { 146 actionColumn: {
142 - width: 240, 147 + width: 200,
143 title: '操作', 148 title: '操作',
144 dataIndex: 'action', 149 dataIndex: 'action',
145 slots: { customRender: 'action' }, 150 slots: { customRender: 'action' },
@@ -251,13 +256,16 @@ @@ -251,13 +256,16 @@
251 isView: false, 256 isView: false,
252 }); 257 });
253 } 258 }
  259 +
  260 + const [registerDrawer, { openDrawer }] = useDrawer();
254 //详情 261 //详情
255 function handleDetailView(record: Recordable) { 262 function handleDetailView(record: Recordable) {
256 - openModal(true, {  
257 - record,  
258 - isUpdate: false,  
259 - isView: true,  
260 - }); 263 + openDrawer(true, { record });
  264 + // openModal(true, {
  265 + // record,
  266 + // isUpdate: false,
  267 + // isView: true,
  268 + // });
261 } 269 }
262 270
263 function defaultHeader({ filename, bookType }: ExportModalResult) { 271 function defaultHeader({ filename, bookType }: ExportModalResult) {
@@ -295,8 +303,8 @@ @@ -295,8 +303,8 @@
295 const handleSetDefault = async (record: Recordable) => { 303 const handleSetDefault = async (record: Recordable) => {
296 let id = record.tbProfileId; 304 let id = record.tbProfileId;
297 const data = await setDeviceProfileIsDefaultApi(id, 'default', defaultObj); 305 const data = await setDeviceProfileIsDefaultApi(id, 'default', defaultObj);
298 - if (!data) return createMessage.error('设置该设备配置为默认失败');  
299 - createMessage.success('设置该设备配置为默认成功'); 306 + if (!data) return createMessage.error('设置该产品为默认失败');
  307 + createMessage.success('设置该产品为默认成功');
300 reload(); 308 reload();
301 disabled.value = true; 309 disabled.value = true;
302 }; 310 };
@@ -151,7 +151,7 @@ @@ -151,7 +151,7 @@
151 showIndexColumn: false, 151 showIndexColumn: false,
152 clickToRowSelect: false, 152 clickToRowSelect: false,
153 useSearchForm: false, 153 useSearchForm: false,
154 - rowKey: 'id', 154 + // rowKey: 'id',
155 showTableSetting: true, 155 showTableSetting: true,
156 bordered: true, 156 bordered: true,
157 actionColumn: { 157 actionColumn: {
1 <template> 1 <template>
2 - <div style="background-color: #f0f2f5">  
3 - <BasicTable @register="registerTable"> 2 + <div style="background-color: #f0f2f5" class="dark:bg-dark-900">
  3 + <BasicTable @register="registerTable" class="dark:bg-dark-900">
4 <template #toolbar> 4 <template #toolbar>
5 <Authority value="api:yt:smsLog:export"> 5 <Authority value="api:yt:smsLog:export">
6 <a-button type="primary" @click="handleCreate"> 导出 </a-button> 6 <a-button type="primary" @click="handleCreate"> 导出 </a-button>
1 <template> 1 <template>
2 - <div style="background-color: #f0f2f5">  
3 - <BasicTable @register="registerTable"> 2 + <div style="background-color: #f0f2f5" class="dark:bg-dark-900">
  3 + <BasicTable @register="registerTable" class="dark:bg-dark-900">
4 <template #toolbar> 4 <template #toolbar>
5 <Authority value="api:yt:smsLog:export"> 5 <Authority value="api:yt:smsLog:export">
6 <a-button type="primary" @click="handleExport"> 导出 </a-button> 6 <a-button type="primary" @click="handleExport"> 导出 </a-button>
@@ -103,15 +103,15 @@ export const formSchema: FormSchema[] = [ @@ -103,15 +103,15 @@ export const formSchema: FormSchema[] = [
103 }, 103 },
104 { 104 {
105 field: PackageField.DEVICE_PROFILE_INFO, 105 field: PackageField.DEVICE_PROFILE_INFO,
106 - label: '设备配置', 106 + label: '所属产品',
107 component: 'ApiSearchSelect', 107 component: 'ApiSearchSelect',
108 helpMessage: ['上传的包仅适用于具有所选配置文件的设备'], 108 helpMessage: ['上传的包仅适用于具有所选配置文件的设备'],
109 defaultValue: 'default', 109 defaultValue: 'default',
110 - rules: [{ required: true, message: '设备配置为必填项' }], 110 + rules: [{ required: true, message: '所属产品为必填项' }],
111 componentProps: ({ formActionType }) => { 111 componentProps: ({ formActionType }) => {
112 const { setFieldsValue } = formActionType; 112 const { setFieldsValue } = formActionType;
113 return { 113 return {
114 - placeholder: '请选择设备配置', 114 + placeholder: '请选择所属产品',
115 showSearch: true, 115 showSearch: true,
116 resultField: 'data', 116 resultField: 'data',
117 labelField: 'name', 117 labelField: 'name',
@@ -137,7 +137,7 @@ export const formSchema: FormSchema[] = [ @@ -137,7 +137,7 @@ export const formSchema: FormSchema[] = [
137 field: PackageField.PACKAGE_TYPE, 137 field: PackageField.PACKAGE_TYPE,
138 label: '包类型', 138 label: '包类型',
139 component: 'Select', 139 component: 'Select',
140 - helpMessage: ['上传包后,您将无法修改标题、版本、设备配置文件和包类型'], 140 + helpMessage: ['上传包后,您将无法修改标题、版本、产品文件和包类型'],
141 defaultValue: PackageType.FIRMWARE, 141 defaultValue: PackageType.FIRMWARE,
142 rules: [{ required: true, message: '包类型为必填项' }], 142 rules: [{ required: true, message: '包类型为必填项' }],
143 componentProps: () => { 143 componentProps: () => {
@@ -146,7 +146,7 @@ export const formSchema: FormSchema[] = [ @@ -146,7 +146,7 @@ export const formSchema: FormSchema[] = [
146 { label: '固件', value: PackageType.FIRMWARE }, 146 { label: '固件', value: PackageType.FIRMWARE },
147 { label: '软件', value: PackageType.SOFTWARE }, 147 { label: '软件', value: PackageType.SOFTWARE },
148 ], 148 ],
149 - placeholder: '请选择设备配置', 149 + placeholder: '请选择所属产品',
150 }; 150 };
151 }, 151 },
152 }, 152 },
@@ -21,7 +21,7 @@ export const formSchema: FormSchema[] = [ @@ -21,7 +21,7 @@ export const formSchema: FormSchema[] = [
21 }, 21 },
22 { 22 {
23 field: PackageField.DEVICE_PROFILE_INFO, 23 field: PackageField.DEVICE_PROFILE_INFO,
24 - label: '设备配置', 24 + label: '所属产品',
25 component: 'Input', 25 component: 'Input',
26 }, 26 },
27 { 27 {
@@ -35,7 +35,7 @@ export const formSchema: FormSchema[] = [ @@ -35,7 +35,7 @@ export const formSchema: FormSchema[] = [
35 { label: '固件', value: PackageType.FIRMWARE }, 35 { label: '固件', value: PackageType.FIRMWARE },
36 { label: '软件', value: PackageType.SOFTWARE }, 36 { label: '软件', value: PackageType.SOFTWARE },
37 ], 37 ],
38 - placeholder: '请选择设备配置', 38 + placeholder: '请选择所属产品',
39 }; 39 };
40 }, 40 },
41 }, 41 },
@@ -32,6 +32,8 @@ @@ -32,6 +32,8 @@
32 onClick: handleEdit.bind(null, record), 32 onClick: handleEdit.bind(null, record),
33 ifShow: record.creator === userId && record.status !== 1, 33 ifShow: record.creator === userId && record.status !== 1,
34 }, 34 },
  35 + ]"
  36 + :drop-down-actions="[
35 { 37 {
36 label: '删除', 38 label: '删除',
37 auth: 'api:yt:sceneLinkage:delete', 39 auth: 'api:yt:sceneLinkage:delete',
@@ -60,7 +60,8 @@ @@ -60,7 +60,8 @@
60 converScriptRef.value?.setFormData(data.record); 60 converScriptRef.value?.setFormData(data.record);
61 } 61 }
62 if (unref(isTitle) == 'test') { 62 if (unref(isTitle) == 'test') {
63 - converScriptRef.value?.setScriptContentData(''); 63 + // converScriptRef.value?.setScriptContentData('');
  64 + converScriptRef.value?.setFormData(data.record);
64 } 65 }
65 setModalProps({ title, showOkBtn: true, showCancelBtn: true, okText }); 66 setModalProps({ title, showOkBtn: true, showCancelBtn: true, okText });
66 if (!unref(isUpdate)) { 67 if (!unref(isUpdate)) {
@@ -28,7 +28,7 @@ export const columns: BasicColumn[] = [ @@ -28,7 +28,7 @@ export const columns: BasicColumn[] = [
28 slots: { customRender: 'convertJs' }, 28 slots: { customRender: 'convertJs' },
29 }, 29 },
30 { 30 {
31 - title: '描述', 31 + title: '备注',
32 dataIndex: 'description', 32 dataIndex: 'description',
33 width: 120, 33 width: 120,
34 }, 34 },
@@ -61,6 +61,8 @@ @@ -61,6 +61,8 @@
61 onClick: handleEdit.bind(null, record), 61 onClick: handleEdit.bind(null, record),
62 ifShow: record.level != 0, 62 ifShow: record.level != 0,
63 }, 63 },
  64 + ]"
  65 + :drop-down-actions="[
64 { 66 {
65 label: '删除', 67 label: '删除',
66 auth: 'api:yt:user:delete', 68 auth: 'api:yt:user:delete',
@@ -15,7 +15,7 @@ @@ -15,7 +15,7 @@
15 </script> 15 </script>
16 16
17 <template> 17 <template>
18 - <section class="widget"> 18 + <section class="widget !dark:bg-dark-900">
19 <slot name="header"></slot> 19 <slot name="header"></slot>
20 20
21 <div class="widget-content"> 21 <div class="widget-content">
@@ -45,7 +45,14 @@ @@ -45,7 +45,14 @@
45 45
46 .widget-select:deep(.ant-card-body) { 46 .widget-select:deep(.ant-card-body) {
47 /* height: 240px; */ 47 /* height: 240px; */
48 - width: 240px; 48 +
  49 + /* width: 236px;
  50 + height: 196px; */
  51 +
  52 + /* width: 100%;
  53 + height: 100%; */
  54 + width: 236px;
  55 + height: 236px;
49 padding: 0; 56 padding: 0;
50 box-sizing: border-box; 57 box-sizing: border-box;
51 display: flex; 58 display: flex;
@@ -64,10 +71,18 @@ @@ -64,10 +71,18 @@
64 } 71 }
65 72
66 .widget-select .widget-container { 73 .widget-select .widget-container {
67 - width: 240px;  
68 - height: 200px; 74 + width: 236px;
  75 + height: 196px;
69 display: flex; 76 display: flex;
70 justify-content: center; 77 justify-content: center;
71 align-items: center; 78 align-items: center;
72 } 79 }
  80 +
  81 + [data-theme='dark'] .widget-select:deep(.ant-card-body) {
  82 + @apply bg-dark-900;
  83 + }
  84 +
  85 + [data-theme='dark'] .widget-select:deep(.ant-card) {
  86 + @apply border-dark-300;
  87 + }
73 </style> 88 </style>
@@ -565,6 +565,10 @@ @@ -565,6 +565,10 @@
565 background-color: #fff; 565 background-color: #fff;
566 } 566 }
567 567
  568 + [data-theme='dark'] .board-detail:deep(.ant-page-header-heading) {
  569 + @apply bg-dark-900;
  570 + }
  571 +
568 .board-detail:deep(.ant-page-header-heading-extra) { 572 .board-detail:deep(.ant-page-header-heading-extra) {
569 margin: 0; 573 margin: 0;
570 line-height: 78px; 574 line-height: 78px;
@@ -189,13 +189,13 @@ @@ -189,13 +189,13 @@
189 189
190 <template> 190 <template>
191 <PageWrapper> 191 <PageWrapper>
192 - <div class="flex items-center mb-3 bg-light-100 h-78px"> 192 + <div class="flex items-center mb-3 bg-light-100 h-78px dark:text-gray-300 dark:bg-dark-900">
193 <div class="text-lg ml-30px mr-9px font-bold">自定义看板</div> 193 <div class="text-lg ml-30px mr-9px font-bold">自定义看板</div>
194 <Authority value="api:yt:data_board:add:post"> 194 <Authority value="api:yt:data_board:add:post">
195 <Button type="primary" @click="handleOpenDetailModal">创建看板</Button> 195 <Button type="primary" @click="handleOpenDetailModal">创建看板</Button>
196 </Authority> 196 </Authority>
197 </div> 197 </div>
198 - <div class="bg-light-100 mb-6 w-full p-3 search-form"> 198 + <div class="bg-light-100 mb-6 w-full p-3 search-form dark:text-gray-300 dark:bg-dark-900">
199 <BasicForm class="flex-auto w-full" @register="searchFormRegister" /> 199 <BasicForm class="flex-auto w-full" @register="searchFormRegister" />
200 </div> 200 </div>
201 <Spin :spinning="loading"> 201 <Spin :spinning="loading">
@@ -309,4 +309,9 @@ @@ -309,4 +309,9 @@
309 padding: 10px; 309 padding: 10px;
310 background-color: #fff; 310 background-color: #fff;
311 } 311 }
  312 +
  313 + [data-theme='dark'] .data-board-list:deep(.ant-list-pagination) {
  314 + padding: 10px;
  315 + background-color: #000;
  316 + }
312 </style> 317 </style>