fd2815e7 by lihua

逻辑空间管理前端开发

1 parent c046732c
...@@ -424,7 +424,52 @@ const routes: RouteRecordRaw[] = [ ...@@ -424,7 +424,52 @@ const routes: RouteRecordRaw[] = [
424 name: 'productApplicationDetail', 424 name: 'productApplicationDetail',
425 component: () => import('@/views/data_asset/productApplicationDetail.vue'), 425 component: () => import('@/views/data_asset/productApplicationDetail.vue'),
426 meta: { 426 meta: {
427 title: '数据申请-', 427 title: '申请详情-',
428 sidebar: false,
429 breadcrumb: false,
430 cache: true,
431 reuse: true
432 }
433 },
434 ]
435 },
436 {
437 path: '/data-product/space-manage',
438 component: Layout,
439 meta: {
440 title: '逻辑空间管理',
441 icon: 'sidebar-videos',
442 },
443 children: [
444 {
445 path: '',
446 name: 'productSpaceManage',
447 component: () => import('@/views/data_asset/productSpaceManage.vue'),
448 meta: {
449 title: '',
450 sidebar: false,
451 breadcrumb: false,
452 cache: true
453 },
454 },
455 {
456 path: 'product-space-edit',
457 name: 'productSpaceEdit',
458 component: () => import('@/views/data_asset/productSpaceEdit.vue'),
459 meta: {
460 title: '新增-',
461 sidebar: false,
462 breadcrumb: false,
463 cache: true,
464 reuse: true
465 }
466 },
467 {
468 path: 'product-space-detail',
469 name: 'productSpaceDetail',
470 component: () => import('@/views/data_asset/productSpaceDetail.vue'),
471 meta: {
472 title: '详情-',
428 sidebar: false, 473 sidebar: false,
429 breadcrumb: false, 474 breadcrumb: false,
430 cache: true, 475 cache: true,
......
1 <template>
2 <div class="container_wrap full" v-loading="fullscreenLoading">
3 <div class="content_main">
4 <ContentWrap id="id-baseInfo" title="逻辑空间信息" description="" :isExpand="baseInfoExpand" :expand-swicth="true"
5 class="mb16" @expand="(v) => baseInfoExpand = v">
6 <div class="list_panel">
7 <div class="list_item">
8 <span class="item_label">逻辑空间名称:</span>
9 <span class="item_value">
10 <ellipsis-tooltip :content="detailInfo.spaceName || '--'" class-name="w100f mr8-i"
11 :refName="'tooltipOver' + 'spaceName'"></ellipsis-tooltip>
12 </span>
13 </div>
14 <div class="list_item">
15 <span class="item_label">所属领域:</span>
16 <span class="item_value">{{ detailInfo.domainName || '--' }}</span>
17 </div>
18 <div class="list_item">
19 <span class="item_label">创建企业:</span>
20 <span class="item_value"> <ellipsis-tooltip :content="detailInfo.tenantName || '--'"
21 class-name="w100f mr8-i" :refName="'tooltipOver' + 'tenantName'"></ellipsis-tooltip></span>
22 </div>
23 <div class="list_item">
24 <span class="item_label">是否开启:</span>
25 <span class="item_value">{{ detailInfo.bizState ? '是' : '否' }}</span>
26 </div>
27 </div>
28 <el-tabs v-model="activeTabName" class="param-tabs" style="margin-top: 8px;">
29 <el-tab-pane label="成员权限" name="member">
30 <Table ref="memberTableRef" :tableInfo="memberTableInfo" class="fiveRow-table" />
31 </el-tab-pane>
32 <el-tab-pane label="策略配置" name="strategy">
33 <StrategyTable ref="strategyTableDetailRef" :show-title="false" :is-look="true"
34 :value="detailInfo.policyRSVOS || []">
35 </StrategyTable>
36 </el-tab-pane>
37 </el-tabs>
38 </ContentWrap>
39 <ContentWrap id="id-approveInfo" title="流程审批" expandSwicth style="margin-top: 15px" :isExpand="expandApprove"
40 @expand="(v) => expandApprove = v">
41 <ApprovalProcess ref="approvalProcessRef" v-if="deploymentId" :deploymentId="deploymentId"
42 :processInstanceId="processInstanceId">
43 </ApprovalProcess>
44 </ContentWrap>
45 </div>
46 <div class="tool_btns">
47 <div class="btns">
48 <el-button v-for="btn in toolBtns" :type="btn.type" :plain="btn.plain" @click="btnClick(btn)">{{ btn.label }}</el-button>
49 </div>
50 </div>
51 </div>
52 </template>
53
54 <script lang="ts" setup name="productSpaceDetail">
55 import useUserStore from "@/store/modules/user";
56 import StrategyTable from "../data_smart_contract/components/strategyTable.vue";
57 import { TableColumnWidth } from "@/utils/enum";
58
59
60 const { proxy } = getCurrentInstance() as any;
61 const userStore = useUserStore();
62 const route = useRoute();
63 const router = useRouter();
64 const fullPath = route.fullPath;
65
66 const fullscreenLoading = ref(false);
67 const baseInfoExpand = ref(true);
68 const expandApprove = ref(true);
69
70 const deploymentId = ref('');
71 const processInstanceId = ref('');
72
73 const detailInfo: any = ref({});
74
75 /** 页签当前活跃的有成员权限和策略配置 */
76 const activeTabName = ref('member');
77
78 const toolBtns: any = computed(() => {
79 let btnsArr: any = [{
80 label: "关闭", value: "cancel", plain: true
81 }];
82 // TODO,资产运营平台TODO
83 return btnsArr;
84 });
85
86 const btnClick = (btn: any) => {
87 switch (btn.value) {
88 case 'cancel':
89 cancel();
90 break;
91 default:
92 break;
93 }
94 }
95
96 const cancel = () => {
97 userStore.setTabbar(userStore.tabbar.filter((tab: any) => tab.fullPath !== fullPath));
98 router.push({
99 name: 'productApplicationManage'
100 });
101 }
102
103 onBeforeMount(() => {
104
105 })
106
107 const memberTableInfo = ref({
108 id: "input-member-table",
109 height: '214px',
110 fields: [
111 { label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
112 { label: "成员名称", field: "memberGuid", width: 200 },
113 { label: "角色类型", field: "roleType", width: 160 },
114 { label: "描述", field: "description", width: 300 },
115 ],
116 data: [],
117 showPage: false,
118 actionInfo: {
119 show: false,
120 }
121 });
122
123 </script>
124
125 <style lang="scss" scoped>
126 .content_main {
127 height: calc(100% - 44px);
128 padding: 16px;
129 overflow: hidden auto;
130 position: sticky;
131 }
132
133 .list_panel {
134 display: flex;
135 flex-wrap: wrap;
136 display: flex;
137 align-items: center;
138
139 .list_item {
140 width: 33.33%;
141 line-height: 32px;
142 font-size: 14px;
143 color: var(--el-text-color-regular);
144 display: flex;
145 justify-content: space-between;
146 min-width: 120px;
147
148 .item_label {
149 text-align: left;
150 }
151
152 .item_value {
153 color: var(--el-color-regular);
154 padding: 0 4px;
155 flex: 1;
156 text-align: justify;
157 min-width: 0;
158
159 &.link {
160 color: var(--el-color-primary);
161 cursor: pointer;
162 }
163 }
164
165 &.is_block {
166 width: 100%;
167
168 .item_value {
169 white-space: pre-wrap;
170 }
171 }
172 }
173 }
174
175 .tool_btns {
176 display: flex;
177 justify-content: center;
178 align-items: center;
179 height: 44px;
180 padding: 0 16px;
181 border-top: 1px solid #d9d9d9;
182 }
183
184 :deep(.el-tabs) {
185 margin-top: -8px;
186
187 .el-tabs__header {
188 margin-bottom: 8px;
189 }
190
191 .el-tabs__item {
192 height: 32px;
193
194 &:nth-child(2) {
195 padding-left: 16px;
196 }
197
198 }
199 }
200 </style>
...\ No newline at end of file ...\ No newline at end of file
1 <template>
2 <div class="container_wrap full" v-loading="fullscreenLoading">
3 <div class="content_main">
4 <ContentWrap id="id-baseInfo" title="逻辑空间信息" description="" :isExpand="baseInfoExpand" :expand-swicth="true"
5 class="mb16" @expand="(v) => baseInfoExpand = v">
6 <Form ref="baseInfoFormRef" :itemList="baseInfoFormItems" formId="base-info-form" :rules="baseInfoFormRules"
7 col="col3" />
8 <el-tabs v-model="activeTabName" class="param-tabs">
9 <el-tab-pane label="成员权限" name="member">
10 <Table ref="memberTableRef" :tableInfo="memberTableInfo" class="fiveRow-table" />
11 <div class="row-add-btn">
12 <el-button link @click="addMember" :icon="CirclePlus" v-preReClick>添加</el-button>
13 </div>
14 </el-tab-pane>
15 <el-tab-pane label="策略配置" name="strategy">
16 <StrategyTable ref="strategyTableRef" :value="detailInfo.policyRSVOS || (route.query.guid ? [] : [{
17 index: 1,
18 action: '',
19 children: [{ childIndex: 1 }]
20 }])" :operatorOptionList="operatorOptionList" :actionOptionsList="actionOptionsList"
21 :constraintOptionsList="constraintOptionsList"></StrategyTable>
22 </el-tab-pane>
23 </el-tabs>
24 </ContentWrap>
25 <ContentWrap id="id-approveInfo" title="流程审批" expandSwicth style="margin-top: 15px" :isExpand="expandApprove"
26 @expand="(v) => expandApprove = v">
27 <ApprovalProcess ref="approvalProcessRef" v-if="deploymentId" :deploymentId="deploymentId"
28 :processInstanceId="processInstanceId">
29 </ApprovalProcess>
30 </ContentWrap>
31 </div>
32 <div class="bottom_tool_wrap">
33 <el-button @click="cancel">取消</el-button>
34 <el-button @click="save" v-preReClick>保存</el-button>
35 <el-button type="primary" @click="submit" v-preReClick>提交审批</el-button>
36 </div>
37 </div>
38 </template>
39
40 <script lang="ts" setup name="productSpaceEdit">
41 import { CirclePlus } from "@element-plus/icons-vue";
42 import { getCamundaDeploymentId } from "@/api/modules/workFlowService";
43 import {
44 getParamsList
45 } from "@/api/modules/queryService";
46 import {
47 getActionPolicyList,
48 getConstraintPolicyList,
49 } from "@/api/modules/dataSmartContract"
50 import useUserStore from "@/store/modules/user";
51 import useDataProductApplicationStore from "@/store/modules/productApplication";
52 import { useValidator } from '@/hooks/useValidator';
53 import { TableColumnWidth } from "@/utils/enum";
54 import { scrollLastRowToView } from "@/utils/common";
55 import StrategyTable from "../data_smart_contract/components/strategyTable.vue";
56
57 const { required } = useValidator();
58
59 const { proxy } = getCurrentInstance() as any;
60
61 const userStore = useUserStore();
62 const productApplicationStore = useDataProductApplicationStore();
63 const route = useRoute();
64 const router = useRouter();
65 const userData = JSON.parse(localStorage.userData);
66 const fullPath = route.fullPath;
67
68 const detailInfo: any = ref({});
69
70 const fullscreenLoading = ref(false);
71 const baseInfoExpand = ref(true);
72 const expandApprove = ref(true);
73
74 /** 约束运算符字典下拉 */
75 const operatorOptionList: any = ref([]);
76
77 /** 约束行为下拉列表 */
78 const constraintOptionsList: any = ref([]);
79
80 /** 策略操作行为下拉列表 */
81 const actionOptionsList: any = ref([]);
82
83 /** 页签当前活跃的有成员权限和策略配置 */
84 const activeTabName = ref('member');
85
86 const deploymentId = ref('');
87 const processInstanceId = ref('');
88
89 const baseInfoFormRef = ref();
90
91 const domainDictList: any = ref([]);
92
93 const baseInfoFormItems = ref([
94 {
95 label: '逻辑空间名称',
96 type: 'input',
97 placeholder: '请输入',
98 field: 'spaceName',
99 maxlength: 50,
100 default: '',
101 clearable: true,
102 required: true
103 },
104 {
105 label: '所属领域',
106 type: 'select',
107 placeholder: '请选择',
108 field: 'domain',
109 default: '003',
110 options: domainDictList.value,
111 props: {
112 value: 'value',
113 label: 'label',
114 children: 'children'
115 },
116 required: true,
117 filterable: true,
118 clearable: true,
119 visible: true
120 },
121 {
122 label: '创建企业',
123 type: 'input',
124 placeholder: '请输入',
125 field: 'tenantName',
126 default: userData.tenantName,
127 required: true,
128 disabled: true
129 },
130 {
131 label: '是否开启',
132 type: 'switch',
133 field: 'bizState',
134 default: 'Y',
135 placeholder: '请选择',
136 activeValue: 'Y',
137 inactiveValue: 'S',
138 required: true,
139 switchWidth: 32,
140 },
141 {
142 label: '逻辑空间描述',
143 type: 'textarea',
144 placeholder: '该逻辑空间主要为医疗机构的数据产品,限制了数据产品以及只有进行查看操作。参与方为某某医药企业、某某医疗机构以及运营方。',
145 field: 'description',
146 default: '',
147 block: true,
148 maxlength: 500,
149 clearable: true,
150 required: true,
151 },
152 ])
153
154 const baseInfoFormRules = ref({
155 spaceName: [required('请输入逻辑空间名称')],
156 domain: [required('请选择所属领域')],
157 description: [required('请输入逻辑空间描述')]
158 })
159
160 const cancel = () => {
161 proxy.$openMessageBox("当前页面尚未保存,确定放弃修改吗?", () => {
162 userStore.setTabbar(userStore.tabbar.filter((tab: any) => tab.fullPath !== fullPath));
163 router.push({
164 name: 'productSpaceManage'
165 });
166 }, () => {
167 proxy.$ElMessage.info("已取消");
168 });
169 }
170
171 const memberTenantList: any = ref([]);
172
173 const roleTypeList: any = ref([{
174 value: 'use',
175 label: '数据使用方'
176 }, {
177 value: 'provider',
178 label: '数据提供方'
179 }]);
180
181 /** 对表格组件的引用 */
182 const memberTableRef = ref();
183
184 /** 成员权限表格 */
185 const memberTableData: any = ref([]);
186
187 /** 成员权限表格 */
188 const memberTableInfo = ref({
189 id: "input-params-table",
190 height: '214px',
191 fields: [
192 { label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
193 { label: "成员名称", field: "memberGuid", width: 200, required: true, columClass: 'edit-colum', type: 'edit' },
194 { label: "角色类型", field: "roleType", width: 160, required: true, columClass: 'edit-colum', type: 'edit' },
195 { label: "描述", field: "description", width: 300, required: false, columClass: 'edit-colum', type: 'edit' },
196 ],
197 editInfo: {
198 memberGuid: {
199 label: '',
200 type: 'select',
201 field: 'memberGuid',
202 default: '',
203 options: memberTenantList.value,
204 props: {
205 label: 'tenantName',
206 value: 'guid'
207 },
208 placeholder: '请选择',
209 clearable: true,
210 filterable: true
211 },
212 roleType: {
213 label: '',
214 type: 'select',
215 field: 'roleType',
216 default: '',
217 options: roleTypeList.value,
218 props: {
219 label: 'label',
220 value: 'value'
221 },
222 placeholder: '请选择',
223 clearable: true,
224 filterable: true
225 },
226 description: {
227 label: '',
228 type: 'input',
229 field: 'description',
230 default: '',
231 maxlength: 200,
232 placeholder: '请输入',
233 clearable: true,
234 }
235 },
236 STATUS: 'edit',
237 data: memberTableData.value,
238 showPage: false,
239 actionInfo: {
240 show: true,
241 label: "操作",
242 type: "btn",
243 width: 60,
244 fixed: 'right',
245 btns: [
246 {
247 label: "删除", value: "remove", click: (scope) => {
248 let index = scope.$index;
249 proxy.$openMessageBox("此操作将永久删除, 是否继续?", () => {
250 memberTableData.value.splice(index, 1);
251 memberTableInfo.value.data = memberTableData.value;
252 proxy.$ElMessage.success('参数删除成功');
253 }, () => {
254 proxy.$ElMessage.info("已取消");
255 });
256 }
257 },
258 ]
259 },
260 loading: false
261 });
262
263 /** 给表格添加一行入参定义。 */
264 const addMember = () => {
265 memberTableData.value.push({ memberGuid: '', roleType: '', description: '' });
266 memberTableInfo.value.data = memberTableData.value;
267 nextTick(() => {
268 scrollLastRowToView(memberTableRef.value?.tableRef, memberTableData.value.length);
269 })
270 }
271
272 const save = () => {
273 // 保存不检验。
274 }
275
276 const submit = () => {
277 baseInfoFormRef.value?.ruleFormRef?.validate().then((valid, errorItem) => {
278 if (valid) {
279 let formInline = baseInfoFormRef.value.formInline;
280 // fullscreenLoading.value = true;
281 // listingSavePortal(params).then((res: any) => {
282 // fullscreenLoading.value = false;
283 // if (res?.code == proxy.$passCode) {
284 // proxy.$ElMessage.success('提交审批成功');
285 // userStore.setTabbar(userStore.tabbar.filter((tab: any) => tab.fullPath !== fullPath));
286 // productApplicationStore.setIsRefresh(true);
287 // router.push({
288 // name: "productApplicationManage",
289 // });
290 // } else {
291 // res?.msg && proxy.$ElMessage.error(res.msg);
292 // }
293 // }).catch((res) => {
294 // fullscreenLoading.value = false;
295 // });
296 } else {
297 var obj = Object.keys(errorItem);
298 baseInfoFormRef.value.ruleFormRef.scrollToField(obj[0]);
299 }
300 })
301 }
302
303 onActivated(() => {
304 let tab: any = userStore.tabbar.find((tab: any) => tab.fullPath == fullPath);
305 let detailType = route.query.type;
306 let name = route.query.name;
307 if (tab) {
308 switch (detailType) {
309 case 'edit':
310 tab.meta.title = `编辑-${name}`;
311 break;
312 case 'redit':
313 tab.meta.title = `编辑-${name}`;
314 break;
315 default:
316 tab.meta.title = '新增逻辑空间';
317 }
318 document.title = tab.meta.title;
319 };
320 })
321
322 onBeforeMount(() => {
323 // getCamundaDeploymentId('10016', userData.tenantGuid, userData.staffGuid).then((res: any) => {
324 // if (res.code == proxy.$passCode) {
325 // deploymentId.value = res.data;
326 // } else {
327 // proxy.$ElMessage.error(res.msg);
328 // }
329 // })
330
331 getParamsList({ dictType: '领域' }).then((res: any) => {
332 if (res.code == proxy.$passCode) {
333 domainDictList.value = res.data || [];
334 let itemIndex = baseInfoFormItems.value.findIndex(item => item.field == 'domain');
335 let item = baseInfoFormItems.value[itemIndex];
336 item && (item.options = domainDictList.value);
337 } else {
338 proxy.$ElMessage.error(res.msg);
339 }
340 });
341
342 getParamsList({ dictType: '约束运算符' }).then((res: any) => {
343 if (res?.code == proxy.$passCode) {
344 const data = res.data || [];
345 operatorOptionList.value = data;
346 } else {
347 res?.msg && proxy.$ElMessage.error(res?.msg);
348 }
349 })
350 getActionPolicyList().then((res: any) => {
351 if (res?.code == proxy.$passCode) {
352 const data = res.data || [];
353 actionOptionsList.value = data;
354 } else {
355 res?.msg && proxy.$ElMessage.error(res?.msg);
356 }
357 })
358 getConstraintPolicyList().then((res: any) => {
359 if (res?.code == proxy.$passCode) {
360 const data = res.data || [];
361 constraintOptionsList.value = data;
362 } else {
363 res?.msg && proxy.$ElMessage.error(res?.msg);
364 }
365 })
366 })
367
368 </script>
369
370 <style lang="scss" scoped>
371 .content_main {
372 height: calc(100% - 40px);
373 padding: 16px;
374 overflow: hidden auto;
375 position: sticky;
376 }
377
378 .bottom_tool_wrap {
379 height: 40px;
380 padding: 0 16px;
381 border-top: 1px solid #d9d9d9;
382 display: flex;
383 justify-content: center;
384 align-items: center;
385 }
386
387 .row-add-btn {
388 .el-button--default {
389 padding: 4px 0px;
390 margin-top: 4px;
391 }
392
393 :deep(.el-icon) {
394 width: 16px;
395 height: 16px;
396
397 svg {
398 width: 16px;
399 height: 16px;
400 }
401 }
402 }
403
404 :deep(.el-tabs) {
405 margin-top: -8px;
406
407 .el-tabs__header {
408 margin-bottom: 8px;
409 }
410
411 .el-tabs__item {
412 height: 32px;
413
414 &:nth-child(2) {
415 padding-left: 16px;
416 }
417
418 }
419 }
420 </style>
...\ No newline at end of file ...\ No newline at end of file
1 <template>
2 <div class="container_wrap">
3 <div class="table_tool_wrap">
4 <el-button type="primary" @click="newCreate">新增</el-button>
5 <el-input v-model.trim="pageInfo.keyWord" placeholder="名称搜索" :suffix-icon="Search" clearable
6 @blur="toSearch(true, true)" @keyup.enter.native="searchEnterFun" />
7 </div>
8 <div class="table_panel_wrap">
9 <div v-show="listData.length" class="data-content" v-loading="listDataLoading">
10 <div class="card-content" v-for="(item, index) in listData" :key="item.guid" @click="handleDataClick(item)">
11 <div class="v-top">
12 <span class="title">{{ item.name }}</span>
13 <el-tag :type="tagType(item, 'approveState')">{{ tagMethod(item, 'approveState') }}</el-tag>
14 </div>
15 <div class="v-middle">
16 <div class="per">
17 <div class="desc">产品数量</div>
18 <div class="cnt">{{ item.productNum == null ? '--' : changeNum(item.productNum, 0) }}</div>
19 </div>
20 <div class="per">
21 <div class="desc">成员数量</div>
22 <div class="cnt">{{ item.productNum == null ? '--' : changeNum(item.productNum, 0) }}</div>
23 </div>
24 </div>
25 <div class="v-bottom">
26 <div class="per" @click.stop="clickDetail(item)">详情</div>
27 <div class="divider" @click.stop></div>
28 <div class="per" @click.stop="clickDelete(item)">删除</div>
29 </div>
30 </div>
31 </div>
32 <div v-show="!listData.length" class="empty-content">
33 <img src="../../assets/images/empty-data.png" :style="{ width: '168px', height: '96px' }" />
34 <div class="empty-text">暂无数据</div>
35 </div>
36 </div>
37 <PageNav :class="[pageInfo.type]" :pageInfo="pageInfo" @pageChange="pageChange" />
38 </div>
39 </template>
40 <script setup lang="ts" name="productSpaceManage">
41 import { commonPageConfig } from '@/components/PageNav';
42 import { changeNum, tagMethod, tagType } from '@/utils/common';
43 import { Search } from "@element-plus/icons-vue";
44
45 const router = useRouter();
46 const { proxy } = getCurrentInstance() as any;
47
48 /** 卡片加载条 */
49 const listDataLoading = ref(false);
50 /** 列表数据 */
51 const listData: any = ref([{ guid: '1', name: '产品空间1' }, { guid: '2', name: '产品空间1' }, { guid: '3', name: '产品空间1' }, { guid: '4', name: '产品空间1' },
52 { guid: '5', name: '产品空间1' }
53 ]);
54
55 const oldKeyWord = ref(""); // 记录上次输入的关键字,避免重复搜索
56 const isEnter = ref(false); // 标识是否通过回车键触发搜索
57
58 const pageInfo = ref({
59 ...commonPageConfig,
60 rows: 0,
61 type: "normal",
62 keyWord: '',
63 });
64
65 const getTableData = (clear = false) => {
66 // listDataLoading.value = true;
67 // getDamCatalogTable({
68 // pageSize: pageInfo.value.limit,
69 // pageIndex: pageInfo.value.curr,
70 // keyWord: pageInfo.value.keyWord
71 // }).then((res: any) => {
72 // listDataLoading.value = false;
73 // if (res.code == proxy.$passCode) {
74 // const data = res.data || {}
75 // listData.value = data.records || [];
76 // pageInfo.value.limit = data.pageSize
77 // pageInfo.value.curr = data.pageIndex
78 // pageInfo.value.rows = data.totalRows
79 // } else {
80 // proxy.$ElMessage.error(res.msg);
81 // }
82 // });
83 }
84
85 const pageChange = (info) => {
86 pageInfo.value.curr = Number(info.curr);
87 pageInfo.value.limit = Number(info.limit);
88 getTableData();
89 };
90
91 /**
92 * 触发搜索查询
93 * @param clear - 是否清空页码,默认为true
94 * @param isBlur - 是否是失焦触发,默认为false
95 */
96 const toSearch = (clear: boolean = true, isBlur: boolean = false) => {
97 if (clear) {
98 pageInfo.value.curr = 1 // 重置为第一页
99 }
100 // 如果是失焦且不是回车触发,且关键词没有变化,则不执行搜索
101 if (isBlur && !isEnter.value && oldKeyWord.value === pageInfo.value.keyWord) {
102 return;
103 }
104 isEnter.value = false; // 重置回车状态
105 oldKeyWord.value = pageInfo.value.keyWord; // 更新关键词记录
106 getTableData(clear);
107 }
108
109 /**
110 * 回车搜索事件处理
111 * 在输入框按下回车键时触发
112 * @param event - 键盘事件对象
113 */
114 const searchEnterFun = (event) => {
115 isEnter.value = true; // 标记为回车触发
116 event.target?.blur(); // 输入框失去焦点
117 }
118
119 const newCreate = () => {
120 router.push({
121 name: 'productSpaceEdit'
122 })
123 }
124
125 const handleDataClick = (item) => {
126 router.push({
127 name: 'productSpaceEdit',
128 query: {
129 guid: item.guid,
130 name: item.name
131 }
132 })
133 }
134
135 const clickDetail = (item) => {
136 router.push({
137 name: 'productSpaceDetail',
138 query: {
139 guid: item.guid,
140 name: item.name
141 }
142 })
143 }
144
145 const clickDelete = (item) => {
146 proxy.$openMessageBox('此操作将永久删除该空间,是否继续?', () => {
147 // TODO
148 }, () => {
149 proxy.$ElMessage.info('已取消删除');
150 });
151 }
152
153 </script>
154
155 <style lang="scss" scoped>
156 .container_wrap {
157 padding: 0 16px;
158 }
159
160 .table_tool_wrap {
161 display: flex;
162 align-items: center;
163 justify-content: space-between;
164 padding-top: 12px;
165
166 .el-input {
167 width: 240px;
168 }
169 }
170
171 .table_panel_wrap {
172 height: calc(100% - 94px);
173 margin-top: 12px;
174 position: relative;
175
176 .data-content {
177 display: flex;
178 flex-wrap: wrap;
179 gap: 16px 16px;
180 align-content: flex-start;
181 overflow-y: auto;
182
183 .card-content {
184 width: calc(25% - 13px);
185 min-width: 220px;
186 height: 174px;
187 border: 1px solid rgba(229, 229, 229, 1);
188 border-radius: 4px;
189 cursor: pointer;
190 position: relative;
191
192 &:hover {
193 border-color: var(--el-color-primary);
194 }
195
196 .v-top {
197 height: 48px;
198 padding: 12px 16px;
199 display: flex;
200
201 .title {
202 font-size: 16px;
203 color: #212121;
204 line-height: 24px;
205 font-weight: 600;
206 width: calc(100% - 58px);
207 white-space: nowrap;
208 /* 防止文本换行 */
209 overflow: hidden;
210 /* 隐藏超出容器的文本 */
211 text-overflow: ellipsis;
212 /* 显示省略号 */
213 }
214
215 .el-tag {
216 width: 50px;
217 text-align: center;
218 line-height: 18px;
219 }
220 }
221
222 .v-middle {
223 height: 80px;
224 display: flex;
225
226 .per {
227 width: 50%;
228 height: 100%;
229 display: flex;
230 flex-direction: column;
231 align-items: center;
232 justify-content: center;
233
234 .desc {
235 font-size: 14px;
236 color: #999999;
237 line-height: 21px;
238 margin-bottom: 4px;
239 }
240
241 .cnt {
242 font-size: 24px;
243 color: #44ABB4;
244 line-height: 36px;
245 font-weight: 600;
246 }
247 }
248 }
249
250 .v-bottom {
251 background: #FAFAFA;
252 height: 44px;
253 display: flex;
254 border-top: 1px solid rgba(229, 229, 229, 1);
255
256 .divider {
257 border-right: 1px solid rgba(229, 229, 229, 1);
258 }
259
260 .per {
261 width: 50%;
262 display: flex;
263 align-items: center;
264 justify-content: center;
265 padding: 8px 0px;
266 }
267 }
268 }
269 }
270 }
271
272 .empty-content {
273 display: flex;
274 align-items: center;
275 justify-content: center;
276 height: 100%;
277 width: 100%;
278 flex-direction: column;
279
280 .empty-text {
281 font-size: 14px;
282 color: #b2b2b2;
283 margin-top: 12px;
284 }
285 }
286 </style>
...\ No newline at end of file ...\ No newline at end of file
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!