update 看板个性配置组件封装
This commit is contained in:
192
src/components/common/dashboardSetting/index.vue
Normal file
192
src/components/common/dashboardSetting/index.vue
Normal file
@@ -0,0 +1,192 @@
|
||||
<template>
|
||||
<div class="dashboard-setting">
|
||||
<!-- 配置按钮 -->
|
||||
<div class="icon-btn" v-if="showSettingBtn">
|
||||
<el-tooltip :content="$t('个性化配置')" placement="top">
|
||||
<div class="setting-btn" @click="settingDiaVisible = true">
|
||||
<el-icon :size="18">
|
||||
<Setting />
|
||||
</el-icon>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<!-- 配置弹窗 -->
|
||||
<settingDia
|
||||
v-model="settingDiaVisible"
|
||||
:configJson="configJson"
|
||||
:baseList="baseList"
|
||||
@updateConfig="updateConfigFun"
|
||||
/>
|
||||
<!-- 图表容器 -->
|
||||
<div class="content" v-if="!loading">
|
||||
<div v-for="config in currentList" :key="config.id" class="chart-box">
|
||||
<component :is="config.component" v-bind="config.props" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import { getUserId, getUserTenantId } from '@/utils/user';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { Setting } from '@element-plus/icons-vue';
|
||||
import settingDia from './settingDia.vue';
|
||||
import {
|
||||
addUserFormConfigureApi,
|
||||
getUserFormConfigureApi,
|
||||
updateUserFormConfigureApi,
|
||||
} from '@/api/system/systemData';
|
||||
|
||||
interface ChartConfig {
|
||||
id: string;
|
||||
title: string;
|
||||
component: any;
|
||||
props: Record<string, any>;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
baseList: ChartConfig[];
|
||||
showSettingBtn?: boolean;
|
||||
formNamePrefix?: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
showSettingBtn: true,
|
||||
formNamePrefix: 'data_Statistics_Setting',
|
||||
});
|
||||
|
||||
const emit = defineEmits(['configUpdated']);
|
||||
|
||||
// 状态
|
||||
const settingDiaVisible = ref(false);
|
||||
const currentList = ref<ChartConfig[]>([]);
|
||||
const loading = ref(false);
|
||||
const hasConfig = ref(false);
|
||||
const configJson = ref('');
|
||||
|
||||
// 获取表单名称
|
||||
const getFormName = () => {
|
||||
return `${props.formNamePrefix}_${getUserId()}_${getUserTenantId()}`;
|
||||
};
|
||||
|
||||
// 配置弹窗点击确定
|
||||
const updateConfigFun = async (info: any) => {
|
||||
try {
|
||||
let res: any;
|
||||
// 新增 or 修改
|
||||
if (hasConfig.value) {
|
||||
res = await updateUserFormConfigureApi({
|
||||
formName: getFormName(),
|
||||
formConfig: info,
|
||||
});
|
||||
} else {
|
||||
res = await addUserFormConfigureApi({
|
||||
formName: getFormName(),
|
||||
formConfig: info,
|
||||
});
|
||||
}
|
||||
// 接口成功后才更新 configJson
|
||||
if (res.code === 200) {
|
||||
ElMessage.success('配置成功');
|
||||
configJson.value = info;
|
||||
hasConfig.value = true;
|
||||
// 根据配置的结果对展示的图表进行排序
|
||||
setConfig(info);
|
||||
emit('configUpdated', info);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('更新配置失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 设置 参数json
|
||||
const setConfig = (dataStatisticsSetting: any) => {
|
||||
if (dataStatisticsSetting) {
|
||||
const configInfo = JSON.parse(dataStatisticsSetting);
|
||||
// 根据配置的结果对展示的图表进行排序
|
||||
const list = configInfo
|
||||
.filter((config: any) => config.inBoard)
|
||||
.map((config: any) => props.baseList.find((item) => item.id === config.key))
|
||||
.filter(Boolean);
|
||||
currentList.value = list as ChartConfig[];
|
||||
} else {
|
||||
currentList.value = props.baseList;
|
||||
}
|
||||
};
|
||||
|
||||
// 获取该用户的配置
|
||||
const getFormConfigure = async () => {
|
||||
loading.value = true;
|
||||
const params = {
|
||||
formName: getFormName(),
|
||||
};
|
||||
try {
|
||||
// 临时保存原始的 ElMessage.warning
|
||||
const originalWarning = ElMessage.warning;
|
||||
// 临时禁用警告消息
|
||||
ElMessage.warning = () => ({ close: () => {} }) as any;
|
||||
const res: any = await getUserFormConfigureApi(params);
|
||||
if (res.code === 200) {
|
||||
// 如果存在配置,则使用配置
|
||||
hasConfig.value = true;
|
||||
configJson.value = res.data.formConfig;
|
||||
setConfig(res.data.formConfig);
|
||||
} else {
|
||||
// 如果不存在配置,则使用默认配置
|
||||
hasConfig.value = false;
|
||||
setConfig('');
|
||||
}
|
||||
// 恢复原始的 ElMessage.warning
|
||||
ElMessage.warning = originalWarning;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 监听baseList变化
|
||||
watch(
|
||||
() => props.baseList,
|
||||
() => {
|
||||
if (!hasConfig.value) {
|
||||
setConfig('');
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
getFormConfigure();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dashboard-setting {
|
||||
.icon-btn {
|
||||
height: 20px;
|
||||
background: var(--el-bg-color);
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-right: 8px;
|
||||
.setting-btn {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
width: 100%;
|
||||
height: calc(100% - 20px);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
.chart-box {
|
||||
width: calc(50% - 8px);
|
||||
height: 400px;
|
||||
position: relative;
|
||||
margin-bottom: 16px;
|
||||
&:nth-last-child(-n + 2) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="comp-content">
|
||||
<Dialog
|
||||
v-model="diaVisible"
|
||||
diaTitle="数据统计看板布局设置"
|
||||
diaTitle="看板布局设置"
|
||||
top="2vh"
|
||||
width="500"
|
||||
height="80%"
|
||||
@@ -66,28 +66,26 @@ import Dialog from '@/components/common/dialog/index.vue';
|
||||
interface Props {
|
||||
modelValue: boolean;
|
||||
configJson?: string;
|
||||
baseList: any[];
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
modelValue: false,
|
||||
configJson: '',
|
||||
baseList: () => [],
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'updateConfig']);
|
||||
const diaVisible = ref(false);
|
||||
const tableData = ref<any>([]);
|
||||
const getBaseTable = () => [
|
||||
{ key: 'userGroupProject', title: '用户组项目统计', inBoard: true },
|
||||
{ key: 'userDifficultyCoefficient', title: '用户组难度系数统计', inBoard: true },
|
||||
{ key: 'userTaskComplete', title: '用户组任务完成情况统计', inBoard: true },
|
||||
{ key: 'projectTaskComplete', title: '项目任务完成情况统计', inBoard: true },
|
||||
{ key: 'taskCompletionMechine', title: '任务完成统计(机台)', inBoard: true },
|
||||
{ key: 'taskCompletionDiscipline', title: '任务完成统计(学科)', inBoard: true },
|
||||
{ key: 'performanceCompletionMechine', title: '指标完成统计(机台)', inBoard: true },
|
||||
{ key: 'performanceCompletionDiscipline', title: '指标完成统计(学科)', inBoard: true },
|
||||
{ key: 'reviewPassed', title: '工位评审通过统计', inBoard: true },
|
||||
{ key: 'fileOperate', title: '文件下载统计', inBoard: true },
|
||||
];
|
||||
// 默认的顺序,按照传入的baseList顺序
|
||||
const getBaseTable = () => {
|
||||
return props.baseList.map((item) => ({
|
||||
key: item.id,
|
||||
title: item.title,
|
||||
inBoard: true,
|
||||
}));
|
||||
};
|
||||
|
||||
const vxeTableRef = ref<any>();
|
||||
|
||||
@@ -1,31 +1,10 @@
|
||||
<template>
|
||||
<div class="gl-page-content-grey data-statistics" v-loading="loading">
|
||||
<!-- 配置按钮 -->
|
||||
<div class="icon-btn">
|
||||
<el-tooltip :content="$t('个性化配置')" placement="top">
|
||||
<div class="setting-btn" @click="settingDiaVisible = true">
|
||||
<el-icon :size="18">
|
||||
<Setting />
|
||||
</el-icon>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<settingDia
|
||||
v-model="settingDiaVisible"
|
||||
:configJson="configJson"
|
||||
@updateConfig="updateConfigFun"
|
||||
/>
|
||||
<!-- echart 图表 -->
|
||||
<div class="content">
|
||||
<div v-for="config in currentList" :key="config.id" class="chart-box">
|
||||
<component :is="config.component" v-bind="config.props" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="gl-page-content-grey">
|
||||
<dashboard-setting :baseList="baseList" @configUpdated="handleConfigUpdated" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { getThemeColor } from '@/utils/theme';
|
||||
// 引入子组件
|
||||
import fileOperateChart from './dataStatistics/fileOperateChart.vue';
|
||||
@@ -36,29 +15,21 @@ import taskCompletion from './dataStatistics/taskCompletion.vue';
|
||||
import performanceCompletion from './dataStatistics/performanceCompletion.vue';
|
||||
import projectTaskComplete from './dataStatistics/projectTaskComplete.vue';
|
||||
import reviewPassed from './dataStatistics/reviewPassed.vue';
|
||||
import settingDia from './dataStatistics/settingDia.vue';
|
||||
import { getUserId, getUserTenantId } from '@/utils/user';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import {
|
||||
addUserFormConfigureApi,
|
||||
getUserFormConfigureApi,
|
||||
updateUserFormConfigureApi,
|
||||
} from '@/api/system/systemData';
|
||||
import { getTaskStatusColorList } from '@/utils/enum/task';
|
||||
import dashboardSetting from '@/components/common/dashboardSetting/index.vue';
|
||||
import { useDict } from '@/utils/useDict';
|
||||
import { useProjectList } from '@/utils/useProjectList';
|
||||
import { getTaskStatusColorList, getAchieveColorList } from '@/utils/enum/task';
|
||||
|
||||
// 统一请求项目列表
|
||||
useProjectList();
|
||||
|
||||
const { TASK_ACHIEVE_STATUS } = useDict('TASK_ACHIEVE_STATUS');
|
||||
const { TASK_ACHIEVE_STATUS, RESULT_ACHIEVE_STATUS } = useDict(
|
||||
'TASK_ACHIEVE_STATUS',
|
||||
'RESULT_ACHIEVE_STATUS'
|
||||
);
|
||||
const statusColorList = getTaskStatusColorList(Object.keys(TASK_ACHIEVE_STATUS.value.O));
|
||||
const performanceColorList = getAchieveColorList(Object.keys(RESULT_ACHIEVE_STATUS.value.O));
|
||||
|
||||
const performanceColorList = [
|
||||
'rgb(200, 201, 204)', // 未分析
|
||||
getThemeColor('--el-color-danger'), // 不合格
|
||||
getThemeColor('--el-color-success'), // 合格
|
||||
];
|
||||
// 难度系数颜色列表
|
||||
const difficultyCountColorList = [
|
||||
'#67c23a',
|
||||
@@ -75,17 +46,18 @@ const processNodeColorList = [
|
||||
getThemeColor('--el-color-success'), // 已通过
|
||||
getThemeColor('--el-color-danger'), // 已拒绝
|
||||
];
|
||||
// 设置弹窗
|
||||
const settingDiaVisible = ref(false);
|
||||
|
||||
// 组件基础配置数组
|
||||
const baseList = ref([
|
||||
const baseList = [
|
||||
{
|
||||
id: 'userGroupProject',
|
||||
title: '用户组项目统计',
|
||||
component: userGroupProjectChart, // 用户组项目统计
|
||||
props: {},
|
||||
},
|
||||
{
|
||||
id: 'userDifficultyCoefficient',
|
||||
title: '用户组难度系数统计',
|
||||
component: userDifficultyCoefficientChart, // 用户组难度系数统计
|
||||
props: {
|
||||
difficultyCountColorList,
|
||||
@@ -93,6 +65,7 @@ const baseList = ref([
|
||||
},
|
||||
{
|
||||
id: 'userTaskComplete',
|
||||
title: '用户组任务完成情况统计',
|
||||
component: userTaskCompleteChart, // 用户组任务完成情况统计
|
||||
props: {
|
||||
statusColorList,
|
||||
@@ -100,6 +73,7 @@ const baseList = ref([
|
||||
},
|
||||
{
|
||||
id: 'projectTaskComplete',
|
||||
title: '项目任务完成情况统计',
|
||||
component: projectTaskComplete, // 项目任务完成情况统计
|
||||
props: {
|
||||
statusColorList,
|
||||
@@ -107,6 +81,7 @@ const baseList = ref([
|
||||
},
|
||||
{
|
||||
id: 'taskCompletionMechine',
|
||||
title: '任务完成统计(机台)',
|
||||
component: taskCompletion, // 任务完成统计(机台)
|
||||
props: {
|
||||
statusColorList,
|
||||
@@ -115,6 +90,7 @@ const baseList = ref([
|
||||
},
|
||||
{
|
||||
id: 'taskCompletionDiscipline',
|
||||
title: '任务完成统计(学科)',
|
||||
component: taskCompletion, // 任务完成统计(学科)
|
||||
props: {
|
||||
statusColorList,
|
||||
@@ -123,6 +99,7 @@ const baseList = ref([
|
||||
},
|
||||
{
|
||||
id: 'performanceCompletionMechine',
|
||||
title: '指标完成统计(机台)',
|
||||
component: performanceCompletion, // 指标完成统计(机台)
|
||||
props: {
|
||||
performanceColorList,
|
||||
@@ -131,6 +108,7 @@ const baseList = ref([
|
||||
},
|
||||
{
|
||||
id: 'performanceCompletionDiscipline',
|
||||
title: '指标完成统计(学科)',
|
||||
component: performanceCompletion, // 指标完成统计(学科)
|
||||
props: {
|
||||
performanceColorList,
|
||||
@@ -139,6 +117,7 @@ const baseList = ref([
|
||||
},
|
||||
{
|
||||
id: 'reviewPassed',
|
||||
title: '工位评审通过统计',
|
||||
component: reviewPassed, // 工位评审通过统计
|
||||
props: {
|
||||
processNodeColorList,
|
||||
@@ -146,121 +125,14 @@ const baseList = ref([
|
||||
},
|
||||
{
|
||||
id: 'fileOperate',
|
||||
title: '文件下载统计',
|
||||
component: fileOperateChart,
|
||||
props: {},
|
||||
},
|
||||
]);
|
||||
// 当前展示的图表
|
||||
const currentList = ref();
|
||||
const loading = ref(false);
|
||||
// 配置弹窗点击确定
|
||||
const updateConfigFun = async (info: any) => {
|
||||
try {
|
||||
let res: any;
|
||||
// 新增 or 修改
|
||||
if (hasConfig.value) {
|
||||
res = await updateUserFormConfigureApi({
|
||||
formName: 'data_Statistics_Setting' + '_' + getUserId() + '_' + getUserTenantId(),
|
||||
formConfig: info,
|
||||
});
|
||||
} else {
|
||||
res = await addUserFormConfigureApi({
|
||||
formName: 'data_Statistics_Setting' + '_' + getUserId() + '_' + getUserTenantId(),
|
||||
formConfig: info,
|
||||
});
|
||||
}
|
||||
// 接口成功后才更新 configJson
|
||||
if (res.code === 200) {
|
||||
ElMessage.success('配置成功');
|
||||
configJson.value = info;
|
||||
hasConfig.value = true;
|
||||
// 根据配置的结果对展示的图表进行排序
|
||||
setConfig(info);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('更新配置失败:', error);
|
||||
}
|
||||
};
|
||||
];
|
||||
|
||||
// 设置 参数json
|
||||
const setConfig = (dataStatisticsSetting: any) => {
|
||||
if (dataStatisticsSetting) {
|
||||
const configInfo = JSON.parse(dataStatisticsSetting);
|
||||
// 根据配置的结果对展示的图表进行排序
|
||||
const list = configInfo
|
||||
.filter((config: any) => config.inBoard)
|
||||
.map((config: any) => baseList.value.find((item) => item.id === config.key))
|
||||
.filter(Boolean);
|
||||
currentList.value = list;
|
||||
} else {
|
||||
currentList.value = baseList.value;
|
||||
}
|
||||
// 配置更新回调
|
||||
const handleConfigUpdated = () => {
|
||||
// console.log('配置已更新:', config);
|
||||
};
|
||||
// 是否配置过
|
||||
const hasConfig = ref(false);
|
||||
// 配置规则
|
||||
const configJson = ref('');
|
||||
// 获取该用户的配置
|
||||
const getFormConfigure = async () => {
|
||||
loading.value = true;
|
||||
const params = {
|
||||
formName: 'data_Statistics_Setting' + '_' + getUserId() + '_' + getUserTenantId(),
|
||||
};
|
||||
try {
|
||||
// 临时保存原始的 ElMessage.warning
|
||||
const originalWarning = ElMessage.warning;
|
||||
// 临时禁用警告消息
|
||||
ElMessage.warning = () => ({ close: () => {} }) as any;
|
||||
const res: any = await getUserFormConfigureApi(params);
|
||||
if (res.code === 200) {
|
||||
// 如果存在配置,则使用配置
|
||||
hasConfig.value = true;
|
||||
configJson.value = res.data.formConfig;
|
||||
setConfig(res.data.formConfig);
|
||||
} else {
|
||||
// 如果不存在配置,则使用默认配置
|
||||
hasConfig.value = false;
|
||||
setConfig('');
|
||||
}
|
||||
// 恢复原始的 ElMessage.warning
|
||||
ElMessage.warning = originalWarning;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getFormConfigure();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.gl-page-content-grey {
|
||||
.icon-btn {
|
||||
height: 20px;
|
||||
background: var(--el-bg-color);
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-right: 8px;
|
||||
.setting-btn {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
width: 100%;
|
||||
height: calc(100% - 20px);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
.chart-box {
|
||||
width: calc(50% - 8px);
|
||||
height: 400px;
|
||||
position: relative;
|
||||
margin-bottom: 16px;
|
||||
&:nth-last-child(-n + 2) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user