1
|
<script lang="ts" setup>
|
1
|
<script lang="ts" setup>
|
2
|
- import { List, Card, Statistic, Button, Tooltip, Spin } from 'ant-design-vue';
|
|
|
3
|
- import { onMounted, ref, unref } from 'vue';
|
|
|
4
|
- import { PageWrapper } from '/@/components/Page';
|
2
|
+ import { Card, Statistic, Button, Tooltip } from 'ant-design-vue';
|
|
|
3
|
+ import { unref, computed } from 'vue';
|
5
|
import { MoreOutlined, ShareAltOutlined } from '@ant-design/icons-vue';
|
4
|
import { MoreOutlined, ShareAltOutlined } from '@ant-design/icons-vue';
|
6
|
import { useMessage } from '/@/hooks/web/useMessage';
|
5
|
import { useMessage } from '/@/hooks/web/useMessage';
|
7
|
import Dropdown from '/@/components/Dropdown/src/Dropdown.vue';
|
6
|
import Dropdown from '/@/components/Dropdown/src/Dropdown.vue';
|
|
@@ -13,12 +12,8 @@ |
|
@@ -13,12 +12,8 @@ |
13
|
import { DataBoardRecord } from '/@/api/dataBoard/model';
|
12
|
import { DataBoardRecord } from '/@/api/dataBoard/model';
|
14
|
import { ViewType } from './config/panelDetail';
|
13
|
import { ViewType } from './config/panelDetail';
|
15
|
import { useRouter } from 'vue-router';
|
14
|
import { useRouter } from 'vue-router';
|
16
|
- import { getBoundingClientRect } from '/@/utils/domUtils';
|
|
|
17
|
- import Authority from '/@/components/Authority/src/Authority.vue';
|
|
|
18
|
- import { computed } from '@vue/reactivity';
|
|
|
19
|
import { usePermission } from '/@/hooks/web/usePermission';
|
15
|
import { usePermission } from '/@/hooks/web/usePermission';
|
20
|
import { encode } from './config/config';
|
16
|
import { encode } from './config/config';
|
21
|
- import { useForm, BasicForm } from '/@/components/Form';
|
|
|
22
|
import { formSchema } from './config/searchForm';
|
17
|
import { formSchema } from './config/searchForm';
|
23
|
import { ShareModal } from '/@/views/common/ShareModal';
|
18
|
import { ShareModal } from '/@/views/common/ShareModal';
|
24
|
import { ModalParamsType } from '/#/utils';
|
19
|
import { ModalParamsType } from '/#/utils';
|
|
@@ -26,62 +21,23 @@ |
|
@@ -26,62 +21,23 @@ |
26
|
import { useRole } from '/@/hooks/business/useRole';
|
21
|
import { useRole } from '/@/hooks/business/useRole';
|
27
|
import { useClipboard } from '@vueuse/core';
|
22
|
import { useClipboard } from '@vueuse/core';
|
28
|
import { DATA_BOARD_SHARE_URL } from '../palette';
|
23
|
import { DATA_BOARD_SHARE_URL } from '../palette';
|
|
|
24
|
+ import { BasicCardList, useCardList } from '/@/components/CardList';
|
29
|
|
25
|
|
30
|
- const ListItem = List.Item;
|
|
|
31
|
const router = useRouter();
|
26
|
const router = useRouter();
|
32
|
|
27
|
|
33
|
const { createMessage, createConfirm } = useMessage();
|
28
|
const { createMessage, createConfirm } = useMessage();
|
34
|
|
29
|
|
35
|
- const listEL = ref();
|
|
|
36
|
- const loading = ref(false);
|
|
|
37
|
- const dataBoardList = ref<DataBoardRecord[]>([]);
|
|
|
38
|
-
|
|
|
39
|
- const [searchFormRegister, searchFormMethod] = useForm({
|
|
|
40
|
- schemas: formSchema,
|
|
|
41
|
- labelWidth: 80,
|
|
|
42
|
- layout: 'inline',
|
|
|
43
|
- submitButtonOptions: {
|
|
|
44
|
- loading: loading as unknown as boolean,
|
|
|
45
|
- },
|
|
|
46
|
- submitFunc: async () => {
|
|
|
47
|
- try {
|
|
|
48
|
- const params = searchFormMethod.getFieldsValue();
|
|
|
49
|
- await getDatasource(params);
|
|
|
50
|
- } catch (error) {}
|
|
|
51
|
- },
|
|
|
52
|
- resetFunc: async () => {
|
|
|
53
|
- try {
|
|
|
54
|
- await getDatasource();
|
|
|
55
|
- } catch (error) {}
|
30
|
+ const [registerCardList, { reload }] = useCardList({
|
|
|
31
|
+ title: '数据看板',
|
|
|
32
|
+ api: getDataBoardList,
|
|
|
33
|
+ baseLayout: { col: 3, row: 3 },
|
|
|
34
|
+ useSearchForm: true,
|
|
|
35
|
+ formConfig: {
|
|
|
36
|
+ schemas: formSchema,
|
|
|
37
|
+ labelWidth: 80,
|
56
|
},
|
38
|
},
|
57
|
});
|
39
|
});
|
58
|
|
40
|
|
59
|
- // about pagination
|
|
|
60
|
- const page = ref(1);
|
|
|
61
|
- const pageSize = ref(10);
|
|
|
62
|
- const total = ref(0);
|
|
|
63
|
- const paginationProp = ref({
|
|
|
64
|
- showSizeChanger: false,
|
|
|
65
|
- showQuickJumper: true,
|
|
|
66
|
- pageSize,
|
|
|
67
|
- current: page,
|
|
|
68
|
- size: 'small',
|
|
|
69
|
- total,
|
|
|
70
|
- showTotal: (total) => `总 ${total} 条`,
|
|
|
71
|
- onChange: pageChange,
|
|
|
72
|
- onShowSizeChange: pageSizeChange,
|
|
|
73
|
- });
|
|
|
74
|
-
|
|
|
75
|
- function pageChange(p, pz) {
|
|
|
76
|
- page.value = p;
|
|
|
77
|
- pageSize.value = pz;
|
|
|
78
|
- getDatasource();
|
|
|
79
|
- }
|
|
|
80
|
- function pageSizeChange(_current, size) {
|
|
|
81
|
- pageSize.value = size;
|
|
|
82
|
- getDatasource();
|
|
|
83
|
- }
|
|
|
84
|
-
|
|
|
85
|
const createShareUrl = (record: DataBoardRecord) => {
|
41
|
const createShareUrl = (record: DataBoardRecord) => {
|
86
|
const { origin } = location;
|
42
|
const { origin } = location;
|
87
|
const { id, publicId } = record;
|
43
|
const { id, publicId } = record;
|
|
@@ -124,22 +80,6 @@ |
|
@@ -124,22 +80,6 @@ |
124
|
return basicMenu;
|
80
|
return basicMenu;
|
125
|
});
|
81
|
});
|
126
|
|
82
|
|
127
|
- const getDatasource = async (params: Recordable = {}) => {
|
|
|
128
|
- try {
|
|
|
129
|
- loading.value = true;
|
|
|
130
|
- const { total, items } = await getDataBoardList({
|
|
|
131
|
- page: unref(paginationProp).current,
|
|
|
132
|
- pageSize: unref(paginationProp).pageSize,
|
|
|
133
|
- ...params,
|
|
|
134
|
- });
|
|
|
135
|
- dataBoardList.value = items;
|
|
|
136
|
- paginationProp.value.total = total;
|
|
|
137
|
- } catch (error) {
|
|
|
138
|
- } finally {
|
|
|
139
|
- loading.value = false;
|
|
|
140
|
- }
|
|
|
141
|
- };
|
|
|
142
|
-
|
|
|
143
|
const handleOpenShareModal = (record: DataBoardRecord) => {
|
83
|
const handleOpenShareModal = (record: DataBoardRecord) => {
|
144
|
openShareModal(true, {
|
84
|
openShareModal(true, {
|
145
|
record,
|
85
|
record,
|
|
@@ -175,7 +115,7 @@ |
|
@@ -175,7 +115,7 @@ |
175
|
try {
|
115
|
try {
|
176
|
await deleteDataBoard([record.id]);
|
116
|
await deleteDataBoard([record.id]);
|
177
|
createMessage.success('删除成功');
|
117
|
createMessage.success('删除成功');
|
178
|
- await getDatasource();
|
118
|
+ reload();
|
179
|
} catch (error) {}
|
119
|
} catch (error) {}
|
180
|
};
|
120
|
};
|
181
|
|
121
|
|
|
@@ -188,106 +128,67 @@ |
|
@@ -188,106 +128,67 @@ |
188
|
if (hasDetailPermission) {
|
128
|
if (hasDetailPermission) {
|
189
|
const boardId = encode(record.id);
|
129
|
const boardId = encode(record.id);
|
190
|
const boardName = encode(record.name);
|
130
|
const boardName = encode(record.name);
|
191
|
- const organizationId = encode(record?.organizationId);
|
131
|
+ const organizationId = encode(record!.organizationId!);
|
192
|
|
132
|
|
193
|
router.push(`/visual/board/detail/${boardId}/${boardName}/${organizationId}`);
|
133
|
router.push(`/visual/board/detail/${boardId}/${boardName}/${organizationId}`);
|
194
|
} else createMessage.warning('没有权限');
|
134
|
} else createMessage.warning('没有权限');
|
195
|
};
|
135
|
};
|
196
|
-
|
|
|
197
|
- const handlePagenationPosition = () => {
|
|
|
198
|
- const clientHeight = document.documentElement.clientHeight;
|
|
|
199
|
- const rect = getBoundingClientRect(unref(listEL).$el!) as DOMRect;
|
|
|
200
|
- const paginationHeight = 32 + 24 + 16;
|
|
|
201
|
- const listContainerMarginBottom = 16;
|
|
|
202
|
- const listContainerHeight =
|
|
|
203
|
- clientHeight - rect.top - paginationHeight - listContainerMarginBottom;
|
|
|
204
|
- const listContainerEl = (unref(listEL).$el as HTMLElement).querySelector(
|
|
|
205
|
- '.ant-spin-container'
|
|
|
206
|
- ) as HTMLElement;
|
|
|
207
|
- listContainerEl &&
|
|
|
208
|
- (listContainerEl.style.height = listContainerHeight + 'px') &&
|
|
|
209
|
- (listContainerEl.style.overflowY = 'auto') &&
|
|
|
210
|
- (listContainerEl.style.overflowX = 'hidden');
|
|
|
211
|
- };
|
|
|
212
|
-
|
|
|
213
|
- onMounted(() => {
|
|
|
214
|
- getDatasource();
|
|
|
215
|
- handlePagenationPosition();
|
|
|
216
|
- });
|
|
|
217
|
</script>
|
136
|
</script>
|
218
|
|
137
|
|
219
|
<template>
|
138
|
<template>
|
220
|
- <PageWrapper>
|
|
|
221
|
- <div class="flex items-center mb-3 bg-light-100 h-78px dark:text-gray-300 dark:bg-dark-900">
|
|
|
222
|
- <div class="text-lg ml-30px mr-9px font-bold">自定义看板</div>
|
|
|
223
|
- <Authority value="api:yt:data_board:add:post">
|
|
|
224
|
- <Button v-if="!isCustomerUser" type="primary" @click="handleOpenDetailModal"
|
|
|
225
|
- >创建看板</Button
|
|
|
226
|
- >
|
|
|
227
|
- </Authority>
|
|
|
228
|
- </div>
|
|
|
229
|
- <div class="bg-light-100 mb-6 w-full p-3 search-form dark:text-gray-300 dark:bg-dark-900">
|
|
|
230
|
- <BasicForm class="flex-auto w-full" @register="searchFormRegister" />
|
|
|
231
|
- </div>
|
|
|
232
|
- <Spin :spinning="loading">
|
|
|
233
|
- <List
|
|
|
234
|
- ref="listEL"
|
|
|
235
|
- :pagination="paginationProp"
|
|
|
236
|
- :data-source="dataBoardList"
|
|
|
237
|
- :grid="{ gutter: 20, column: 4, xs: 1, sm: 2, md: 2, lg: 3, xl: 3, xxl: 3 }"
|
|
|
238
|
- class="data-board-list"
|
|
|
239
|
- >
|
|
|
240
|
- <template #renderItem="{ item }">
|
|
|
241
|
- <ListItem>
|
|
|
242
|
- <Card class="data-card cursor-pointer">
|
|
|
243
|
- <template #title>
|
|
|
244
|
- <div class="font-bold">{{ item.name }}</div>
|
|
|
245
|
- </template>
|
|
|
246
|
- <template #extra>
|
|
|
247
|
- <Dropdown
|
|
|
248
|
- v-if="!isCustomerUser && dropMenuList.length"
|
|
|
249
|
- :trigger="['click']"
|
|
|
250
|
- @menu-event="(event) => handleMenuEvent(event, item)"
|
|
|
251
|
- :drop-menu-list="dropMenuList"
|
|
|
252
|
- >
|
|
|
253
|
- <MoreOutlined class="rotate-90 transform cursor-pointer" />
|
|
|
254
|
- </Dropdown>
|
|
|
255
|
- </template>
|
|
|
256
|
- <section @click="handleViewBoard(item)">
|
|
|
257
|
- <div class="flex data-card__info">
|
|
|
258
|
- <div>
|
|
|
259
|
- <div>组件数量</div>
|
|
|
260
|
- <Statistic style="font-size: 22px" :value="item.componentNum">
|
|
|
261
|
- <template #suffix>
|
|
|
262
|
- <span class="text-sm">个</span>
|
|
|
263
|
- </template>
|
|
|
264
|
- </Statistic>
|
|
|
265
|
- </div>
|
|
|
266
|
- </div>
|
|
|
267
|
- <div class="flex justify-between mt-4 text-sm" style="color: #999">
|
|
|
268
|
- <div class="flex min-w-20 mr-3">
|
|
|
269
|
- <span>
|
|
|
270
|
- {{ item.viewType === ViewType.PRIVATE_VIEW ? '私有看板' : '公共看板' }}
|
|
|
271
|
- </span>
|
|
|
272
|
- <span v-if="item.viewType === ViewType.PUBLIC_VIEW">
|
|
|
273
|
- <Tooltip title="点击复制分享链接">
|
|
|
274
|
- <ShareAltOutlined class="ml-1" @click.stop="handleCopyShareUrl(item)" />
|
|
|
275
|
- </Tooltip>
|
|
|
276
|
- </span>
|
|
|
277
|
- </div>
|
|
|
278
|
- <Tooltip placement="topLeft" :title="item.createTime">
|
|
|
279
|
- <div class="truncate">{{ item.createTime }}</div>
|
139
|
+ <section>
|
|
|
140
|
+ <BasicCardList @register="registerCardList">
|
|
|
141
|
+ <template #toolbar>
|
|
|
142
|
+ <Button type="primary" @click="handleOpenDetailModal">新增看板</Button>
|
|
|
143
|
+ </template>
|
|
|
144
|
+ <template #renderItem="{ item }: CardListRenderItem<DataBoardRecord>">
|
|
|
145
|
+ <Card class="data-card cursor-pointer">
|
|
|
146
|
+ <template #title>
|
|
|
147
|
+ <div class="font-bold">{{ item.name }}</div>
|
|
|
148
|
+ </template>
|
|
|
149
|
+ <template #extra>
|
|
|
150
|
+ <Dropdown
|
|
|
151
|
+ v-if="!isCustomerUser && dropMenuList.length"
|
|
|
152
|
+ :trigger="['click']"
|
|
|
153
|
+ @menu-event="(event) => handleMenuEvent(event, item)"
|
|
|
154
|
+ :drop-menu-list="dropMenuList"
|
|
|
155
|
+ >
|
|
|
156
|
+ <MoreOutlined class="rotate-90 transform cursor-pointer" />
|
|
|
157
|
+ </Dropdown>
|
|
|
158
|
+ </template>
|
|
|
159
|
+ <section @click="handleViewBoard(item)">
|
|
|
160
|
+ <div class="flex data-card__info">
|
|
|
161
|
+ <div>
|
|
|
162
|
+ <div>组件数量</div>
|
|
|
163
|
+ <Statistic class="text-2xl" :value="item.componentNum">
|
|
|
164
|
+ <template #suffix>
|
|
|
165
|
+ <span class="text-sm">个</span>
|
|
|
166
|
+ </template>
|
|
|
167
|
+ </Statistic>
|
|
|
168
|
+ </div>
|
|
|
169
|
+ </div>
|
|
|
170
|
+ <div class="flex justify-between mt-4 text-sm" style="color: #999">
|
|
|
171
|
+ <div class="flex min-w-20 mr-3">
|
|
|
172
|
+ <span>
|
|
|
173
|
+ {{ item.viewType === ViewType.PRIVATE_VIEW ? '私有看板' : '公共看板' }}
|
|
|
174
|
+ </span>
|
|
|
175
|
+ <span v-if="item.viewType === ViewType.PUBLIC_VIEW">
|
|
|
176
|
+ <Tooltip title="点击复制分享链接">
|
|
|
177
|
+ <ShareAltOutlined class="ml-1" @click.stop="handleCopyShareUrl(item)" />
|
280
|
</Tooltip>
|
178
|
</Tooltip>
|
281
|
- </div>
|
|
|
282
|
- </section>
|
|
|
283
|
- </Card>
|
|
|
284
|
- </ListItem>
|
|
|
285
|
- </template>
|
|
|
286
|
- </List>
|
|
|
287
|
- </Spin>
|
|
|
288
|
- <ShareModal @register="registerShareModal" :shareApi="shareBoard" @success="getDatasource" />
|
|
|
289
|
- <PanelDetailModal @register="registerModal" @change="getDatasource" />
|
|
|
290
|
- </PageWrapper>
|
179
|
+ </span>
|
|
|
180
|
+ </div>
|
|
|
181
|
+ <Tooltip placement="topLeft" :title="item.createTime">
|
|
|
182
|
+ <div class="truncate">{{ item.createTime }}</div>
|
|
|
183
|
+ </Tooltip>
|
|
|
184
|
+ </div>
|
|
|
185
|
+ </section>
|
|
|
186
|
+ </Card>
|
|
|
187
|
+ </template>
|
|
|
188
|
+ </BasicCardList>
|
|
|
189
|
+ <ShareModal @register="registerShareModal" :shareApi="shareBoard" @success="reload()" />
|
|
|
190
|
+ <PanelDetailModal @register="registerModal" @change="reload()" />
|
|
|
191
|
+ </section>
|
291
|
</template>
|
192
|
</template>
|
292
|
|
193
|
|
293
|
<style scoped lang="less">
|
194
|
<style scoped lang="less">
|