Commit 01f7c9e054dc1fea857a769d8dd930c6d23088d4

Authored by ww
1 parent 64868c79

feat: 新增组态分享功能

... ... @@ -10,6 +10,7 @@ import { FileUploadResponse } from '../../oem/model';
10 10 enum API {
11 11 basicUrl = '/configuration/center',
12 12 UPLOAD = '/oss/upload',
  13 + SHARE = '/configuration/center/share',
13 14 }
14 15
15 16 export const getPage = (params: queryPageParams) => {
... ... @@ -49,3 +50,20 @@ export const saveOrUpdateConfigurationCenter = (
49 50 export const uploadThumbnail = (file: FormData) => {
50 51 return defHttp.post<FileUploadResponse>({ url: API.UPLOAD, params: file });
51 52 };
  53 +
  54 +export const shareConfiguration = (record: {
  55 + id: string;
  56 + isShare: boolean;
  57 + accessCredentials: string;
  58 +}) => {
  59 + const { accessCredentials, isShare, id } = record;
  60 + return defHttp.post(
  61 + {
  62 + url: `${API.SHARE}/${id}`,
  63 + params: { isShare, ...(accessCredentials ? { accessCredentials } : {}) },
  64 + },
  65 + {
  66 + joinParamsToUrl: true,
  67 + }
  68 + );
  69 +};
... ...
... ... @@ -6,6 +6,7 @@ export interface ConfigurationCenterItemsModal {
6 6 createTime: string;
7 7 creator: string;
8 8 remark: string;
  9 + publicId?: string;
9 10 }
10 11 export type queryPageParams = BasicPageParams & {
11 12 name?: Nullable<string>;
... ...
src/views/common/ShareModal/config/index.ts renamed from src/views/visual/board/config/share.ts
1 1 import { FormSchema } from '/@/components/Form';
2 2
  3 +export enum ViewTypeEnum {
  4 + PRIVATE_VIEW = 'PRIVATE_VIEW',
  5 + PUBLIC_VIEW = 'PUBLIC_VIEW',
  6 +}
  7 +
  8 +export enum ViewTypeNameEnum {
  9 + PRIVATE_VIEW = '私有',
  10 + PUBLIC_VIEW = '公共',
  11 +}
  12 +
3 13 export enum FieldsEnum {
4 14 IS_SHARE = 'isShare',
5 15 ACCESS_CREDENTIALS = 'accessCredentials',
... ...
  1 +export { default as ShareModal } from './index.vue';
... ...
src/views/common/ShareModal/index.vue renamed from src/views/visual/board/components/ShareModal.vue
1 1 <script lang="ts" setup>
2 2 import { BasicForm, useForm } from '/@/components/Form';
3 3 import { BasicModal, useModalInner } from '/@/components/Modal';
4   - import { FieldsEnum, schemas } from '../config/share';
  4 + import { FieldsEnum, schemas, ViewTypeEnum } from './config';
5 5 import { DataBoardRecord } from '/@/api/dataBoard/model';
6 6 import { Alert } from 'ant-design-vue';
7 7 import { ref, unref } from 'vue';
8   - import { shareBoard } from '/@/api/dataBoard';
9   - import { ViewType } from '../config/panelDetail';
10 8 import { nextTick } from 'vue';
11 9
  10 + const props = defineProps<{
  11 + shareApi?: (...args: any[]) => Promise<any>;
  12 + }>();
  13 +
12 14 const loading = ref(false);
13 15 const record = ref<DataBoardRecord>({} as unknown as DataBoardRecord);
14 16
... ... @@ -16,7 +18,7 @@
16 18 record.value = data;
17 19 await nextTick();
18 20 setFieldsValue({
19   - [FieldsEnum.IS_SHARE]: data.viewType === ViewType.PUBLIC_VIEW,
  21 + [FieldsEnum.IS_SHARE]: data.viewType === ViewTypeEnum.PUBLIC_VIEW,
20 22 [FieldsEnum.ACCESS_CREDENTIALS]: data.accessCredentials,
21 23 });
22 24 });
... ... @@ -35,7 +37,7 @@
35 37 loading.value = true;
36 38 const value = getFieldsValue();
37 39 const { id } = unref(record);
38   - await shareBoard({ id, ...value });
  40 + await props?.shareApi?.({ id, ...value });
39 41 closeModal();
40 42 emit('success');
41 43 } finally {
... ... @@ -45,7 +47,7 @@
45 47 </script>
46 48
47 49 <template>
48   - <BasicModal title="分享" @register="register" @ok="handleSubmit" :loading="loading">
  50 + <BasicModal title="分享" @register="register" @ok="handleSubmit" :okButtonProps="{ loading }">
49 51 <Alert
50 52 class="!mb-4"
51 53 type="info"
... ...
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';
6   - import {
7   - deleteConfigurationCenter,
8   - getPage,
9   - } from '/@/api/configuration/center/configurationCenter';
10   - import { ConfigurationCenterItemsModal } from '/@/api/configuration/center/model/configurationCenterModal';
11   - import { PageWrapper } from '/@/components/Page';
12   - import { BasicForm, useForm } from '/@/components/Form';
13   - import { ConfigurationPermission, searchFormSchema } from './center.data';
14   - import { useMessage } from '/@/hooks/web/useMessage';
15   - import { Authority } from '/@/components/Authority';
16   - import { isDevMode } from '/@/utils/env';
17   - import ConfigurationCenterDrawer from './ConfigurationCenterDrawer.vue';
18   - import { useDrawer } from '/@/components/Drawer';
19   - import { getBoundingClientRect } from '/@/utils/domUtils';
20   - import configurationSrc from '/@/assets/icons/configuration.svg';
21   - import { cloneDeep } from 'lodash';
22   - import { usePermission } from '/@/hooks/web/usePermission';
23   - import { useGlobSetting } from '/@/hooks/setting';
24   - import { AuthIcon, CardLayoutButton } from '/@/components/Widget';
25   - import AuthDropDown from '/@/components/Widget/AuthDropDown.vue';
26   -
27   - const listColumn = ref(5);
28   -
29   - const { createMessage } = useMessage();
30   -
31   - const organizationId = ref<Nullable<number>>(null);
32   -
33   - const pagination = reactive<PaginationProps>({
34   - size: 'small',
35   - showTotal: (total: number) => `共 ${total} 条数据`,
36   - current: 1,
37   - pageSize: unref(listColumn) * 2,
38   - onChange: (page: number) => {
39   - pagination.current = page;
40   - getListData();
41   - },
42   - });
43   -
44   - const loading = ref(false);
45   -
46   - const dataSource = ref<ConfigurationCenterItemsModal[]>([]);
47   -
48   - const [registerForm, { getFieldsValue }] = useForm({
49   - schemas: searchFormSchema,
50   - showAdvancedButton: true,
51   - labelWidth: 100,
52   - compact: true,
53   - resetFunc: () => {
54   - resetFn();
55   - organizationId.value = null;
56   - return getListData();
57   - },
58   - submitFunc: async () => {
59   - const value = getFieldsValue();
60   - getListData(value);
61   - },
62   - });
63   -
64   - async function getListData(value: Recordable = {}) {
65   - try {
66   - loading.value = true;
67   - const pageSize = unref(listColumn) * 2;
68   - const { items, total } = await getPage({
69   - organizationId: unref(organizationId),
70   - ...value,
71   - page: pagination.current!,
72   - pageSize,
73   - });
74   -
75   - dataSource.value = items;
76   - Object.assign(pagination, { total, pageSize });
77   - } catch (error) {
78   - } finally {
79   - loading.value = false;
80   - }
81   - }
82   -
83   - onMounted(() => {
84   - getListData();
85   - });
86   -
87   - const searchInfo = reactive<Recordable>({});
88   - const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo);
89   - const handleSelect = (orgId: number) => {
90   - organizationId.value = orgId;
91   - getListData();
92   - };
93   -
94   - const [registerDrawer, { openDrawer }] = useDrawer();
95   -
96   - const { hasPermission } = usePermission();
97   -
98   - const getPreviewFlag = computed(() => {
99   - return hasPermission(ConfigurationPermission.PREVIEW);
100   - });
101   -
102   - const getDesignFlag = computed(() => {
103   - return hasPermission(ConfigurationPermission.DESIGN);
104   - });
105   -
106   - const handleCreateOrUpdate = (record?: ConfigurationCenterItemsModal) => {
107   - if (record) {
108   - openDrawer(true, {
109   - isUpdate: true,
110   - record: cloneDeep(record),
111   - });
112   - } else {
113   - openDrawer(true, {
114   - isUpdate: false,
115   - });
116   - }
117   - };
118   -
119   - const { configurationPrefix } = useGlobSetting();
120   - const isDev = isDevMode();
121   -
122   - const handlePreview = (record: ConfigurationCenterItemsModal) => {
123   - if (!unref(getPreviewFlag)) return;
124   - window.open(
125   - `${configurationPrefix}/${isDev ? '?dev=1&' : '?'}configurationId=${record!.id}&lightbox=1`
126   - );
127   - };
128   -
129   - const handleDesign = (record: ConfigurationCenterItemsModal) => {
130   - if (!unref(getDesignFlag)) return;
131   - window.open(`${configurationPrefix}/${isDev ? '?dev=1&' : '?'}configurationId=${record!.id}`);
132   - };
133   -
134   - const handleDelete = async (record: ConfigurationCenterItemsModal) => {
135   - try {
136   - await deleteConfigurationCenter([record.id]);
137   - createMessage.success('删除成功');
138   - await getListData();
139   - } catch (error) {}
140   - };
141   -
142   - const handleCardLayoutChange = () => {
143   - pagination.current = 1;
144   - getListData();
145   - };
146   -
147   - const listEl = ref<Nullable<ComponentElRef>>(null);
148   -
149   - onMounted(() => {
150   - const clientHeight = document.documentElement.clientHeight;
151   - const rect = getBoundingClientRect(unref(listEl)!.$el!) as DOMRect;
152   - // margin-top 24 height 24
153   - const paginationHeight = 24 + 24 + 8;
154   - // list pading top 8 maring-top 8 extra slot 56
155   - const listContainerMarginBottom = 8 + 8 + 56;
156   - const listContainerHeight =
157   - clientHeight - rect.top - paginationHeight - listContainerMarginBottom;
158   - const listContainerEl = (unref(listEl)!.$el as HTMLElement).querySelector(
159   - '.ant-spin-container'
160   - ) as HTMLElement;
161   - listContainerEl &&
162   - (listContainerEl.style.height = listContainerHeight + 'px') &&
163   - (listContainerEl.style.overflowY = 'auto') &&
164   - (listContainerEl.style.overflowX = 'hidden');
165   - });
166   -</script>
167   -
168   -<template>
169   - <PageWrapper dense contentFullHeight contentClass="flex">
170   - <OrganizationIdTree @select="handleSelect" ref="organizationIdTreeRef" />
171   - <section class="flex-auto p-4 w-3/4 xl:w-4/5 w-full configuration-list">
172   - <div class="flex-auto w-full bg-light-50 dark:bg-dark-900 p-4">
173   - <BasicForm @register="registerForm" />
174   - </div>
175   - <List
176   - ref="listEl"
177   - :loading="loading"
178   - class="flex-auto bg-light-50 dark:bg-dark-900 !p-2 !mt-4"
179   - position="bottom"
180   - :pagination="pagination"
181   - :data-source="dataSource"
182   - :grid="{ gutter: 4, column: listColumn }"
183   - >
184   - <template #header>
185   - <div class="flex gap-3 justify-end">
186   - <Authority :value="ConfigurationPermission.CREATE">
187   - <Button type="primary" @click="handleCreateOrUpdate()">新增组态</Button>
188   - </Authority>
189   - <CardLayoutButton v-model:value="listColumn" @change="handleCardLayoutChange" />
190   - <Tooltip title="刷新">
191   - <Button type="primary" @click="getListData">
192   - <ReloadOutlined />
193   - </Button>
194   - </Tooltip>
195   - </div>
196   - </template>
197   - <template #renderItem="{ item }">
198   - <List.Item>
199   - <Card hoverable>
200   - <template #cover>
201   - <div class="h-full w-full !flex justify-center items-center text-center p-1">
202   - <img
203   - class="w-full h-36"
204   - alt="example"
205   - :src="item.thumbnail || configurationSrc"
206   - @click="handlePreview(item)"
207   - />
208   - </div>
209   - </template>
210   - <template class="ant-card-actions" #actions>
211   - <Tooltip title="预览">
212   - <AuthIcon
213   - :auth="ConfigurationPermission.PREVIEW"
214   - class="!text-lg"
215   - icon="ant-design:eye-outlined"
216   - @click="handlePreview(item)"
217   - />
218   - </Tooltip>
219   - <Tooltip title="设计">
220   - <AuthIcon
221   - :auth="ConfigurationPermission.DESIGN"
222   - class="!text-lg"
223   - icon="ant-design:edit-outlined"
224   - @click="handleDesign(item)"
225   - />
226   - </Tooltip>
227   - <AuthDropDown
228   - :dropMenuList="[
229   - {
230   - text: '编辑',
231   - auth: ConfigurationPermission.UPDATE,
232   - icon: 'clarity:note-edit-line',
233   - event: '',
234   - onClick: handleCreateOrUpdate.bind(null, item),
235   - },
236   - {
237   - text: '删除',
238   - auth: ConfigurationPermission.DELETE,
239   - icon: 'ant-design:delete-outlined',
240   - event: '',
241   - popconfirm: {
242   - title: '是否确认删除操作?',
243   - onConfirm: handleDelete.bind(null, item),
244   - },
245   - },
246   - ]"
247   - :trigger="['hover']"
248   - />
249   - </template>
250   - <Card.Meta>
251   - <template #title>
252   - <span class="truncate">{{ item.name }}</span>
253   - </template>
254   - <template #description>
255   - <div class="truncate h-11">
256   - <div class="truncate">{{ item.organizationDTO.name }}</div>
257   - <div class="truncate">{{ item.remark || '' }} </div>
258   - </div>
259   - </template>
260   - </Card.Meta>
261   - </Card>
262   - </List.Item>
263   - </template>
264   - </List>
265   - </section>
266   - <ConfigurationCenterDrawer @register="registerDrawer" @success="getListData" />
267   - </PageWrapper>
268   -</template>
269   -
270   -<style lang="less" scoped>
271   - .configuration-list:deep(.ant-list-header) {
272   - border-bottom: none !important;
273   - }
274   -
275   - .configuration-list:deep(.ant-list-pagination) {
276   - height: 24px;
277   - }
278   -
279   - .configuration-list:deep(.ant-card-body) {
280   - padding: 16px !important;
281   - }
282   -
283   - .configuration-list:deep(.ant-list-empty-text) {
284   - @apply w-full h-full flex justify-center items-center;
285   - }
286   -</style>
  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';
  6 + import {
  7 + deleteConfigurationCenter,
  8 + getPage,
  9 + shareConfiguration,
  10 + } from '/@/api/configuration/center/configurationCenter';
  11 + import { ConfigurationCenterItemsModal } from '/@/api/configuration/center/model/configurationCenterModal';
  12 + import { PageWrapper } from '/@/components/Page';
  13 + import { BasicForm, useForm } from '/@/components/Form';
  14 + import { ConfigurationPermission, searchFormSchema } from './center.data';
  15 + import { useMessage } from '/@/hooks/web/useMessage';
  16 + import { Authority } from '/@/components/Authority';
  17 + import { isDevMode } from '/@/utils/env';
  18 + import ConfigurationCenterDrawer from './ConfigurationCenterDrawer.vue';
  19 + import { useDrawer } from '/@/components/Drawer';
  20 + import { getBoundingClientRect } from '/@/utils/domUtils';
  21 + import configurationSrc from '/@/assets/icons/configuration.svg';
  22 + import { cloneDeep } from 'lodash';
  23 + import { usePermission } from '/@/hooks/web/usePermission';
  24 + import { useGlobSetting } from '/@/hooks/setting';
  25 + import { AuthIcon, CardLayoutButton } from '/@/components/Widget';
  26 + import AuthDropDown from '/@/components/Widget/AuthDropDown.vue';
  27 + import { ShareModal } from '/@/views/common/ShareModal';
  28 + import { ViewTypeNameEnum } from '../../common/ShareModal/config';
  29 + import { useModal } from '/@/components/Modal';
  30 + import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
  31 +
  32 + const listColumn = ref(5);
  33 +
  34 + const { createMessage } = useMessage();
  35 +
  36 + const organizationId = ref<Nullable<number>>(null);
  37 +
  38 + const pagination = reactive<PaginationProps>({
  39 + size: 'small',
  40 + showTotal: (total: number) => `共 ${total} 条数据`,
  41 + current: 1,
  42 + pageSize: unref(listColumn) * 2,
  43 + onChange: (page: number) => {
  44 + pagination.current = page;
  45 + getListData();
  46 + },
  47 + });
  48 +
  49 + const loading = ref(false);
  50 +
  51 + const dataSource = ref<ConfigurationCenterItemsModal[]>([]);
  52 +
  53 + const [registerForm, { getFieldsValue }] = useForm({
  54 + schemas: searchFormSchema,
  55 + showAdvancedButton: true,
  56 + labelWidth: 100,
  57 + compact: true,
  58 + resetFunc: () => {
  59 + resetFn();
  60 + organizationId.value = null;
  61 + return getListData();
  62 + },
  63 + submitFunc: async () => {
  64 + const value = getFieldsValue();
  65 + getListData(value);
  66 + },
  67 + });
  68 +
  69 + async function getListData(value: Recordable = {}) {
  70 + try {
  71 + loading.value = true;
  72 + const pageSize = unref(listColumn) * 2;
  73 + const { items, total } = await getPage({
  74 + organizationId: unref(organizationId),
  75 + ...value,
  76 + page: pagination.current!,
  77 + pageSize,
  78 + });
  79 +
  80 + dataSource.value = items;
  81 + Object.assign(pagination, { total, pageSize });
  82 + } catch (error) {
  83 + } finally {
  84 + loading.value = false;
  85 + }
  86 + }
  87 +
  88 + onMounted(() => {
  89 + getListData();
  90 + });
  91 +
  92 + const searchInfo = reactive<Recordable>({});
  93 + const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo);
  94 + const handleSelect = (orgId: number) => {
  95 + organizationId.value = orgId;
  96 + getListData();
  97 + };
  98 +
  99 + const [registerDrawer, { openDrawer }] = useDrawer();
  100 +
  101 + const { hasPermission } = usePermission();
  102 +
  103 + const getPreviewFlag = computed(() => {
  104 + return hasPermission(ConfigurationPermission.PREVIEW);
  105 + });
  106 +
  107 + const getDesignFlag = computed(() => {
  108 + return hasPermission(ConfigurationPermission.DESIGN);
  109 + });
  110 +
  111 + const getShareFlag = computed(() => {
  112 + return hasPermission(ConfigurationPermission.SHARE);
  113 + });
  114 +
  115 + const handleCreateOrUpdate = (record?: ConfigurationCenterItemsModal) => {
  116 + if (record) {
  117 + openDrawer(true, {
  118 + isUpdate: true,
  119 + record: cloneDeep(record),
  120 + });
  121 + } else {
  122 + openDrawer(true, {
  123 + isUpdate: false,
  124 + });
  125 + }
  126 + };
  127 +
  128 + const { configurationPrefix } = useGlobSetting();
  129 + const isDev = isDevMode();
  130 +
  131 + const handlePreview = (record: ConfigurationCenterItemsModal) => {
  132 + if (!unref(getPreviewFlag)) return;
  133 + window.open(
  134 + `${configurationPrefix}/${isDev ? '?dev=1&' : '?'}configurationId=${record!.id}&lightbox=1`
  135 + );
  136 + };
  137 +
  138 + const handleDesign = (record: ConfigurationCenterItemsModal) => {
  139 + if (!unref(getDesignFlag)) return;
  140 + window.open(`${configurationPrefix}/${isDev ? '?dev=1&' : '?'}configurationId=${record!.id}`);
  141 + };
  142 +
  143 + const handleDelete = async (record: ConfigurationCenterItemsModal) => {
  144 + try {
  145 + await deleteConfigurationCenter([record.id]);
  146 + createMessage.success('删除成功');
  147 + await getListData();
  148 + } catch (error) {}
  149 + };
  150 +
  151 + const handleCardLayoutChange = () => {
  152 + pagination.current = 1;
  153 + getListData();
  154 + };
  155 +
  156 + const { clipboardRef, isSuccessRef } = useCopyToClipboard();
  157 + const handleCreateShareUrl = (record: ConfigurationCenterItemsModal) => {
  158 + if (!unref(getShareFlag)) return;
  159 + const { origin } = location;
  160 + const searchParams = new URLSearchParams();
  161 + isDev && searchParams.set('dev', '1');
  162 + searchParams.set('share', 'SCADA');
  163 + searchParams.set('configurationId', record.id);
  164 + searchParams.set('publicId', record.publicId || '');
  165 + searchParams.set('lightbox', '1');
  166 + const url = `${origin}${configurationPrefix}/?${searchParams.toString()}`;
  167 + clipboardRef.value = url;
  168 + if (unref(isSuccessRef)) {
  169 + createMessage.success('复制成功~');
  170 + }
  171 + };
  172 +
  173 + const [registerShareModal, { openModal }] = useModal();
  174 +
  175 + const handleOpenShareModal = (record: ConfigurationCenterItemsModal) => {
  176 + openModal(true, record);
  177 + };
  178 +
  179 + const listEl = ref<Nullable<ComponentElRef>>(null);
  180 +
  181 + onMounted(() => {
  182 + const clientHeight = document.documentElement.clientHeight;
  183 + const rect = getBoundingClientRect(unref(listEl)!.$el!) as DOMRect;
  184 + // margin-top 24 height 24
  185 + const paginationHeight = 24 + 24 + 8;
  186 + // list pading top 8 maring-top 8 extra slot 56
  187 + const listContainerMarginBottom = 8 + 8 + 56;
  188 + const listContainerHeight =
  189 + clientHeight - rect.top - paginationHeight - listContainerMarginBottom;
  190 + const listContainerEl = (unref(listEl)!.$el as HTMLElement).querySelector(
  191 + '.ant-spin-container'
  192 + ) as HTMLElement;
  193 + listContainerEl &&
  194 + (listContainerEl.style.height = listContainerHeight + 'px') &&
  195 + (listContainerEl.style.overflowY = 'auto') &&
  196 + (listContainerEl.style.overflowX = 'hidden');
  197 + });
  198 +</script>
  199 +
  200 +<template>
  201 + <PageWrapper dense contentFullHeight contentClass="flex">
  202 + <OrganizationIdTree @select="handleSelect" ref="organizationIdTreeRef" />
  203 + <section class="flex-auto p-4 w-3/4 xl:w-4/5 w-full configuration-list">
  204 + <div class="flex-auto w-full bg-light-50 dark:bg-dark-900 p-4">
  205 + <BasicForm @register="registerForm" />
  206 + </div>
  207 + <List
  208 + ref="listEl"
  209 + :loading="loading"
  210 + class="flex-auto bg-light-50 dark:bg-dark-900 !p-2 !mt-4"
  211 + position="bottom"
  212 + :pagination="pagination"
  213 + :data-source="dataSource"
  214 + :grid="{ gutter: 4, column: listColumn }"
  215 + >
  216 + <template #header>
  217 + <div class="flex gap-3 justify-end">
  218 + <Authority :value="ConfigurationPermission.CREATE">
  219 + <Button type="primary" @click="handleCreateOrUpdate()">新增组态</Button>
  220 + </Authority>
  221 + <CardLayoutButton v-model:value="listColumn" @change="handleCardLayoutChange" />
  222 + <Tooltip title="刷新">
  223 + <Button type="primary" @click="getListData">
  224 + <ReloadOutlined />
  225 + </Button>
  226 + </Tooltip>
  227 + </div>
  228 + </template>
  229 + <template #renderItem="{ item }">
  230 + <List.Item>
  231 + <Card hoverable class="card-container">
  232 + <template #cover>
  233 + <div
  234 + class="img-container h-full w-full !flex justify-center items-center text-center p-1 relative"
  235 + >
  236 + <img
  237 + class="w-full h-36"
  238 + alt="example"
  239 + :src="item.thumbnail || configurationSrc"
  240 + @click="handlePreview(item)"
  241 + />
  242 + <span
  243 + class="absolute top-0 left-0 text-light-50 transform -rotate-45 translate-y-1"
  244 + >
  245 + {{ ViewTypeNameEnum[item.viewType] }}
  246 + </span>
  247 + </div>
  248 + </template>
  249 + <template class="ant-card-actions" #actions>
  250 + <Tooltip title="预览">
  251 + <AuthIcon
  252 + :auth="ConfigurationPermission.PREVIEW"
  253 + class="!text-lg"
  254 + icon="ant-design:eye-outlined"
  255 + @click="handlePreview(item)"
  256 + />
  257 + </Tooltip>
  258 + <Tooltip title="设计">
  259 + <AuthIcon
  260 + :auth="ConfigurationPermission.DESIGN"
  261 + class="!text-lg"
  262 + icon="ant-design:edit-outlined"
  263 + @click="handleDesign(item)"
  264 + />
  265 + </Tooltip>
  266 + <Tooltip title="分享">
  267 + <AuthIcon
  268 + :auth="ConfigurationPermission.SHARE"
  269 + class="!text-lg"
  270 + icon="ant-design:share-alt-outlined"
  271 + @click="handleCreateShareUrl(item)"
  272 + />
  273 + </Tooltip>
  274 + <AuthDropDown
  275 + :dropMenuList="[
  276 + {
  277 + text: '分享',
  278 + auth: ConfigurationPermission.SHARE,
  279 + icon: 'ant-design:share-alt-outlined',
  280 + event: '',
  281 + onClick: handleOpenShareModal.bind(null, item),
  282 + },
  283 + {
  284 + text: '编辑',
  285 + auth: ConfigurationPermission.UPDATE,
  286 + icon: 'clarity:note-edit-line',
  287 + event: '',
  288 + onClick: handleCreateOrUpdate.bind(null, item),
  289 + },
  290 + {
  291 + text: '删除',
  292 + auth: ConfigurationPermission.DELETE,
  293 + icon: 'ant-design:delete-outlined',
  294 + event: '',
  295 + popconfirm: {
  296 + title: '是否确认删除操作?',
  297 + onConfirm: handleDelete.bind(null, item),
  298 + },
  299 + },
  300 + ]"
  301 + :trigger="['hover']"
  302 + />
  303 + </template>
  304 + <Card.Meta>
  305 + <template #title>
  306 + <span class="truncate">{{ item.name }}</span>
  307 + </template>
  308 + <template #description>
  309 + <div class="truncate h-11">
  310 + <div class="truncate">{{ item.organizationDTO.name }}</div>
  311 + <div class="truncate">{{ item.remark || '' }} </div>
  312 + </div>
  313 + </template>
  314 + </Card.Meta>
  315 + </Card>
  316 + </List.Item>
  317 + </template>
  318 + </List>
  319 + </section>
  320 + <ConfigurationCenterDrawer @register="registerDrawer" @success="getListData" />
  321 + <ShareModal
  322 + @register="registerShareModal"
  323 + :shareApi="shareConfiguration"
  324 + @success="getListData"
  325 + />
  326 + </PageWrapper>
  327 +</template>
  328 +
  329 +<style lang="less" scoped>
  330 + .configuration-list:deep(.ant-list-header) {
  331 + border-bottom: none !important;
  332 + }
  333 +
  334 + .configuration-list:deep(.ant-list-pagination) {
  335 + height: 24px;
  336 + }
  337 +
  338 + .configuration-list:deep(.ant-card-body) {
  339 + padding: 16px !important;
  340 + }
  341 +
  342 + .configuration-list:deep(.ant-list-empty-text) {
  343 + @apply w-full h-full flex justify-center items-center;
  344 + }
  345 +
  346 + .card-container {
  347 + // background-color: red;
  348 + .img-container {
  349 + border-top-left-radius: 80px;
  350 + background-color: #fff;
  351 + }
  352 + }
  353 +
  354 + .card-container:deep(.ant-card-cover) {
  355 + background-color: red;
  356 + }
  357 +</style>
... ...
... ... @@ -8,7 +8,7 @@
8 8 import { ShareRouteParams } from '/@/api/sys/model/shareModel';
9 9 import { useUserStore } from '/@/store/modules/user';
10 10 import { BasicForm, useForm } from '/@/components/Form';
11   - import { FieldsEnum } from '../../visual/board/config/share';
  11 + import { FieldsEnum } from '/@/views/common/ShareModal/config';
12 12 import BoardDetail from '/@/views/visual/board/detail/index.vue';
13 13
14 14 const loading = ref(true);
... ...
... ... @@ -10,7 +10,7 @@
10 10 import { DATA_BOARD_SHARE_URL, MoreActionEvent, VisualBoardPermission } from './config/config';
11 11 import { useModal } from '/@/components/Modal';
12 12 import PanelDetailModal from './components/PanelDetailModal.vue';
13   - import { getDataBoardList, deleteDataBoard } from '/@/api/dataBoard';
  13 + import { getDataBoardList, deleteDataBoard, shareBoard } from '/@/api/dataBoard';
14 14 import { DataBoardRecord } from '/@/api/dataBoard/model';
15 15 import { ViewType } from './config/panelDetail';
16 16 import { useRouter } from 'vue-router';
... ... @@ -21,7 +21,7 @@
21 21 import { encode } from './config/config';
22 22 import { useForm, BasicForm } from '/@/components/Form';
23 23 import { formSchema } from './config/searchForm';
24   - import ShareModal from './components/ShareModal.vue';
  24 + import { ShareModal } from '/@/views/common/ShareModal';
25 25
26 26 const ListItem = List.Item;
27 27 const router = useRouter();
... ... @@ -267,7 +267,7 @@
267 267 </template>
268 268 </List>
269 269 </Spin>
270   - <ShareModal @register="registerShareModal" @success="getDatasource" />
  270 + <ShareModal @register="registerShareModal" :shareApi="shareBoard" @success="getDatasource" />
271 271 <PanelDetailModal @register="registerModal" @change="getDatasource" />
272 272 </PageWrapper>
273 273 </template>
... ...