Compare commits

8 Commits
dev ... main

Author SHA1 Message Date
7f779e021d update 解决项目列表卡片按钮下拉问题 2026-02-14 14:08:54 +08:00
32a7e34e64 merge 2026-02-13 17:04:27 +08:00
f1cdf878ab update:文件下载配置 2026-02-13 17:03:52 +08:00
4c0f6fb246 bug 修复 2026-02-13 16:52:50 +08:00
3d7f1bbe7e update 2026-02-13 16:13:25 +08:00
4cbb38b339 update:宜安配置 2026-02-13 15:13:10 +08:00
8697bc9bcd update:宜安配置 2026-02-13 14:59:24 +08:00
6d3448e542 update:数据总览维度限制 2026-02-13 10:39:49 +08:00
24 changed files with 146 additions and 136 deletions

View File

@@ -17,8 +17,8 @@ VITE_API_STATIC_FILE=http://192.168.65.161:3000/static
VITE_API_IMAGE_PREVIEW_URL=http://192.168.65.161:3000/imagePreview VITE_API_IMAGE_PREVIEW_URL=http://192.168.65.161:3000/imagePreview
# 文件预览地址 # 文件预览地址
VITE_API_FILE_PREVIEW_URL=http://192.168.65.161:3000/preview/onlinePreview VITE_API_FILE_PREVIEW_URL=http://192.168.65.161:3000/preview/onlinePreview
# 文件下载地址(暂未使用) # 文件下载地址
VITE_API_FILE_URL=http://192.168.65.161:7104 VITE_API_DOWNLOAD_URL=http://192.168.65.161:9000
# onlyOffice服务 # onlyOffice服务
VITE_API_ONLYOFFICE_URL=http://192.168.65.161:18888 VITE_API_ONLYOFFICE_URL=http://192.168.65.161:18888
# onlyOffice回调服务 # onlyOffice回调服务

40
.env.eontec Normal file
View File

@@ -0,0 +1,40 @@
# 测试环境
NODE_ENV=test
VITE_APP_ENV=test
# 租户
VITE_API_TENANT_NAME = eontec
# http请求的baseUrl/api为代理字段
VITE_API_BASE_URL=/api/simulation
# 本地环境http地址线上通过nginx转发/api到指定服务地址
VITE_API_HTTP_URL=http://192.168.65.161:7100
# ws请求的baseUrl/wsApi为代理字段
VITE_API_WS_BASE_URL=/wsApi/simulation
# 本地环境ws地址线上通过nginx转发/wsApi到指定服务地址
VITE_API_WS_URL=ws://192.168.65.161:7100
# 静态资源/usr/local/nginx/html/static
VITE_API_STATIC_FILE=http://192.168.65.161:3000/static
# 图片预览地址
VITE_API_IMAGE_PREVIEW_URL=http://cidweb.eon.com.cn:3000/imagePreview
# 文件预览地址
VITE_API_FILE_PREVIEW_URL=http://cidweb.eon.com.cn:3000/preview/onlinePreview
# 文件下载地址
VITE_API_DOWNLOAD_URL=http://cidweb.eon.com.cn:3000
# onlyOffice服务
VITE_API_ONLYOFFICE_URL=http://192.168.65.161:18888
# onlyOffice回调服务
VITE_API_ONLYOFFICE_CALLBACK=http://192.168.65.161:3000/api/simulation/data/data/onlyOfficeCallback
# 基线地址用于onlyOffice预览
VITE_API_SPDM_URL=http://192.168.65.161:3000/spdm
# CID地址
VITE_API_CID_URL=http://192.168.65.161:3001
VITE_API_PREFIX_APPROVE=/approve/
VITE_API_PREFIX_CAPABILITY=/capability/
VITE_API_PREFIX_DATA=/data/
VITE_API_PREFIX_PBS=/pbs/
VITE_API_PREFIX_PERFORMANCE=/performance/
VITE_API_PREFIX_PROJECT=/project/
VITE_API_PREFIX_SYSTEM=/system/
VITE_API_PREFIX_TASK=/task/
VITE_API_PREFIX_APPLICATION=/application/
VITE_API_PREFIX_FLOWABLE=/flowable/

View File

@@ -17,8 +17,8 @@ VITE_API_STATIC_FILE=http://192.168.30.147:7115/static
VITE_API_IMAGE_PREVIEW_URL=http://192.168.30.147:7115/imagePreview VITE_API_IMAGE_PREVIEW_URL=http://192.168.30.147:7115/imagePreview
# 文件预览地址 # 文件预览地址
VITE_API_FILE_PREVIEW_URL=http://192.168.30.147:7115/preview/onlinePreview VITE_API_FILE_PREVIEW_URL=http://192.168.30.147:7115/preview/onlinePreview
# 文件下载地址(暂未使用) # 文件下载地址
VITE_API_FILE_URL=http://192.168.30.148:7104 VITE_API_DOWNLOAD_URL=http://192.168.30.146:9000
# onlyOffice服务 # onlyOffice服务
VITE_API_ONLYOFFICE_URL=http://192.168.30.148:18888 VITE_API_ONLYOFFICE_URL=http://192.168.30.148:18888
# onlyOffice回调服务 # onlyOffice回调服务

View File

@@ -17,8 +17,8 @@ VITE_API_STATIC_FILE=http://192.168.190.161:3000/static
VITE_API_IMAGE_PREVIEW_URL=http://192.168.190.161:3000/imagePreview VITE_API_IMAGE_PREVIEW_URL=http://192.168.190.161:3000/imagePreview
# 文件预览地址 # 文件预览地址
VITE_API_FILE_PREVIEW_URL=http://192.168.190.161:3000/preview/onlinePreview VITE_API_FILE_PREVIEW_URL=http://192.168.190.161:3000/preview/onlinePreview
# 文件下载地址(暂未使用) # 文件下载地址
VITE_API_FILE_URL=http://192.168.190.161:7104 VITE_API_DOWNLOAD_URL=http://192.168.190.161:9000
# onlyOffice服务 # onlyOffice服务
VITE_API_ONLYOFFICE_URL=http://192.168.65.161:18888 VITE_API_ONLYOFFICE_URL=http://192.168.65.161:18888
# onlyOffice回调服务 # onlyOffice回调服务

View File

@@ -17,8 +17,8 @@ VITE_API_STATIC_FILE=http://192.168.65.161:3000/static
VITE_API_IMAGE_PREVIEW_URL=http://192.168.65.161:3000/imagePreview VITE_API_IMAGE_PREVIEW_URL=http://192.168.65.161:3000/imagePreview
# 文件预览地址 # 文件预览地址
VITE_API_FILE_PREVIEW_URL=http://192.168.65.161:3000/preview/onlinePreview VITE_API_FILE_PREVIEW_URL=http://192.168.65.161:3000/preview/onlinePreview
# 文件下载地址(暂未使用) # 文件下载地址
VITE_API_FILE_URL=http://192.168.65.161:7104 VITE_API_DOWNLOAD_URL=http://192.168.65.161:9000
# onlyOffice服务 # onlyOffice服务
VITE_API_ONLYOFFICE_URL=http://192.168.65.161:18888 VITE_API_ONLYOFFICE_URL=http://192.168.65.161:18888
# onlyOffice回调服务 # onlyOffice回调服务

View File

@@ -10,6 +10,7 @@
"dev": "vite --mode development", "dev": "vite --mode development",
"build:dev": "vite build --mode development", "build:dev": "vite build --mode development",
"build:lyric": "vite build --mode lyric", "build:lyric": "vite build --mode lyric",
"build:eontec": "vite build --mode eontec",
"build:test": "vite build --mode test", "build:test": "vite build --mode test",
"build:prod": "vite build --mode production", "build:prod": "vite build --mode production",
"build": "run-p type-check \"build-only {@}\" --", "build": "run-p type-check \"build-only {@}\" --",

View File

@@ -105,7 +105,7 @@ const initFun = () => {
modeType.value = 'csv'; modeType.value = 'csv';
return; return;
} }
if (enableConfigByTenant([TENANT_ENUM.LYRIC])) { if (enableConfigByTenant([TENANT_ENUM.LYRIC, TENANT_ENUM.EONTEC])) {
modeType.value = 'kkFile'; modeType.value = 'kkFile';
diaVisible.value = true; diaVisible.value = true;
return; return;
@@ -134,25 +134,31 @@ const getCsvDataFun = () => {
current: 1, current: 1,
size: 1, size: 1,
}; };
listSimulationKeyResultApi(params).then((res: any) => { listSimulationKeyResultApi(params)
if (res.code === 200) { .then((res: any) => {
csvData.value = res.data?.data[0] || {}; if (res.code === 200) {
csvData.value = res.data?.data[0] || {};
}
})
.finally(() => {
diaVisible.value = true; diaVisible.value = true;
} });
});
}; };
const getOnlyOfficeFun = () => { const getOnlyOfficeFun = () => {
const params = { const params = {
fileId: props.fileId, fileId: props.fileId,
}; };
downloadFileForEditApi(params).then((res: any) => { downloadFileForEditApi(params)
if (res.code === 200) { .then((res: any) => {
fileData.value = JSON.stringify(res.data); if (res.code === 200) {
fileKey.value = `${props.fileId}_${getUserId()}`; fileData.value = JSON.stringify(res.data);
fileKey.value = `${props.fileId}_${getUserId()}`;
}
})
.finally(() => {
diaVisible.value = true; diaVisible.value = true;
} });
});
}; };
const closeFun = () => { const closeFun = () => {

View File

@@ -606,7 +606,6 @@ defineExpose({
setSearchParamsFun, setSearchParamsFun,
setSearchParamByKeyFun, setSearchParamByKeyFun,
setOptionsFun, setOptionsFun,
getTableDataFun,
}); });
</script> </script>

View File

@@ -93,6 +93,7 @@ watch(
expStatus: localDetail.value.expStatus ? '1' : '0', expStatus: localDetail.value.expStatus ? '1' : '0',
eMemberList: getMemberListIds(localDetail.value.eMemberList), eMemberList: getMemberListIds(localDetail.value.eMemberList),
pMemberList: getMemberListIds(localDetail.value.pMemberList), pMemberList: getMemberListIds(localDetail.value.pMemberList),
planTime: [localDetail.value.beginTime, localDetail.value.endTime],
}); });
standard.value = localDetail.value.standard; standard.value = localDetail.value.standard;
if (localDetail.value.flowTemplate) { if (localDetail.value.flowTemplate) {

View File

@@ -30,22 +30,10 @@ export default [
// component: () => import('@/views/task/projectOverview/index.vue'), // component: () => import('@/views/task/projectOverview/index.vue'),
// }, // },
{ {
title: '所有项目', title: '项目列表',
path: '/project/allProject', path: '/project/projectList',
name: 'AllProject', name: 'ProjectList',
component: () => import('@/views/task/projectList/allProject.vue'), component: () => import('@/views/task/projectList/index.vue'),
},
{
title: '负责项目',
path: '/project/chargeProject',
name: 'ChargeProject',
component: () => import('@/views/task/projectList/chargeProject.vue'),
},
{
title: '关注项目',
path: '/project/followProject',
name: 'FllowProject',
component: () => import('@/views/task/projectList/followProject.vue'),
}, },
// { // {
// title: '项目详情', // title: '项目详情',

View File

@@ -37,22 +37,10 @@ export default [
// component: () => import('@/views/task/projectOverview/index.vue'), // component: () => import('@/views/task/projectOverview/index.vue'),
// }, // },
{ {
title: '所有项目', title: '项目列表',
path: '/project/allProject', path: '/project/projectList',
name: 'AllProject', name: 'ProjectList',
component: () => import('@/views/task/projectList/allProject.vue'), component: () => import('@/views/task/projectList/index.vue'),
},
{
title: '负责项目',
path: '/project/chargeProject',
name: 'ChargeProject',
component: () => import('@/views/task/projectList/chargeProject.vue'),
},
{
title: '关注项目',
path: '/project/followProject',
name: 'FllowProject',
component: () => import('@/views/task/projectList/followProject.vue'),
}, },
// { // {
// title: '项目详情', // title: '项目详情',

View File

@@ -20,16 +20,19 @@
</span> </span>
</div> </div>
<el-dropdown class="options-dropdown" :teleported="false"> <el-dropdown
class="options-dropdown"
:class="{ 'is-visible': isDropdownVisible }"
@command="handleCommand"
@visible-change="handleVisibleChange"
>
<div class="options-btn" @click.stop> <div class="options-btn" @click.stop>
<el-icon :size="18"><MoreFilled /></el-icon> <el-icon :size="18"><MoreFilled /></el-icon>
</div> </div>
<template #dropdown> <template #dropdown>
<el-dropdown-menu @click.stop> <el-dropdown-menu>
<el-dropdown-item v-for="(action, aIndex) in actionList" :key="aIndex"> <el-dropdown-item v-for="(action, aIndex) in actionList" :key="aIndex" :command="action">
<el-link :type="action.type" @click.stop="actionClickFun(action)"> <el-link :type="action.type">{{ action.title }}</el-link>
{{ action.title }}
</el-link>
</el-dropdown-item> </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
@@ -38,7 +41,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed, ref } from 'vue';
import { MoreFilled } from '@element-plus/icons-vue'; import { MoreFilled } from '@element-plus/icons-vue';
import { useDict } from '@/utils/useDict'; import { useDict } from '@/utils/useDict';
import { PROJECT_EXE_STATUS_CODE } from '@/utils/enum/project'; import { PROJECT_EXE_STATUS_CODE } from '@/utils/enum/project';
@@ -79,8 +82,15 @@ const cardClickFun = () => {
emit('cardClick', props.project); emit('cardClick', props.project);
}; };
const actionClickFun = (action: any) => { // const actionClickFun = (action: any) => {
emit('actionClick', props.project, action); // emit('actionClick', props.project, action);
// };
const handleCommand = (command: any) => {
emit('actionClick', props.project, command);
};
const isDropdownVisible = ref(false);
const handleVisibleChange = (visible: boolean) => {
isDropdownVisible.value = visible;
}; };
</script> </script>
@@ -101,6 +111,10 @@ const actionClickFun = (action: any) => {
transform: scale(1.1); transform: scale(1.1);
} }
} }
&:hover .options-dropdown,
.options-dropdown.is-visible {
opacity: 1;
}
.cover-img { .cover-img {
transition: transform 0.6s cubic-bezier(0.165, 0.84, 0.44, 1); transition: transform 0.6s cubic-bezier(0.165, 0.84, 0.44, 1);

View File

@@ -223,7 +223,7 @@ export const exportFile = (api: any, tableName: string, fileName: string, params
export const downloadFileById = async (fileId: number) => { export const downloadFileById = async (fileId: number) => {
// 1.点击事件下载 // 1.点击事件下载
// const link = document.createElement('a'); // const link = document.createElement('a');
// link.href = `${env.VITE_API_FILE_URL}/data/downloadFile?fileId=${fileId}`; // link.href = `${env.VITE_API_DOWNLOAD_URL}/data/downloadFile?fileId=${fileId}`;
// document.body.appendChild(link); // document.body.appendChild(link);
// link.click(); // link.click();
// document.body.removeChild(link); // document.body.removeChild(link);
@@ -232,7 +232,8 @@ export const downloadFileById = async (fileId: number) => {
// 3.浏览器下载 // 3.浏览器下载
getMinioPresignedUrlApi({ fileId }).then((res: any) => { getMinioPresignedUrlApi({ fileId }).then((res: any) => {
if (res.code === 200) { if (res.code === 200) {
const downloadUrl = res.data.minioDownloadUrl; const { minioDownloadUrl } = res.data;
const downloadUrl = env.VITE_API_DOWNLOAD_URL + minioDownloadUrl.split(':9000')[1];
window.open(downloadUrl, '_blank'); window.open(downloadUrl, '_blank');
} }
}); });

View File

@@ -74,9 +74,7 @@ const lang = {
: 'All Tasks', : 'All Tasks',
: 'Project Management', : 'Project Management',
: 'Poject Overview', : 'Poject Overview',
: 'All Project', : 'Project List',
: 'Charge Project',
: 'Follow Project',
仿: 'Simulation Dashboard', 仿: 'Simulation Dashboard',
仿: 'Simulation Loop Dashboard', 仿: 'Simulation Loop Dashboard',
: 'Accuracy Dashboard', : 'Accuracy Dashboard',

View File

@@ -74,9 +74,7 @@ const lang = {
: '所有任务', : '所有任务',
: '项目管理', : '项目管理',
: '项目总览', : '项目总览',
: '所有项目', : '项目列表',
: '负责项目',
: '关注项目',
仿: '仿真看板', 仿: '仿真看板',
仿: '仿真闭环看板', 仿: '仿真闭环看板',
仿: '仿真汇总看板', 仿: '仿真汇总看板',

View File

@@ -979,7 +979,7 @@ const updatePerformanceFun = async (data: any) => {
const res: any = await editPerformanceApi(data); const res: any = await editPerformanceApi(data);
if (res && res.code === 200) { if (res && res.code === 200) {
ElMessage.success('操作成功'); ElMessage.success('操作成功');
tableRef.value.getTableDataFun(); tableRef.value.resetFun();
} }
}; };

View File

@@ -22,7 +22,13 @@
<div class="select-content"> <div class="select-content">
<div class="select-content-head"> <div class="select-content-head">
<el-space> <el-space>
<el-button type="primary" @click="addSelectLevelFun">添加层级</el-button> <el-button
type="primary"
@click="addSelectLevelFun"
:disabled="selectLevelFormData.selectLevelList.length >= 10"
>
添加层级
</el-button>
<el-button type="primary" @click="saveSelectLevelFun">保存</el-button> <el-button type="primary" @click="saveSelectLevelFun">保存</el-button>
<el-button type="primary" @click="editFun">编辑</el-button> <el-button type="primary" @click="editFun">编辑</el-button>
</el-space> </el-space>
@@ -384,6 +390,7 @@ watch(
width: 100%; width: 100%;
flex: 1; flex: 1;
padding: var(--padding-normal) 0; padding: var(--padding-normal) 0;
overflow-y: auto;
.select-level-box { .select-level-box {
width: 100%; width: 100%;
display: flex; display: flex;

View File

@@ -755,6 +755,9 @@ const goDetailFun = (data: any) => {
const mergeCurrentData = ref<any>({}); const mergeCurrentData = ref<any>({});
const choseNodeFun = (mergeData: any) => { const choseNodeFun = (mergeData: any) => {
if (isSearching.value) {
isSearching.value = false;
}
mergeCurrentData.value = mergeData; mergeCurrentData.value = mergeData;
chosenData.value = []; chosenData.value = [];
let data: any = {}; let data: any = {};

View File

@@ -44,7 +44,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue';
import BaseTable from '@/components/common/table/baseTable.vue'; // import BaseTable from '@/components/common/table/baseTable.vue';
import FileTable from '@/components/common/fileTable/index.vue'; import FileTable from '@/components/common/fileTable/index.vue';
import { formatFileSize } from '@/utils/file'; import { formatFileSize } from '@/utils/file';
import { import {
@@ -108,7 +108,7 @@ const clickDeleteFun = () => {
// 清空回收站 // 清空回收站
const deleteAllLoading = ref(false); const deleteAllLoading = ref(false);
const clearAll = () => { const clearAll = () => {
ElMessageBox.confirm('是否确认清空回收站', '提示', { ElMessageBox.confirm('该操作会删除回收站中所有文件,是否继续', '提示', {
confirmButtonText: '确认', confirmButtonText: '确认',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning', type: 'warning',

View File

@@ -1,18 +0,0 @@
<template>
<ProjectList :expandAction="actionList" />
</template>
<script setup lang="ts">
import { ref } from 'vue';
import ProjectList from './components/projectList.vue';
const actionList = ref<any>([
{
title: '关注',
type: 'primary',
click: (row: any) => {
console.log('关注', row);
},
},
]);
</script>

View File

@@ -1,7 +0,0 @@
<template>
<ProjectList />
</template>
<script setup lang="ts">
import ProjectList from './components/projectList.vue';
</script>

View File

@@ -1,13 +1,18 @@
<template> <template>
<div class="project-card" @click="cardClickFun"> <div class="project-card" @click="cardClickFun">
<el-dropdown class="options-dropdown" :teleported="false"> <el-dropdown
class="options-dropdown"
:class="{ 'is-visible': isDropdownVisible }"
@command="handleCommand"
@visible-change="handleVisibleChange"
>
<div class="options-btn" @click.stop> <div class="options-btn" @click.stop>
<el-icon :size="18"><MoreFilled /></el-icon> <el-icon :size="18"><MoreFilled /></el-icon>
</div> </div>
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item v-for="(action, aIndex) in actionList" :key="aIndex"> <el-dropdown-item v-for="(action, aIndex) in actionList" :key="aIndex" :command="action">
<el-link :type="action.type" @click.stop="actionClickFun(action)"> <el-link :type="action.type">
{{ action.title }} {{ action.title }}
</el-link> </el-link>
</el-dropdown-item> </el-dropdown-item>
@@ -15,7 +20,11 @@
</template> </template>
</el-dropdown> </el-dropdown>
<img class="gl-pointer-class cover-img" :src="coverImgMap[project.detailImgUrl ? 'custom' : (index % 2 !== 0 ? 'blue' : 'green')]" alt="" /> <img
class="gl-pointer-class cover-img"
:src="coverImgMap[project.detailImgUrl ? 'custom' : index % 2 !== 0 ? 'blue' : 'green']"
alt=""
/>
<div class="bottom-box"> <div class="bottom-box">
<span class="gl-text-ellipsis gl-pointer-class" :title="project.nodeName"> <span class="gl-text-ellipsis gl-pointer-class" :title="project.nodeName">
@@ -29,7 +38,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed, ref } from 'vue';
import { MoreFilled } from '@element-plus/icons-vue'; import { MoreFilled } from '@element-plus/icons-vue';
import { useDict } from '@/utils/useDict'; import { useDict } from '@/utils/useDict';
import { PROJECT_EXE_STATUS_CODE } from '@/utils/enum/project'; import { PROJECT_EXE_STATUS_CODE } from '@/utils/enum/project';
@@ -70,8 +79,15 @@ const cardClickFun = () => {
emit('cardClick', props.project); emit('cardClick', props.project);
}; };
const actionClickFun = (action: any) => { // const actionClickFun = (action: any) => {
emit('actionClick', props.project, action); // emit('actionClick', props.project, action);
// };
const handleCommand = (command: any) => {
emit('actionClick', props.project, command);
};
const isDropdownVisible = ref(false);
const handleVisibleChange = (visible: boolean) => {
isDropdownVisible.value = visible;
}; };
</script> </script>
@@ -80,5 +96,9 @@ const actionClickFun = (action: any) => {
.project-card { .project-card {
@extend .project-card-base; @extend .project-card-base;
&:hover .options-dropdown,
.options-dropdown.is-visible {
opacity: 1;
}
} }
</style> </style>

View File

@@ -1,20 +0,0 @@
<template>
<ProjectList :expandAction="actionList" />
</template>
<script setup lang="ts">
import { ref } from 'vue';
import ProjectList from './components/projectList.vue';
const actionList = ref<any>([
{
title: '取消关注',
type: 'danger',
needConfirm: true,
confirmTip: '确定取消关注吗?',
click: (row: any) => {
console.log('取消关注', row);
},
},
]);
</script>

View File

@@ -136,14 +136,6 @@ import { hasPermission } from '@/utils/permission';
import DefaultProjectCard from '@/views/task/projectList/components/projectCard.vue'; import DefaultProjectCard from '@/views/task/projectList/components/projectCard.vue';
import LyricProjectCard from '@/tenants/lyric/views/project/projectCard.vue'; import LyricProjectCard from '@/tenants/lyric/views/project/projectCard.vue';
interface Props {
expandAction?: any;
}
const props = withDefaults(defineProps<Props>(), {
expandAction: [],
});
export interface IUserInfo { export interface IUserInfo {
id: number; id: number;
company: string | null; company: string | null;
@@ -207,7 +199,6 @@ const actionList = ref<any>([
return !hasPermission('project_list_delete_project'); return !hasPermission('project_list_delete_project');
}, },
}, },
...props.expandAction,
]); ]);
// //
const cardActionList = computed(() => { const cardActionList = computed(() => {
@@ -248,7 +239,7 @@ const currentProjectBaseInfo = reactive<any>({
memberList: [], memberList: [],
}); });
const viewType = ref('card'); const viewType = ref('car');
const currentRow = ref(); const currentRow = ref();