fd2815e7 by lihua

逻辑空间管理前端开发

1 parent c046732c
......@@ -424,7 +424,52 @@ const routes: RouteRecordRaw[] = [
name: 'productApplicationDetail',
component: () => import('@/views/data_asset/productApplicationDetail.vue'),
meta: {
title: '数据申请-',
title: '申请详情-',
sidebar: false,
breadcrumb: false,
cache: true,
reuse: true
}
},
]
},
{
path: '/data-product/space-manage',
component: Layout,
meta: {
title: '逻辑空间管理',
icon: 'sidebar-videos',
},
children: [
{
path: '',
name: 'productSpaceManage',
component: () => import('@/views/data_asset/productSpaceManage.vue'),
meta: {
title: '',
sidebar: false,
breadcrumb: false,
cache: true
},
},
{
path: 'product-space-edit',
name: 'productSpaceEdit',
component: () => import('@/views/data_asset/productSpaceEdit.vue'),
meta: {
title: '新增-',
sidebar: false,
breadcrumb: false,
cache: true,
reuse: true
}
},
{
path: 'product-space-detail',
name: 'productSpaceDetail',
component: () => import('@/views/data_asset/productSpaceDetail.vue'),
meta: {
title: '详情-',
sidebar: false,
breadcrumb: false,
cache: true,
......
<template>
<div class="container_wrap full" v-loading="fullscreenLoading">
<div class="content_main">
<ContentWrap id="id-baseInfo" title="逻辑空间信息" description="" :isExpand="baseInfoExpand" :expand-swicth="true"
class="mb16" @expand="(v) => baseInfoExpand = v">
<div class="list_panel">
<div class="list_item">
<span class="item_label">逻辑空间名称:</span>
<span class="item_value">
<ellipsis-tooltip :content="detailInfo.spaceName || '--'" class-name="w100f mr8-i"
:refName="'tooltipOver' + 'spaceName'"></ellipsis-tooltip>
</span>
</div>
<div class="list_item">
<span class="item_label">所属领域:</span>
<span class="item_value">{{ detailInfo.domainName || '--' }}</span>
</div>
<div class="list_item">
<span class="item_label">创建企业:</span>
<span class="item_value"> <ellipsis-tooltip :content="detailInfo.tenantName || '--'"
class-name="w100f mr8-i" :refName="'tooltipOver' + 'tenantName'"></ellipsis-tooltip></span>
</div>
<div class="list_item">
<span class="item_label">是否开启:</span>
<span class="item_value">{{ detailInfo.bizState ? '是' : '否' }}</span>
</div>
</div>
<el-tabs v-model="activeTabName" class="param-tabs" style="margin-top: 8px;">
<el-tab-pane label="成员权限" name="member">
<Table ref="memberTableRef" :tableInfo="memberTableInfo" class="fiveRow-table" />
</el-tab-pane>
<el-tab-pane label="策略配置" name="strategy">
<StrategyTable ref="strategyTableDetailRef" :show-title="false" :is-look="true"
:value="detailInfo.policyRSVOS || []">
</StrategyTable>
</el-tab-pane>
</el-tabs>
</ContentWrap>
<ContentWrap id="id-approveInfo" title="流程审批" expandSwicth style="margin-top: 15px" :isExpand="expandApprove"
@expand="(v) => expandApprove = v">
<ApprovalProcess ref="approvalProcessRef" v-if="deploymentId" :deploymentId="deploymentId"
:processInstanceId="processInstanceId">
</ApprovalProcess>
</ContentWrap>
</div>
<div class="tool_btns">
<div class="btns">
<el-button v-for="btn in toolBtns" :type="btn.type" :plain="btn.plain" @click="btnClick(btn)">{{ btn.label }}</el-button>
</div>
</div>
</div>
</template>
<script lang="ts" setup name="productSpaceDetail">
import useUserStore from "@/store/modules/user";
import StrategyTable from "../data_smart_contract/components/strategyTable.vue";
import { TableColumnWidth } from "@/utils/enum";
const { proxy } = getCurrentInstance() as any;
const userStore = useUserStore();
const route = useRoute();
const router = useRouter();
const fullPath = route.fullPath;
const fullscreenLoading = ref(false);
const baseInfoExpand = ref(true);
const expandApprove = ref(true);
const deploymentId = ref('');
const processInstanceId = ref('');
const detailInfo: any = ref({});
/** 页签当前活跃的有成员权限和策略配置 */
const activeTabName = ref('member');
const toolBtns: any = computed(() => {
let btnsArr: any = [{
label: "关闭", value: "cancel", plain: true
}];
// TODO,资产运营平台TODO
return btnsArr;
});
const btnClick = (btn: any) => {
switch (btn.value) {
case 'cancel':
cancel();
break;
default:
break;
}
}
const cancel = () => {
userStore.setTabbar(userStore.tabbar.filter((tab: any) => tab.fullPath !== fullPath));
router.push({
name: 'productApplicationManage'
});
}
onBeforeMount(() => {
})
const memberTableInfo = ref({
id: "input-member-table",
height: '214px',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "成员名称", field: "memberGuid", width: 200 },
{ label: "角色类型", field: "roleType", width: 160 },
{ label: "描述", field: "description", width: 300 },
],
data: [],
showPage: false,
actionInfo: {
show: false,
}
});
</script>
<style lang="scss" scoped>
.content_main {
height: calc(100% - 44px);
padding: 16px;
overflow: hidden auto;
position: sticky;
}
.list_panel {
display: flex;
flex-wrap: wrap;
display: flex;
align-items: center;
.list_item {
width: 33.33%;
line-height: 32px;
font-size: 14px;
color: var(--el-text-color-regular);
display: flex;
justify-content: space-between;
min-width: 120px;
.item_label {
text-align: left;
}
.item_value {
color: var(--el-color-regular);
padding: 0 4px;
flex: 1;
text-align: justify;
min-width: 0;
&.link {
color: var(--el-color-primary);
cursor: pointer;
}
}
&.is_block {
width: 100%;
.item_value {
white-space: pre-wrap;
}
}
}
}
.tool_btns {
display: flex;
justify-content: center;
align-items: center;
height: 44px;
padding: 0 16px;
border-top: 1px solid #d9d9d9;
}
:deep(.el-tabs) {
margin-top: -8px;
.el-tabs__header {
margin-bottom: 8px;
}
.el-tabs__item {
height: 32px;
&:nth-child(2) {
padding-left: 16px;
}
}
}
</style>
\ No newline at end of file
<template>
<div class="container_wrap">
<div class="table_tool_wrap">
<el-button type="primary" @click="newCreate">新增</el-button>
<el-input v-model.trim="pageInfo.keyWord" placeholder="名称搜索" :suffix-icon="Search" clearable
@blur="toSearch(true, true)" @keyup.enter.native="searchEnterFun" />
</div>
<div class="table_panel_wrap">
<div v-show="listData.length" class="data-content" v-loading="listDataLoading">
<div class="card-content" v-for="(item, index) in listData" :key="item.guid" @click="handleDataClick(item)">
<div class="v-top">
<span class="title">{{ item.name }}</span>
<el-tag :type="tagType(item, 'approveState')">{{ tagMethod(item, 'approveState') }}</el-tag>
</div>
<div class="v-middle">
<div class="per">
<div class="desc">产品数量</div>
<div class="cnt">{{ item.productNum == null ? '--' : changeNum(item.productNum, 0) }}</div>
</div>
<div class="per">
<div class="desc">成员数量</div>
<div class="cnt">{{ item.productNum == null ? '--' : changeNum(item.productNum, 0) }}</div>
</div>
</div>
<div class="v-bottom">
<div class="per" @click.stop="clickDetail(item)">详情</div>
<div class="divider" @click.stop></div>
<div class="per" @click.stop="clickDelete(item)">删除</div>
</div>
</div>
</div>
<div v-show="!listData.length" class="empty-content">
<img src="../../assets/images/empty-data.png" :style="{ width: '168px', height: '96px' }" />
<div class="empty-text">暂无数据</div>
</div>
</div>
<PageNav :class="[pageInfo.type]" :pageInfo="pageInfo" @pageChange="pageChange" />
</div>
</template>
<script setup lang="ts" name="productSpaceManage">
import { commonPageConfig } from '@/components/PageNav';
import { changeNum, tagMethod, tagType } from '@/utils/common';
import { Search } from "@element-plus/icons-vue";
const router = useRouter();
const { proxy } = getCurrentInstance() as any;
/** 卡片加载条 */
const listDataLoading = ref(false);
/** 列表数据 */
const listData: any = ref([{ guid: '1', name: '产品空间1' }, { guid: '2', name: '产品空间1' }, { guid: '3', name: '产品空间1' }, { guid: '4', name: '产品空间1' },
{ guid: '5', name: '产品空间1' }
]);
const oldKeyWord = ref(""); // 记录上次输入的关键字,避免重复搜索
const isEnter = ref(false); // 标识是否通过回车键触发搜索
const pageInfo = ref({
...commonPageConfig,
rows: 0,
type: "normal",
keyWord: '',
});
const getTableData = (clear = false) => {
// listDataLoading.value = true;
// getDamCatalogTable({
// pageSize: pageInfo.value.limit,
// pageIndex: pageInfo.value.curr,
// keyWord: pageInfo.value.keyWord
// }).then((res: any) => {
// listDataLoading.value = false;
// if (res.code == proxy.$passCode) {
// const data = res.data || {}
// listData.value = data.records || [];
// pageInfo.value.limit = data.pageSize
// pageInfo.value.curr = data.pageIndex
// pageInfo.value.rows = data.totalRows
// } else {
// proxy.$ElMessage.error(res.msg);
// }
// });
}
const pageChange = (info) => {
pageInfo.value.curr = Number(info.curr);
pageInfo.value.limit = Number(info.limit);
getTableData();
};
/**
* 触发搜索查询
* @param clear - 是否清空页码,默认为true
* @param isBlur - 是否是失焦触发,默认为false
*/
const toSearch = (clear: boolean = true, isBlur: boolean = false) => {
if (clear) {
pageInfo.value.curr = 1 // 重置为第一页
}
// 如果是失焦且不是回车触发,且关键词没有变化,则不执行搜索
if (isBlur && !isEnter.value && oldKeyWord.value === pageInfo.value.keyWord) {
return;
}
isEnter.value = false; // 重置回车状态
oldKeyWord.value = pageInfo.value.keyWord; // 更新关键词记录
getTableData(clear);
}
/**
* 回车搜索事件处理
* 在输入框按下回车键时触发
* @param event - 键盘事件对象
*/
const searchEnterFun = (event) => {
isEnter.value = true; // 标记为回车触发
event.target?.blur(); // 输入框失去焦点
}
const newCreate = () => {
router.push({
name: 'productSpaceEdit'
})
}
const handleDataClick = (item) => {
router.push({
name: 'productSpaceEdit',
query: {
guid: item.guid,
name: item.name
}
})
}
const clickDetail = (item) => {
router.push({
name: 'productSpaceDetail',
query: {
guid: item.guid,
name: item.name
}
})
}
const clickDelete = (item) => {
proxy.$openMessageBox('此操作将永久删除该空间,是否继续?', () => {
// TODO
}, () => {
proxy.$ElMessage.info('已取消删除');
});
}
</script>
<style lang="scss" scoped>
.container_wrap {
padding: 0 16px;
}
.table_tool_wrap {
display: flex;
align-items: center;
justify-content: space-between;
padding-top: 12px;
.el-input {
width: 240px;
}
}
.table_panel_wrap {
height: calc(100% - 94px);
margin-top: 12px;
position: relative;
.data-content {
display: flex;
flex-wrap: wrap;
gap: 16px 16px;
align-content: flex-start;
overflow-y: auto;
.card-content {
width: calc(25% - 13px);
min-width: 220px;
height: 174px;
border: 1px solid rgba(229, 229, 229, 1);
border-radius: 4px;
cursor: pointer;
position: relative;
&:hover {
border-color: var(--el-color-primary);
}
.v-top {
height: 48px;
padding: 12px 16px;
display: flex;
.title {
font-size: 16px;
color: #212121;
line-height: 24px;
font-weight: 600;
width: calc(100% - 58px);
white-space: nowrap;
/* 防止文本换行 */
overflow: hidden;
/* 隐藏超出容器的文本 */
text-overflow: ellipsis;
/* 显示省略号 */
}
.el-tag {
width: 50px;
text-align: center;
line-height: 18px;
}
}
.v-middle {
height: 80px;
display: flex;
.per {
width: 50%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.desc {
font-size: 14px;
color: #999999;
line-height: 21px;
margin-bottom: 4px;
}
.cnt {
font-size: 24px;
color: #44ABB4;
line-height: 36px;
font-weight: 600;
}
}
}
.v-bottom {
background: #FAFAFA;
height: 44px;
display: flex;
border-top: 1px solid rgba(229, 229, 229, 1);
.divider {
border-right: 1px solid rgba(229, 229, 229, 1);
}
.per {
width: 50%;
display: flex;
align-items: center;
justify-content: center;
padding: 8px 0px;
}
}
}
}
}
.empty-content {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 100%;
flex-direction: column;
.empty-text {
font-size: 14px;
color: #b2b2b2;
margin-top: 12px;
}
}
</style>
\ 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!