Commit 904cbc287aaf24a675f43c50ac5a23e4bf0665fe

Authored by ww
1 parent f5190842

perf: 优化组态管理独立组态页面

@@ -174,13 +174,12 @@ @@ -174,13 +174,12 @@
174 overflow-x: hidden; 174 overflow-x: hidden;
175 overflow-y: auto; 175 overflow-y: auto;
176 176
177 - .ant-row {  
178 - row-gap: 16px;  
179 -  
180 - .ant-list-item {  
181 - margin-bottom: 0;  
182 - }  
183 - } 177 + // .ant-row {
  178 + // .ant-col {
  179 + // }
  180 + // .ant-list-item {
  181 + // }
  182 + // }
184 } 183 }
185 184
186 .ant-list-header { 185 .ant-list-header {
1 import { Ref, computed, reactive, unref } from 'vue'; 1 import { Ref, computed, reactive, unref } from 'vue';
2 import { BasicCardListPropsType, ListGridType } from '../types'; 2 import { BasicCardListPropsType, ListGridType } from '../types';
3 import { getListGridByColumn } from '../utils'; 3 import { getListGridByColumn } from '../utils';
  4 +import { screenMap, sizeEnum } from '/@/enums/breakpointEnum';
4 5
5 export function useListGrid(getProps: Ref<BasicCardListPropsType>) { 6 export function useListGrid(getProps: Ref<BasicCardListPropsType>) {
6 const cardListLayout = reactive({ row: 2, col: 5 }); 7 const cardListLayout = reactive({ row: 2, col: 5 });
@@ -15,8 +16,31 @@ export function useListGrid(getProps: Ref<BasicCardListPropsType>) { @@ -15,8 +16,31 @@ export function useListGrid(getProps: Ref<BasicCardListPropsType>) {
15 } as ListGridType; 16 } as ListGridType;
16 }); 17 });
17 18
  19 + function getScreenSize() {
  20 + const width = document.body.clientWidth;
  21 + const xs = screenMap.get(sizeEnum.XS)!;
  22 + const sm = screenMap.get(sizeEnum.SM)!;
  23 + const md = screenMap.get(sizeEnum.MD)!;
  24 + const lg = screenMap.get(sizeEnum.LG)!;
  25 + const xl = screenMap.get(sizeEnum.XL)!;
  26 + if (width < xs) {
  27 + return sizeEnum.XS;
  28 + } else if (width < sm) {
  29 + return sizeEnum.SM;
  30 + } else if (width < md) {
  31 + return sizeEnum.MD;
  32 + } else if (width < lg) {
  33 + return sizeEnum.LG;
  34 + } else if (width < xl) {
  35 + return sizeEnum.XL;
  36 + } else {
  37 + return sizeEnum.XXL;
  38 + }
  39 + }
  40 +
18 return { 41 return {
19 getListGrid, 42 getListGrid,
20 cardListLayout, 43 cardListLayout,
  44 + getScreenSize,
21 }; 45 };
22 } 46 }
@@ -3,10 +3,10 @@ import { ListGridType } from '../types'; @@ -3,10 +3,10 @@ import { ListGridType } from '../types';
3 export const getListGridByColumn = (col: number): Omit<ListGridType, 'gutter' | 'column'> => { 3 export const getListGridByColumn = (col: number): Omit<ListGridType, 'gutter' | 'column'> => {
4 return { 4 return {
5 xxl: col, 5 xxl: col,
6 - xl: col,  
7 - lg: Math.min(col - 1, 2),  
8 - md: Math.min(col - 1, 2),  
9 - sm: Math.min(col - 2, 2),  
10 - xs: Math.min(col - 2, 2), 6 + xl: Math.max(1, col - 1),
  7 + lg: Math.max(1, col - 2),
  8 + md: Math.max(1, col - 3),
  9 + sm: Math.max(1, col - 4),
  10 + xs: Math.max(1, col - 5),
11 }; 11 };
12 }; 12 };
1 <script setup lang="ts"> 1 <script setup lang="ts">
2 - import { List, Card, Button, PaginationProps, Tooltip } from 'ant-design-vue';  
3 - import { ReloadOutlined } from '@ant-design/icons-vue';  
4 - import { computed, onMounted, reactive, ref, unref } from 'vue';  
5 - import { OrganizationIdTree, useResetOrganizationTree } from '../../common/organizationIdTree'; 2 + import { BasicCardList, useCardList } from '/@/components/CardList';
6 import { 3 import {
7 deleteConfigurationCenter, 4 deleteConfigurationCenter,
8 getPage, 5 getPage,
9 shareConfiguration, 6 shareConfiguration,
10 } from '/@/api/configuration/center/configurationCenter'; 7 } from '/@/api/configuration/center/configurationCenter';
  8 + import { searchFormSchema, ConfigurationPermission } from './center.data';
11 import { ConfigurationCenterItemsModal } from '/@/api/configuration/center/model/configurationCenterModal'; 9 import { ConfigurationCenterItemsModal } from '/@/api/configuration/center/model/configurationCenterModal';
12 - import { PageWrapper } from '/@/components/Page';  
13 - import { BasicForm, useForm } from '/@/components/Form';  
14 - import { ConfigurationPermission, Platform, searchFormSchema } from './center.data';  
15 - import { useMessage } from '/@/hooks/web/useMessage';  
16 import { Authority } from '/@/components/Authority'; 10 import { Authority } from '/@/components/Authority';
17 - import ConfigurationCenterDrawer from './ConfigurationCenterDrawer.vue';  
18 - import { useDrawer } from '/@/components/Drawer';  
19 - import { getBoundingClientRect } from '/@/utils/domUtils'; 11 + import { Button, Card, Tooltip } from 'ant-design-vue';
  12 + import { useRole } from '/@/hooks/business/useRole';
20 import configurationSrc from '/@/assets/icons/configuration.svg'; 13 import configurationSrc from '/@/assets/icons/configuration.svg';
21 - import { cloneDeep } from 'lodash'; 14 + import { Platform } from '../center/center.data';
  15 + import { computed, unref } from 'vue';
  16 + import { createScadaPageLink, ScadaModeEnum } from '../center/help';
  17 + import { useDrawer } from '/@/components/Drawer';
22 import { usePermission } from '/@/hooks/web/usePermission'; 18 import { usePermission } from '/@/hooks/web/usePermission';
23 - import { AuthIcon, CardLayoutButton } from '/@/components/Widget';  
24 - import AuthDropDown from '/@/components/Widget/AuthDropDown.vue';  
25 - import { ShareModal } from '/@/views/common/ShareModal';  
26 - import { ViewTypeNameEnum } from '../../common/ShareModal/config';  
27 - import { useModal } from '/@/components/Modal';  
28 - import { ViewType } from '../../visual/board/config/panelDetail';  
29 - import { useRole } from '/@/hooks/business/useRole';  
30 - import { useClipboard } from '@vueuse/core'; 19 + import { useMessage } from '/@/hooks/web/useMessage';
31 import { Icon } from '/@/components/Icon'; 20 import { Icon } from '/@/components/Icon';
32 - import { createScadaPageLink, ScadaModeEnum } from './help';  
33 -  
34 - const listColumn = ref(5);  
35 -  
36 - const { createMessage } = useMessage();  
37 -  
38 - const { isCustomerUser } = useRole();  
39 -  
40 - const organizationId = ref<Nullable<number>>(null); 21 + import { AuthIcon, AuthDropDown } from '/@/components/Widget';
  22 + import { cloneDeep } from 'lodash-es';
  23 + import { OrganizationIdTree, useOrganizationTree } from '../../common/organizationIdTree';
  24 + import ConfigurationCenterDrawer from './ConfigurationCenterDrawer.vue';
  25 + import { useClipboard } from '@vueuse/core';
  26 + import { useModal } from '/@/components/Modal';
  27 + import { ShareModal } from '/@/views/common/ShareModal';
41 28
42 - const pagination = reactive<PaginationProps>({  
43 - size: 'small',  
44 - showTotal: (total: number) => `共 ${total} 条数据`,  
45 - current: 1,  
46 - pageSize: unref(listColumn) * 2,  
47 - onChange: (page: number) => {  
48 - pagination.current = page;  
49 - getListData(); 29 + const [register, { reload }] = useCardList({
  30 + api: getPage,
  31 + useSearchForm: true,
  32 + formConfig: {
  33 + schemas: searchFormSchema,
  34 + labelWidth: 80,
  35 + resetFunc: async () => {
  36 + clearSelected();
  37 + },
  38 + },
  39 + beforeFetch: async (params: Recordable) => {
  40 + return { ...params, organizationId: getSelectKey(), isTemplate: 0 };
50 }, 41 },
51 }); 42 });
52 43
53 - const loading = ref(false);  
54 -  
55 - const dataSource = ref<ConfigurationCenterItemsModal[]>([]);  
56 -  
57 - const [registerForm, { getFieldsValue }] = useForm({  
58 - schemas: searchFormSchema,  
59 - showAdvancedButton: true,  
60 - labelWidth: 100,  
61 - compact: true,  
62 - resetFunc: () => {  
63 - resetFn();  
64 - organizationId.value = null;  
65 - return getListData();  
66 - },  
67 - submitFunc: async () => {  
68 - const value = getFieldsValue();  
69 - getListData(value); 44 + const [registerOrgTree, { getSelectKey, clearSelected }] = useOrganizationTree({
  45 + onSelect: () => {
  46 + reload();
70 }, 47 },
71 }); 48 });
72 49
73 - async function getListData(value: Recordable = {}) {  
74 - try {  
75 - loading.value = true;  
76 - const pageSize = unref(listColumn) * 2;  
77 - const { items, total } = await getPage({  
78 - organizationId: unref(organizationId),  
79 - ...value,  
80 - isTemplate: 0,  
81 - page: pagination.current!,  
82 - pageSize,  
83 - });  
84 -  
85 - dataSource.value = items;  
86 - Object.assign(pagination, { total, pageSize });  
87 - } catch (error) {  
88 - } finally {  
89 - loading.value = false;  
90 - }  
91 - } 50 + const [registerDrawer, { openDrawer }] = useDrawer();
92 51
93 - onMounted(() => {  
94 - getListData();  
95 - }); 52 + const [registerShareModal, { openModal }] = useModal();
96 53
97 - const searchInfo = reactive<Recordable>({});  
98 - const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo);  
99 - const handleSelect = (orgId: number) => {  
100 - organizationId.value = orgId;  
101 - getListData(); 54 + const handleOpenShareModal = (record: ConfigurationCenterItemsModal) => {
  55 + openModal(true, { record, href: createShareUrl(record) });
102 }; 56 };
103 57
104 - const [registerDrawer, { openDrawer }] = useDrawer(); 58 + const { createMessage } = useMessage();
  59 +
  60 + const { isCustomerUser } = useRole();
105 61
106 const { hasPermission } = usePermission(); 62 const { hasPermission } = usePermission();
107 63
@@ -141,19 +97,6 @@ @@ -141,19 +97,6 @@
141 createScadaPageLink(record, ScadaModeEnum.DESIGN); 97 createScadaPageLink(record, ScadaModeEnum.DESIGN);
142 }; 98 };
143 99
144 - const handleDelete = async (record: ConfigurationCenterItemsModal) => {  
145 - try {  
146 - await deleteConfigurationCenter([record.id]);  
147 - createMessage.success('删除成功');  
148 - await getListData();  
149 - } catch (error) {}  
150 - };  
151 -  
152 - const handleCardLayoutChange = () => {  
153 - pagination.current = 1;  
154 - getListData();  
155 - };  
156 -  
157 const createShareUrl = (record: ConfigurationCenterItemsModal) => { 100 const createShareUrl = (record: ConfigurationCenterItemsModal) => {
158 return createScadaPageLink(record, ScadaModeEnum.SHARE, false); 101 return createScadaPageLink(record, ScadaModeEnum.SHARE, false);
159 }; 102 };
@@ -168,209 +111,130 @@ @@ -168,209 +111,130 @@
168 } 111 }
169 }; 112 };
170 113
171 - const [registerShareModal, { openModal }] = useModal();  
172 -  
173 - const handleOpenShareModal = (record: ConfigurationCenterItemsModal) => {  
174 - openModal(true, { record, href: createShareUrl(record) }); 114 + const handleDelete = async (record: ConfigurationCenterItemsModal) => {
  115 + try {
  116 + await deleteConfigurationCenter([record.id]);
  117 + createMessage.success('删除成功');
  118 + await reload();
  119 + } catch (error) {}
175 }; 120 };
176 -  
177 - const listEl = ref<Nullable<ComponentElRef>>(null);  
178 -  
179 - onMounted(() => {  
180 - const clientHeight = document.documentElement.clientHeight;  
181 - const rect = getBoundingClientRect(unref(listEl)!.$el! as HTMLElement) as DOMRect;  
182 - // margin-top 24 height 24  
183 - const paginationHeight = 24 + 24 + 8;  
184 - // list pading top 8 maring-top 8 extra slot 56  
185 - const listContainerMarginBottom = 8 + 8 + 56;  
186 - const listContainerHeight =  
187 - clientHeight - rect.top - paginationHeight - listContainerMarginBottom;  
188 - const listContainerEl = (unref(listEl)!.$el as HTMLElement).querySelector(  
189 - '.ant-spin-container'  
190 - ) as HTMLElement;  
191 - listContainerEl &&  
192 - (listContainerEl.style.height = listContainerHeight + 'px') &&  
193 - (listContainerEl.style.overflowY = 'auto') &&  
194 - (listContainerEl.style.overflowX = 'hidden');  
195 - });  
196 </script> 121 </script>
197 122
198 <template> 123 <template>
199 - <PageWrapper dense contentFullHeight contentClass="flex">  
200 - <OrganizationIdTree @select="handleSelect" ref="organizationIdTreeRef" />  
201 - <section class="flex-auto p-4 w-3/4 xl:w-4/5 w-full configuration-list">  
202 - <div class="flex-auto w-full bg-light-50 dark:bg-dark-900 p-4">  
203 - <BasicForm @register="registerForm" />  
204 - </div>  
205 - <List  
206 - ref="listEl"  
207 - :loading="loading"  
208 - class="flex-auto bg-light-50 dark:bg-dark-900 !p-2 !mt-4"  
209 - position="bottom"  
210 - :pagination="pagination"  
211 - :data-source="dataSource"  
212 - :grid="{ gutter: 4, column: listColumn }"  
213 - >  
214 - <template #header>  
215 - <div class="flex gap-3 justify-end">  
216 - <Authority v-if="!isCustomerUser" :value="ConfigurationPermission.CREATE">  
217 - <Button type="primary" @click="handleCreateOrUpdate()">新增组态</Button>  
218 - </Authority>  
219 - <CardLayoutButton v-model:value="listColumn" @change="handleCardLayoutChange" />  
220 - <Tooltip title="刷新">  
221 - <Button type="primary" @click="getListData">  
222 - <ReloadOutlined />  
223 - </Button>  
224 - </Tooltip>  
225 - </div>  
226 - </template>  
227 - <template #renderItem="{ item }">  
228 - <List.Item>  
229 - <Card  
230 - :style="{  
231 - '--viewType': item.viewType === ViewType.PUBLIC_VIEW ? '#1890ff' : '#faad14',  
232 - }"  
233 - hoverable  
234 - class="card-container" 124 + <section class="flex w-full h-full">
  125 + <OrganizationIdTree @register="registerOrgTree" />
  126 + <BasicCardList class="flex-auto p-4 w-3/4 xl:w-4/5 w-full" @register="register">
  127 + <template #toolbar>
  128 + <div class="flex gap-3 justify-end">
  129 + <Authority v-if="!isCustomerUser" :value="ConfigurationPermission.CREATE">
  130 + <Button type="primary" @click="handleCreateOrUpdate()">新增组态</Button>
  131 + </Authority>
  132 + </div>
  133 + </template>
  134 + <template #renderItem="{ item }: CardListRenderItem<ConfigurationCenterItemsModal>">
  135 + <Card
  136 + :style="{
  137 + '--viewType': '#1890ff',
  138 + }"
  139 + hoverable
  140 + class="card-container"
  141 + >
  142 + <template #cover>
  143 + <div
  144 + class="img-container h-full w-full !flex justify-center items-center text-center p-1 relative"
235 > 145 >
236 - <template #cover>  
237 - <div  
238 - class="img-container h-full w-full !flex justify-center items-center text-center p-1 relative"  
239 - >  
240 - <img  
241 - class="w-full h-36"  
242 - alt="example"  
243 - :src="item.thumbnail || configurationSrc"  
244 - @click="handlePreview(item)" 146 + <img
  147 + class="w-full h-36"
  148 + alt="example"
  149 + :src="item.thumbnail || configurationSrc"
  150 + @click="handlePreview(item)"
  151 + />
  152 + <span class="absolute top-0 left-0 text-light-50 transform -rotate-45 translate-y-1">
  153 + 母版
  154 + </span>
  155 + </div>
  156 + </template>
  157 + <template class="ant-card-actions" #actions>
  158 + <Tooltip title="预览">
  159 + <AuthIcon
  160 + :auth="ConfigurationPermission.PREVIEW"
  161 + class="!text-lg"
  162 + icon="ant-design:eye-outlined"
  163 + @click="handlePreview(item)"
  164 + />
  165 + </Tooltip>
  166 + <Tooltip v-if="!isCustomerUser" title="设计">
  167 + <AuthIcon
  168 + :auth="ConfigurationPermission.DESIGN"
  169 + class="!text-lg"
  170 + icon="ant-design:edit-outlined"
  171 + @click="handleDesign(item)"
  172 + />
  173 + </Tooltip>
  174 + <Tooltip title="点击复制分享链接">
  175 + <AuthIcon
  176 + :auth="ConfigurationPermission.SHARE"
  177 + :disabled="!item.publicId"
  178 + class="!text-lg"
  179 + icon="ant-design:share-alt-outlined"
  180 + @click="handleCreateShareUrl(item)"
  181 + />
  182 + </Tooltip>
  183 + <AuthDropDown
  184 + v-if="!isCustomerUser"
  185 + :dropMenuList="[
  186 + {
  187 + text: '分享',
  188 + auth: ConfigurationPermission.SHARE,
  189 + icon: 'ant-design:share-alt-outlined',
  190 + event: '',
  191 + onClick: handleOpenShareModal.bind(null, item),
  192 + },
  193 + {
  194 + text: '编辑',
  195 + auth: ConfigurationPermission.UPDATE,
  196 + icon: 'clarity:note-edit-line',
  197 + event: '',
  198 + onClick: handleCreateOrUpdate.bind(null, item),
  199 + },
  200 + {
  201 + text: '删除',
  202 + auth: ConfigurationPermission.DELETE,
  203 + icon: 'ant-design:delete-outlined',
  204 + event: '',
  205 + popconfirm: {
  206 + title: '是否确认删除操作?',
  207 + onConfirm: handleDelete.bind(null, item),
  208 + },
  209 + },
  210 + ]"
  211 + :trigger="['hover']"
  212 + />
  213 + </template>
  214 + <Card.Meta>
  215 + <template #title>
  216 + <span class="truncate">{{ item.name }}</span>
  217 + </template>
  218 + <template #description>
  219 + <div class="truncate h-11">
  220 + <div class="truncate flex justify-between items-center">
  221 + <div>{{ item.organizationDTO?.name }}</div>
  222 + <Icon
  223 + :icon="
  224 + item.platform === Platform.PC
  225 + ? 'ri:computer-line'
  226 + : 'clarity:mobile-phone-solid'
  227 + "
245 /> 228 />
246 - <span  
247 - class="absolute top-0 left-0 text-light-50 transform -rotate-45 translate-y-1"  
248 - >  
249 - {{ ViewTypeNameEnum[item.viewType] || ViewTypeNameEnum.PRIVATE_VIEW }}  
250 - </span>  
251 </div> 229 </div>
252 - </template>  
253 - <template class="ant-card-actions" #actions>  
254 - <Tooltip title="预览">  
255 - <AuthIcon  
256 - :auth="ConfigurationPermission.PREVIEW"  
257 - class="!text-lg"  
258 - icon="ant-design:eye-outlined"  
259 - @click="handlePreview(item)"  
260 - />  
261 - </Tooltip>  
262 - <Tooltip v-if="!isCustomerUser" title="设计">  
263 - <AuthIcon  
264 - :auth="ConfigurationPermission.DESIGN"  
265 - class="!text-lg"  
266 - icon="ant-design:edit-outlined"  
267 - @click="handleDesign(item)"  
268 - />  
269 - </Tooltip>  
270 - <Tooltip title="点击复制分享链接">  
271 - <AuthIcon  
272 - :auth="ConfigurationPermission.SHARE"  
273 - :disabled="!item.publicId"  
274 - class="!text-lg"  
275 - icon="ant-design:share-alt-outlined"  
276 - @click="handleCreateShareUrl(item)"  
277 - />  
278 - </Tooltip>  
279 - <AuthDropDown  
280 - v-if="!isCustomerUser"  
281 - :dropMenuList="[  
282 - {  
283 - text: '分享',  
284 - auth: ConfigurationPermission.SHARE,  
285 - icon: 'ant-design:share-alt-outlined',  
286 - event: '',  
287 - onClick: handleOpenShareModal.bind(null, item),  
288 - },  
289 - {  
290 - text: '编辑',  
291 - auth: ConfigurationPermission.UPDATE,  
292 - icon: 'clarity:note-edit-line',  
293 - event: '',  
294 - onClick: handleCreateOrUpdate.bind(null, item),  
295 - },  
296 - {  
297 - text: '删除',  
298 - auth: ConfigurationPermission.DELETE,  
299 - icon: 'ant-design:delete-outlined',  
300 - event: '',  
301 - popconfirm: {  
302 - title: '是否确认删除操作?',  
303 - onConfirm: handleDelete.bind(null, item),  
304 - },  
305 - },  
306 - ]"  
307 - :trigger="['hover']"  
308 - />  
309 - </template>  
310 - <Card.Meta>  
311 - <template #title>  
312 - <span class="truncate">{{ item.name }}</span>  
313 - </template>  
314 - <template #description>  
315 - <div class="truncate h-11">  
316 - <div class="truncate flex justify-between items-center">  
317 - <div>{{ item.organizationDTO.name }}</div>  
318 - <Icon  
319 - :icon="  
320 - item.platform === Platform.PC  
321 - ? 'ri:computer-line'  
322 - : 'clarity:mobile-phone-solid'  
323 - "  
324 - />  
325 - </div>  
326 - <div class="truncate">{{ item.remark || '' }} </div>  
327 - </div>  
328 - </template>  
329 - </Card.Meta>  
330 - </Card>  
331 - </List.Item>  
332 - </template>  
333 - </List>  
334 - </section>  
335 - <ConfigurationCenterDrawer @register="registerDrawer" @success="getListData" />  
336 - <ShareModal  
337 - @register="registerShareModal"  
338 - :shareApi="shareConfiguration"  
339 - @success="getListData"  
340 - />  
341 - </PageWrapper> 230 + <div class="truncate">{{ item.remark || '' }} </div>
  231 + </div>
  232 + </template>
  233 + </Card.Meta>
  234 + </Card>
  235 + </template>
  236 + </BasicCardList>
  237 + <ConfigurationCenterDrawer @register="registerDrawer" @success="reload()" />
  238 + <ShareModal @register="registerShareModal" :shareApi="shareConfiguration" @success="reload" />
  239 + </section>
342 </template> 240 </template>
343 -  
344 -<style lang="less" scoped>  
345 - .configuration-list:deep(.ant-list-header) {  
346 - border-bottom: none !important;  
347 - }  
348 -  
349 - .configuration-list:deep(.ant-list-pagination) {  
350 - height: 24px;  
351 - }  
352 -  
353 - .configuration-list:deep(.ant-card-body) {  
354 - padding: 16px !important;  
355 - }  
356 -  
357 - .configuration-list:deep(.ant-list-empty-text) {  
358 - @apply w-full h-full flex justify-center items-center;  
359 - }  
360 -  
361 - .card-container {  
362 - // background-color: red;  
363 - .img-container {  
364 - border-top-left-radius: 80px;  
365 - background-color: #fff;  
366 -  
367 - img {  
368 - border-top-left-radius: 80px;  
369 - }  
370 - }  
371 - }  
372 -  
373 - .card-container:deep(.ant-card-cover) {  
374 - background-color: var(--viewType);  
375 - }  
376 -</style>