merge
This commit is contained in:
@@ -199,11 +199,11 @@ watch(
|
|||||||
(newVal) => {
|
(newVal) => {
|
||||||
if (newVal && Object.keys(newVal).length > 0) {
|
if (newVal && Object.keys(newVal).length > 0) {
|
||||||
const { tag1, workspace, discipline, createTimeArr, finishTimeArr } = newVal;
|
const { tag1, workspace, discipline, createTimeArr, finishTimeArr } = newVal;
|
||||||
if (tag1 !== undefined) formData.value.tag1 = tag1;
|
formData.value.tag1 = tag1;
|
||||||
if (workspace !== undefined) formData.value.workspace = workspace;
|
formData.value.workspace = workspace;
|
||||||
if (discipline !== undefined) formData.value.discipline = discipline;
|
formData.value.discipline = discipline;
|
||||||
if (createTimeArr !== undefined) formData.value.createTimeArr = createTimeArr;
|
formData.value.createTimeArr = createTimeArr;
|
||||||
if (finishTimeArr !== undefined) formData.value.finishTimeArr = finishTimeArr;
|
formData.value.finishTimeArr = finishTimeArr;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ deep: true }
|
{ deep: true }
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ interface Props {
|
|||||||
checkMethod?: any; // 处理勾选逻辑
|
checkMethod?: any; // 处理勾选逻辑
|
||||||
showAddCategoryButton?: boolean; // 是否显示添加分类按钮
|
showAddCategoryButton?: boolean; // 是否显示添加分类按钮
|
||||||
allowRootAddTask?: boolean; // 是否允许在根节点添加任务
|
allowRootAddTask?: boolean; // 是否允许在根节点添加任务
|
||||||
|
hideEditFn?: (row: any) => boolean; // 外部控制编辑按钮隐藏逻辑
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
@@ -156,6 +157,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
checkMethod: null,
|
checkMethod: null,
|
||||||
showAddCategoryButton: true,
|
showAddCategoryButton: true,
|
||||||
allowRootAddTask: false,
|
allowRootAddTask: false,
|
||||||
|
hideEditFn: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (props?.checkMethod) {
|
if (props?.checkMethod) {
|
||||||
@@ -410,7 +412,10 @@ const actionList = computed(() => {
|
|||||||
click: (row: any) => {
|
click: (row: any) => {
|
||||||
editRowFun(row);
|
editRowFun(row);
|
||||||
},
|
},
|
||||||
hide: () => {
|
hide: (row: any) => {
|
||||||
|
if (props.hideEditFn && props.hideEditFn(row)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return props.readonly;
|
return props.readonly;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -70,9 +70,14 @@
|
|||||||
:loading="loading"
|
:loading="loading"
|
||||||
:editMode="!enableConfigByTenant([TENANT_ENUM.LYRIC])"
|
:editMode="!enableConfigByTenant([TENANT_ENUM.LYRIC])"
|
||||||
:enableSelectCode="enableSelectCode"
|
:enableSelectCode="enableSelectCode"
|
||||||
|
:hideEditFn="hideEditForLyricFun"
|
||||||
>
|
>
|
||||||
<template #otherOptions>
|
<template #otherOptions>
|
||||||
<el-tooltip :content="$t('工况库.导入Excel')" placement="top">
|
<el-tooltip
|
||||||
|
:content="$t('工况库.导入Excel')"
|
||||||
|
placement="top"
|
||||||
|
v-if="!enableConfigByTenant([TENANT_ENUM.LYRIC])"
|
||||||
|
>
|
||||||
<div class="icon-change-view" @click="openImportPoolFun">
|
<div class="icon-change-view" @click="openImportPoolFun">
|
||||||
<el-icon :size="18">
|
<el-icon :size="18">
|
||||||
<Upload />
|
<Upload />
|
||||||
@@ -281,6 +286,13 @@ const enableSelectCode = computed(() => {
|
|||||||
return props.pageType === 'loadcase' && enableConfigByTenant([TENANT_ENUM.LYRIC]);
|
return props.pageType === 'loadcase' && enableConfigByTenant([TENANT_ENUM.LYRIC]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const hideEditForLyricFun = (row: any) => {
|
||||||
|
if (!enableConfigByTenant([TENANT_ENUM.LYRIC])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return row.nodeType === NODE_TYPE.TASK || row.nodeType === NODE_TYPE.PERFORMANCE;
|
||||||
|
};
|
||||||
|
|
||||||
let originalSnapshot: any = null;
|
let originalSnapshot: any = null;
|
||||||
|
|
||||||
const tableData = ref<any>([]);
|
const tableData = ref<any>([]);
|
||||||
|
|||||||
@@ -37,11 +37,15 @@ const getProjectGroupTaskCompleteStatistics = async (formData: any) => {
|
|||||||
finishTimeArr: formData.finishTimeArr,
|
finishTimeArr: formData.finishTimeArr,
|
||||||
});
|
});
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
|
const validStatusKeys =
|
||||||
|
res.data?.allExeStatus?.filter((statusKey: string) =>
|
||||||
|
TASK_ACHIEVE_STATUS.value.O.hasOwnProperty(statusKey)
|
||||||
|
) || [];
|
||||||
legendData =
|
legendData =
|
||||||
res.data?.allExeStatus?.map((item: any) => {
|
validStatusKeys?.map((item: any) => {
|
||||||
return TASK_ACHIEVE_STATUS.value.O[item] || item;
|
return TASK_ACHIEVE_STATUS.value.O[item] || item;
|
||||||
}) || [];
|
}) || [];
|
||||||
colors = res.data?.allExeStatus.map((item: any) => {
|
colors = validStatusKeys.map((item: any) => {
|
||||||
return props.statusColorList[Number(item) - 1];
|
return props.statusColorList[Number(item) - 1];
|
||||||
});
|
});
|
||||||
seriesData = legendData?.map((item: any) => {
|
seriesData = legendData?.map((item: any) => {
|
||||||
|
|||||||
@@ -63,15 +63,18 @@ const initTaskCompleteChart = async (formData: any) => {
|
|||||||
res.data?.result?.map((item: any) => {
|
res.data?.result?.map((item: any) => {
|
||||||
return item.name;
|
return item.name;
|
||||||
}) || [];
|
}) || [];
|
||||||
|
const validStatusKeys =
|
||||||
|
res.data?.allExeStatus?.filter((statusKey: string) =>
|
||||||
|
TASK_ACHIEVE_STATUS.value.O.hasOwnProperty(statusKey)
|
||||||
|
) || [];
|
||||||
titles =
|
titles =
|
||||||
res.data?.allExeStatus?.map((item: any) => {
|
validStatusKeys?.map((item: any) => {
|
||||||
return TASK_ACHIEVE_STATUS.value.O[item] || item;
|
return TASK_ACHIEVE_STATUS.value.O[item] || item;
|
||||||
}) || [];
|
}) || [];
|
||||||
const colors = res.data?.allExeStatus.map((item: any) => {
|
const colors = validStatusKeys.map((item: any) => {
|
||||||
return props.statusColorList[Number(item) - 1];
|
return props.statusColorList[Number(item) - 1];
|
||||||
});
|
});
|
||||||
const names = res.data?.allExeStatus || [];
|
const names = validStatusKeys || [];
|
||||||
|
|
||||||
for (let i = 0; i < names.length; i++) {
|
for (let i = 0; i < names.length; i++) {
|
||||||
const str = names[i];
|
const str = names[i];
|
||||||
|
|||||||
@@ -44,11 +44,16 @@ const getUserGroupTaskCompleteStatistics = async (formData: any) => {
|
|||||||
delete params.userId;
|
delete params.userId;
|
||||||
const res: any = await getUserGroupTaskCompleteStatisticsApi(params);
|
const res: any = await getUserGroupTaskCompleteStatisticsApi(params);
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
|
// 获取有效的状态列表(只保留 TASK_ACHIEVE_STATUS.value.O 中存在的 key)
|
||||||
|
const validStatusKeys =
|
||||||
|
res.data?.allExeStatus?.filter((statusKey: string) =>
|
||||||
|
TASK_ACHIEVE_STATUS.value.O.hasOwnProperty(statusKey)
|
||||||
|
) || [];
|
||||||
legendData =
|
legendData =
|
||||||
res.data?.allExeStatus?.map((item: any) => {
|
validStatusKeys?.map((item: any) => {
|
||||||
return TASK_ACHIEVE_STATUS.value.O[item];
|
return TASK_ACHIEVE_STATUS.value.O[item];
|
||||||
}) || [];
|
}) || [];
|
||||||
colors = res.data?.allExeStatus.map((item: any) => {
|
colors = validStatusKeys.map((item: any) => {
|
||||||
return props.statusColorList[Number(item) - 1];
|
return props.statusColorList[Number(item) - 1];
|
||||||
});
|
});
|
||||||
seriesData = legendData?.map((item: any) => {
|
seriesData = legendData?.map((item: any) => {
|
||||||
|
|||||||
@@ -127,23 +127,16 @@ const achieveFilterData = ref<any>({
|
|||||||
|
|
||||||
const handleProgressFilterUpdate = async (data: any) => {
|
const handleProgressFilterUpdate = async (data: any) => {
|
||||||
progressFilterData.value = data;
|
progressFilterData.value = data;
|
||||||
await progressBarChartUpdate(data);
|
await updateProgressCharts(data);
|
||||||
await progressPieChartUpdate(data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAchieveFilterUpdate = async (data: any) => {
|
const handleAchieveFilterUpdate = async (data: any) => {
|
||||||
achieveFilterData.value = data;
|
achieveFilterData.value = data;
|
||||||
await achieveBarChartUpdate(data);
|
await updateAchieveCharts(data);
|
||||||
await achievePieChartUpdate(data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 【1】进度统计柱状图
|
// 统一更新进度统计图表(只调用一次接口)
|
||||||
const progressBarChartNodata = ref(false);
|
const updateProgressCharts = async (data: any) => {
|
||||||
const progressBarOption = ref<any>();
|
|
||||||
const getCommonOptionFun = async (data: any) => {
|
|
||||||
let xData: any = [];
|
|
||||||
let seriesData: any = [];
|
|
||||||
let legendData: any = [];
|
|
||||||
const res: any = await getTaskCompleteStatisticsByDisciplineApi({
|
const res: any = await getTaskCompleteStatisticsByDisciplineApi({
|
||||||
tag1: data.tag1,
|
tag1: data.tag1,
|
||||||
tag5: data.workspace,
|
tag5: data.workspace,
|
||||||
@@ -151,16 +144,17 @@ const getCommonOptionFun = async (data: any) => {
|
|||||||
createTimeArr: data.createTimeArr,
|
createTimeArr: data.createTimeArr,
|
||||||
finishTimeArr: data.finishTimeArr,
|
finishTimeArr: data.finishTimeArr,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res && res.code === 200) {
|
if (res && res.code === 200) {
|
||||||
progressBarChartNodata.value = res.data.allExeStatus.length === 0;
|
// 更新柱状图
|
||||||
xData = res.data.result.map((item: any) => {
|
const xData = res.data.result.map((item: any) => {
|
||||||
return item.name;
|
return item.name;
|
||||||
});
|
});
|
||||||
legendData = Object.keys(TASK_ACHIEVE_STATUS.value.O).map((item: any) => {
|
const legendData = Object.keys(TASK_ACHIEVE_STATUS.value.O).map((item: any) => {
|
||||||
return TASK_ACHIEVE_STATUS.value.O[item];
|
return TASK_ACHIEVE_STATUS.value.O[item];
|
||||||
});
|
});
|
||||||
const names = Object.keys(TASK_ACHIEVE_STATUS.value.O);
|
const names = Object.keys(TASK_ACHIEVE_STATUS.value.O);
|
||||||
seriesData = names.map((str) => ({
|
const seriesData = names.map((str) => ({
|
||||||
name: TASK_ACHIEVE_STATUS.value.O[str],
|
name: TASK_ACHIEVE_STATUS.value.O[str],
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
emphasis: {
|
emphasis: {
|
||||||
@@ -168,81 +162,54 @@ const getCommonOptionFun = async (data: any) => {
|
|||||||
},
|
},
|
||||||
data: res.data.result.map((item: any) => item?.statusCount[str] || 0),
|
data: res.data.result.map((item: any) => item?.statusCount[str] || 0),
|
||||||
}));
|
}));
|
||||||
}
|
|
||||||
return { xData, seriesData, legendData };
|
|
||||||
};
|
|
||||||
const progressBarChartUpdate = async (data: any) => {
|
|
||||||
const { xData, seriesData, legendData } = await getCommonOptionFun(data);
|
|
||||||
const option = {
|
|
||||||
color: statusColorList,
|
|
||||||
legend: { data: legendData },
|
|
||||||
grid: { bottom: '50' },
|
|
||||||
xAxis: { type: 'category', data: xData || [] },
|
|
||||||
yAxis: { type: 'value', minInterval: 1 },
|
|
||||||
dataZoom: xData.length > 4,
|
|
||||||
series: seriesData || [],
|
|
||||||
};
|
|
||||||
progressBarOption.value = option;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 【2】进度统计饼图
|
const barOption = {
|
||||||
const progressPieChartNodata = ref(false);
|
color: statusColorList,
|
||||||
const progressPieOption = ref<any>();
|
legend: { data: legendData },
|
||||||
const progressPieChartUpdate = async (data: any) => {
|
grid: { bottom: '50' },
|
||||||
const seriesData: { name: any; value: any }[] = [];
|
xAxis: { type: 'category', data: xData || [] },
|
||||||
const res: any = await getTaskCompleteStatisticsByDisciplineApi({
|
yAxis: { type: 'value', minInterval: 1 },
|
||||||
tag1: data.tag1,
|
dataZoom: xData.length > 4,
|
||||||
tag5: data.workspace,
|
series: seriesData || [],
|
||||||
discipline: data.discipline,
|
};
|
||||||
createTimeArr: data.createTimeArr,
|
progressBarOption.value = barOption;
|
||||||
finishTimeArr: data.finishTimeArr,
|
progressBarChartNodata.value = res.data.allExeStatus.length === 0;
|
||||||
});
|
|
||||||
if (res.code === 200) {
|
// 更新饼图
|
||||||
progressPieChartNodata.value = res.data.allExeStatus.length === 0;
|
const pieSeriesData: { name: any; value: any }[] = [];
|
||||||
// 把res.data.allAchieveStatus数组转换为对象的key,value默认是0
|
|
||||||
const achieveStatusObj: any = {};
|
const achieveStatusObj: any = {};
|
||||||
Object.keys(TASK_ACHIEVE_STATUS.value.O).forEach((item: any) => {
|
Object.keys(TASK_ACHIEVE_STATUS.value.O).forEach((item: any) => {
|
||||||
achieveStatusObj[item] = 0;
|
achieveStatusObj[item] = 0;
|
||||||
});
|
});
|
||||||
// 遍历res.data.result数组,把每个对象的statusCount属性合并到achieveStatusObj中
|
|
||||||
res.data.result?.forEach((item: any) => {
|
res.data.result?.forEach((item: any) => {
|
||||||
for (const key in item.statusCount) {
|
for (const key in item.statusCount) {
|
||||||
achieveStatusObj[key] += item.statusCount[key];
|
achieveStatusObj[key] += item.statusCount[key];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 遍历achieveStatusObj,把每个对象的key转换为中文
|
|
||||||
for (const key in achieveStatusObj) {
|
for (const key in achieveStatusObj) {
|
||||||
seriesData.push({
|
pieSeriesData.push({
|
||||||
name: TASK_ACHIEVE_STATUS.value.O[key],
|
name: TASK_ACHIEVE_STATUS.value.O[key],
|
||||||
value: achieveStatusObj[key],
|
value: achieveStatusObj[key],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const option = getPieOptions(statusColorList, seriesData);
|
const pieOption = getPieOptions(statusColorList, pieSeriesData);
|
||||||
progressPieOption.value = option;
|
progressPieOption.value = pieOption;
|
||||||
|
progressPieChartNodata.value = res.data.allExeStatus.length === 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 完成情况颜色列表:未分析、不合格、合格
|
// 统一更新达成统计图表(只调用一次接口)
|
||||||
const completionStatusColorList = [
|
const updateAchieveCharts = async (data: any) => {
|
||||||
'rgb(200, 201, 204)',
|
|
||||||
getThemeColor('--el-color-danger'),
|
|
||||||
getThemeColor('--el-color-success'),
|
|
||||||
];
|
|
||||||
// 【3】任务达成统计柱状图
|
|
||||||
const achieveBarOption = ref<any>();
|
|
||||||
const taskCalculateStatusLegendData = TASK_CALCULATE_STATUS_OPTIONS.map((item) => ({
|
|
||||||
name: item.label,
|
|
||||||
}));
|
|
||||||
const achieveBarChartUpdate = async (data: any) => {
|
|
||||||
const res: any = await getTaskAchieveStatisticsByDisciplineApi({
|
const res: any = await getTaskAchieveStatisticsByDisciplineApi({
|
||||||
// resultTagType: 'tag6',
|
|
||||||
tag1: data.tag1,
|
tag1: data.tag1,
|
||||||
tag5: data.workspace,
|
tag5: data.workspace,
|
||||||
discipline: data.discipline,
|
discipline: data.discipline,
|
||||||
createTimeArr: data.createTimeArr,
|
createTimeArr: data.createTimeArr,
|
||||||
finishTimeArr: data.finishTimeArr,
|
finishTimeArr: data.finishTimeArr,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res && res.code === 200) {
|
if (res && res.code === 200) {
|
||||||
|
// 更新柱状图
|
||||||
const xData = res.data.result.map((item: any) => {
|
const xData = res.data.result.map((item: any) => {
|
||||||
return item.name;
|
return item.name;
|
||||||
});
|
});
|
||||||
@@ -254,7 +221,7 @@ const achieveBarChartUpdate = async (data: any) => {
|
|||||||
},
|
},
|
||||||
data: res.data.result.map((resultItem: any) => resultItem?.statusCount[item.value] || 0),
|
data: res.data.result.map((resultItem: any) => resultItem?.statusCount[item.value] || 0),
|
||||||
}));
|
}));
|
||||||
const option = {
|
const barOption = {
|
||||||
color: completionStatusColorList,
|
color: completionStatusColorList,
|
||||||
legend: { data: taskCalculateStatusLegendData },
|
legend: { data: taskCalculateStatusLegendData },
|
||||||
grid: { bottom: xData.length > 4 ? '50' : '10' },
|
grid: { bottom: xData.length > 4 ? '50' : '10' },
|
||||||
@@ -263,46 +230,52 @@ const achieveBarChartUpdate = async (data: any) => {
|
|||||||
dataZoom: xData.length > 4,
|
dataZoom: xData.length > 4,
|
||||||
series: seriesData,
|
series: seriesData,
|
||||||
};
|
};
|
||||||
achieveBarOption.value = { ...option };
|
achieveBarOption.value = { ...barOption };
|
||||||
}
|
|
||||||
};
|
// 更新饼图
|
||||||
// 【4】任务达成统计饼图
|
const pieSeriesData: { name: any; value: any }[] = [];
|
||||||
const achievePieChartNodata = ref(false);
|
|
||||||
const achievePieOption = ref<any>();
|
|
||||||
const achievePieChartUpdate = async (data: any) => {
|
|
||||||
const seriesData: { name: any; value: any }[] = [];
|
|
||||||
const res: any = await getTaskAchieveStatisticsByDisciplineApi({
|
|
||||||
// resultTagType: 'tag6',
|
|
||||||
tag1: data.tag1,
|
|
||||||
tag5: data.workspace,
|
|
||||||
discipline: data.discipline,
|
|
||||||
createTimeArr: data.createTimeArr,
|
|
||||||
finishTimeArr: data.finishTimeArr,
|
|
||||||
});
|
|
||||||
if (res.code === 200) {
|
|
||||||
achievePieChartNodata.value = res.data.allExeStatus.length === 0;
|
|
||||||
const achieveStatusObj: any = {};
|
const achieveStatusObj: any = {};
|
||||||
Object.keys(RESULT_ACHIEVE_STATUS.value.O).forEach((item: any) => {
|
Object.keys(RESULT_ACHIEVE_STATUS.value.O).forEach((item: any) => {
|
||||||
achieveStatusObj[item] = 0;
|
achieveStatusObj[item] = 0;
|
||||||
});
|
});
|
||||||
// 遍历res.data.result数组,把每个对象的statusCount属性合并到achieveStatusObj中
|
|
||||||
res.data.result?.forEach((item: any) => {
|
res.data.result?.forEach((item: any) => {
|
||||||
for (const key in item.statusCount) {
|
for (const key in item.statusCount) {
|
||||||
achieveStatusObj[key] += item.statusCount[key];
|
achieveStatusObj[key] += item.statusCount[key];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 遍历achieveStatusObj,把每个对象的key转换为中文
|
|
||||||
for (const key in achieveStatusObj) {
|
for (const key in achieveStatusObj) {
|
||||||
seriesData.push({
|
pieSeriesData.push({
|
||||||
name: RESULT_ACHIEVE_STATUS.value.O[key],
|
name: RESULT_ACHIEVE_STATUS.value.O[key],
|
||||||
value: achieveStatusObj[key],
|
value: achieveStatusObj[key],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const option = getPieOptions(completionStatusColorList, seriesData);
|
const pieOption = getPieOptions(completionStatusColorList, pieSeriesData);
|
||||||
achievePieOption.value = option;
|
achievePieOption.value = pieOption;
|
||||||
|
achievePieChartNodata.value = res.data.allExeStatus.length === 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 进度统计图表状态
|
||||||
|
const progressBarChartNodata = ref(false);
|
||||||
|
const progressBarOption = ref<any>();
|
||||||
|
const progressPieChartNodata = ref(false);
|
||||||
|
const progressPieOption = ref<any>();
|
||||||
|
|
||||||
|
// 完成情况颜色列表:未分析、不合格、合格
|
||||||
|
const completionStatusColorList = [
|
||||||
|
'rgb(200, 201, 204)',
|
||||||
|
getThemeColor('--el-color-danger'),
|
||||||
|
getThemeColor('--el-color-success'),
|
||||||
|
];
|
||||||
|
|
||||||
|
// 达成统计图表状态
|
||||||
|
const achieveBarOption = ref<any>();
|
||||||
|
const taskCalculateStatusLegendData = TASK_CALCULATE_STATUS_OPTIONS.map((item) => ({
|
||||||
|
name: item.label,
|
||||||
|
}));
|
||||||
|
const achievePieChartNodata = ref(false);
|
||||||
|
const achievePieOption = ref<any>();
|
||||||
|
|
||||||
// 饼图配置 statusColorList 颜色列表 seriesData 数据 [{ name: '分类1', value: 10 },{ name: '分类2', value: 20 }]
|
// 饼图配置 statusColorList 颜色列表 seriesData 数据 [{ name: '分类1', value: 10 },{ name: '分类2', value: 20 }]
|
||||||
const getPieOptions = (statusColorList: any, seriesData: any) => {
|
const getPieOptions = (statusColorList: any, seriesData: any) => {
|
||||||
const option = {
|
const option = {
|
||||||
|
|||||||
Reference in New Issue
Block a user