调整成绩分析
This commit is contained in:
parent
63eca2a0ea
commit
67ab505da5
@ -37,26 +37,13 @@
|
|||||||
<CjBjTjGl :tjgl-data="tjglData" />
|
<CjBjTjGl :tjgl-data="tjglData" />
|
||||||
|
|
||||||
<!-- 6. 本班与年级平均分对比分析图表 -->
|
<!-- 6. 本班与年级平均分对比分析图表 -->
|
||||||
<CjBjNjPjf
|
<CjBjNjPjf v-model:selected-km-id="xzkmId" :bj-pj-list="bjPjList" />
|
||||||
:km-lb="
|
|
||||||
ksccKmLb.map((km) => ({
|
|
||||||
id: km.id,
|
|
||||||
name: km.kmmc,
|
|
||||||
kmmc: km.kmmc,
|
|
||||||
}))
|
|
||||||
"
|
|
||||||
v-model:selected-km-id="xzkmId"
|
|
||||||
:bj-pj-list="bjPjList"
|
|
||||||
:bj-pjf="tjglData.bjpjf"
|
|
||||||
:nj-pjf="tjglData.njpjzf"
|
|
||||||
@change="onKmChange"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 7. 总分分数段图表 -->
|
<!-- 7. 总分分数段图表 -->
|
||||||
<CjZfFs :fs-duan-lb="fsDuanLb" />
|
<CjZfFs :dj-rs-list="djRsList" />
|
||||||
|
|
||||||
<!-- 8. 总分等级段图表 -->
|
<!-- 8. 总分等级段图表 -->
|
||||||
<CjZfDj :dj-duan-lb="djDuanLb" />
|
<CjZfDj :dj-rs-list="djRsList" />
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -116,22 +103,15 @@ interface BjPjInfo {
|
|||||||
njmc: string;
|
njmc: string;
|
||||||
fs: number;
|
fs: number;
|
||||||
}
|
}
|
||||||
|
interface DjRsInfo {
|
||||||
|
dj: string;
|
||||||
|
rs: number;
|
||||||
|
zgf: string;
|
||||||
|
zdf: string;
|
||||||
|
}
|
||||||
|
|
||||||
// --- Static Mock Data ---
|
// --- Static Mock Data ---
|
||||||
const staticFsDuanLb: FsDuan[] = [
|
// 这些静态数据现在不再需要,因为组件直接使用 djRsList
|
||||||
{ name: "240-269", value: 5, color: "#1890ff" },
|
|
||||||
{ name: "210-239", value: 12, color: "#2fc25b" },
|
|
||||||
{ name: "180-210", value: 18, color: "#facc14" },
|
|
||||||
{ name: "180以下", value: 10, color: "#f04864" },
|
|
||||||
];
|
|
||||||
|
|
||||||
const staticDjDuanLb: DjDuan[] = [
|
|
||||||
{ name: "A", value: 5, color: "#1890ff" },
|
|
||||||
{ name: "B", value: 15, color: "#2fc25b" },
|
|
||||||
{ name: "C", value: 18, color: "#facc14" },
|
|
||||||
{ name: "D", value: 10, color: "#f04864" },
|
|
||||||
{ name: "E", value: 2, color: "#999999" },
|
|
||||||
];
|
|
||||||
|
|
||||||
// --- State ---
|
// --- State ---
|
||||||
const xzbjId = ref<string | number | null>(null);
|
const xzbjId = ref<string | number | null>(null);
|
||||||
@ -150,9 +130,8 @@ const tjglData = ref<TjglData>({
|
|||||||
jgl: 0,
|
jgl: 0,
|
||||||
jgrs: 0,
|
jgrs: 0,
|
||||||
});
|
});
|
||||||
const fsDuanLb = ref<FsDuan[]>([...staticFsDuanLb]);
|
|
||||||
const djDuanLb = ref<DjDuan[]>([...staticDjDuanLb]);
|
|
||||||
const bjPjList = ref<BjPjInfo[]>([]);
|
const bjPjList = ref<BjPjInfo[]>([]);
|
||||||
|
const djRsList = ref<DjRsInfo[]>([]);
|
||||||
|
|
||||||
// --- API Functions ---
|
// --- API Functions ---
|
||||||
const getKsccKmLb = async (ksccId: string | number) => {
|
const getKsccKmLb = async (ksccId: string | number) => {
|
||||||
@ -197,6 +176,7 @@ const getBjKscjKmData = async (
|
|||||||
score: cj.ksfs || 0,
|
score: cj.ksfs || 0,
|
||||||
bjpm: cj.bjpm || 0, // 使用后端返回的班级排名
|
bjpm: cj.bjpm || 0, // 使用后端返回的班级排名
|
||||||
}));
|
}));
|
||||||
|
console.log("学生成绩列表:", xsCjLb.value);
|
||||||
|
|
||||||
// 处理统计数据
|
// 处理统计数据
|
||||||
tjglData.value.bjrs = res.result.bjRs || 0;
|
tjglData.value.bjrs = res.result.bjRs || 0;
|
||||||
@ -211,7 +191,12 @@ const getBjKscjKmData = async (
|
|||||||
|
|
||||||
// 处理班级平均分列表数据,传递给CjBjNjPjf组件
|
// 处理班级平均分列表数据,传递给CjBjNjPjf组件
|
||||||
bjPjList.value = res.result.bjPjList || [];
|
bjPjList.value = res.result.bjPjList || [];
|
||||||
|
|
||||||
|
// 处理等级段数据列表,传递给CjZfFs和CjZfDj组件
|
||||||
|
djRsList.value = res.result.djRsList || [];
|
||||||
|
|
||||||
console.log("获取班级科目成绩数据成功:", res.result);
|
console.log("获取班级科目成绩数据成功:", res.result);
|
||||||
|
console.log("等级人数列表:", djRsList.value);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("获取班级科目成绩数据失败:", error);
|
console.error("获取班级科目成绩数据失败:", error);
|
||||||
@ -316,4 +301,24 @@ onMounted(async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.debug-info {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
padding: 20rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
|
||||||
|
.debug-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.debug-item {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 5rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -13,18 +13,26 @@
|
|||||||
<view class="th">班级排名</view>
|
<view class="th">班级排名</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="bg-body">
|
<view class="bg-body">
|
||||||
<view class="bg-row" v-for="xs in xsCjLb" :key="xs.id">
|
<view class="bg-row" v-for="xs in displayList" :key="xs.id">
|
||||||
<view class="td">{{ xs.name }}</view>
|
<view class="td">{{ xs.name }}</view>
|
||||||
<view class="td">{{ xs.score }}</view>
|
<view class="td">{{ xs.score }}</view>
|
||||||
<view class="td">{{ xs.bjpm }}</view>
|
<view class="td">{{ xs.bjpm }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view v-if="!xsCjLb.length" class="bg-empty"> 暂无数据 </view>
|
<view v-if="!xsCjLb.length" class="bg-empty"> 暂无数据 </view>
|
||||||
</view>
|
</view>
|
||||||
|
<view
|
||||||
|
v-if="xsCjLb.length > 5"
|
||||||
|
class="expand-btn-wrap"
|
||||||
|
@click="toggleExpand"
|
||||||
|
>
|
||||||
|
{{ expanded ? "收拢" : "展开全部" }}
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</uni-section>
|
</uni-section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { computed, ref } from "vue";
|
||||||
// --- Interfaces ---
|
// --- Interfaces ---
|
||||||
interface XsCj {
|
interface XsCj {
|
||||||
id: string | number;
|
id: string | number;
|
||||||
@ -47,6 +55,22 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
{ id: "st-5", name: "孙七", score: 85, bjpm: 8 },
|
{ id: "st-5", name: "孙七", score: 85, bjpm: 8 },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 展开/收拢状态
|
||||||
|
const expanded = ref(false);
|
||||||
|
|
||||||
|
// 计算显示的学生列表
|
||||||
|
const displayList = computed(() => {
|
||||||
|
if (expanded.value) {
|
||||||
|
return props.xsCjLb;
|
||||||
|
}
|
||||||
|
return props.xsCjLb.slice(0, 5);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 切换展开/收拢
|
||||||
|
function toggleExpand() {
|
||||||
|
expanded.value = !expanded.value;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@ -100,5 +124,15 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
padding: 40rpx 0;
|
padding: 40rpx 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.expand-btn-wrap {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 16rpx 10rpx;
|
||||||
|
text-align: center;
|
||||||
|
background: #fff;
|
||||||
|
color: #1890ff;
|
||||||
|
border-top: 1rpx solid #f0f0f0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -12,8 +12,9 @@
|
|||||||
id="GradeAnalysisAreaChart"
|
id="GradeAnalysisAreaChart"
|
||||||
class="charts"
|
class="charts"
|
||||||
/>
|
/>
|
||||||
<view v-if="isLoading" class="tb-placeholder">
|
<view v-if="isLoading" class="tb-placeholder"> 图表加载中... </view>
|
||||||
图表加载中或无数据...
|
<view v-else-if="!hasValidData" class="tb-placeholder">
|
||||||
|
暂无等级段数据
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</uni-section>
|
</uni-section>
|
||||||
@ -21,7 +22,7 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import uCharts from "@/components/charts/u-charts.js";
|
import uCharts from "@/components/charts/u-charts.js";
|
||||||
import { nextTick, onMounted, ref } from "vue";
|
import { computed, nextTick, onMounted, ref, watch } from "vue";
|
||||||
import { areaOption } from "./cj.data";
|
import { areaOption } from "./cj.data";
|
||||||
|
|
||||||
// --- Interfaces ---
|
// --- Interfaces ---
|
||||||
@ -31,26 +32,72 @@ interface DjDuan {
|
|||||||
color: string;
|
color: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface DjRsInfo {
|
||||||
|
dj: string;
|
||||||
|
rs: number;
|
||||||
|
zgf: string;
|
||||||
|
zdf: string;
|
||||||
|
}
|
||||||
|
|
||||||
// --- Props ---
|
// --- Props ---
|
||||||
interface Props {
|
interface Props {
|
||||||
djDuanLb?: DjDuan[];
|
djRsList?: DjRsInfo[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
djDuanLb: () => [
|
djRsList: () => [],
|
||||||
{ name: "A", value: 5, color: "#1890ff" },
|
|
||||||
{ name: "B", value: 15, color: "#2fc25b" },
|
|
||||||
{ name: "C", value: 18, color: "#facc14" },
|
|
||||||
{ name: "D", value: 10, color: "#f04864" },
|
|
||||||
{ name: "E", value: 2, color: "#999999" },
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- State ---
|
// --- State ---
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
|
|
||||||
|
// --- Computed ---
|
||||||
|
const hasValidData = computed(() => {
|
||||||
|
return (
|
||||||
|
props.djRsList &&
|
||||||
|
props.djRsList.length > 0 &&
|
||||||
|
props.djRsList.some((item) => item.rs > 0)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const processedData = computed(() => {
|
||||||
|
if (!props.djRsList || props.djRsList.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义等级颜色映射
|
||||||
|
const djColorMap: { [key: string]: string } = {
|
||||||
|
A: "#1890ff",
|
||||||
|
B: "#2fc25b",
|
||||||
|
C: "#facc14",
|
||||||
|
D: "#f04864",
|
||||||
|
E: "#999999",
|
||||||
|
};
|
||||||
|
|
||||||
|
// 过滤掉人数为0的数据,并按等级排序
|
||||||
|
return props.djRsList
|
||||||
|
.filter((item) => item.rs > 0)
|
||||||
|
.map((item) => ({
|
||||||
|
name: item.dj, // 使用 dj 作为等级名称
|
||||||
|
value: item.rs,
|
||||||
|
color: djColorMap[item.dj] || "#666666", // 根据等级分配颜色
|
||||||
|
}))
|
||||||
|
.sort((a, b) => {
|
||||||
|
// 按等级排序(A > B > C > D > E)
|
||||||
|
const levelOrder = { A: 5, B: 4, C: 3, D: 2, E: 1 };
|
||||||
|
const aLevel = levelOrder[a.name as keyof typeof levelOrder] || 0;
|
||||||
|
const bLevel = levelOrder[b.name as keyof typeof levelOrder] || 0;
|
||||||
|
return bLevel - aLevel; // 降序排列
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// --- 图表绘制逻辑 ---
|
// --- 图表绘制逻辑 ---
|
||||||
const drawAreaChart = () => {
|
const drawAreaChart = () => {
|
||||||
|
if (!hasValidData.value) {
|
||||||
|
console.log("没有有效的等级段数据");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -73,11 +120,11 @@ const drawAreaChart = () => {
|
|||||||
const ctx = uni.createCanvasContext("GradeAnalysisAreaChart");
|
const ctx = uni.createCanvasContext("GradeAnalysisAreaChart");
|
||||||
|
|
||||||
const areaData = {
|
const areaData = {
|
||||||
categories: props.djDuanLb.map((item) => item.name),
|
categories: processedData.value.map((item) => item.name),
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: "人数",
|
name: "人数",
|
||||||
data: props.djDuanLb.map((item) => item.value),
|
data: processedData.value.map((item) => item.value),
|
||||||
color: "#1890ff",
|
color: "#1890ff",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -120,6 +167,7 @@ const drawAreaChart = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log("图表数据:", areaData);
|
console.log("图表数据:", areaData);
|
||||||
|
console.log("处理后的等级段数据:", processedData.value);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new uCharts(newOption);
|
new uCharts(newOption);
|
||||||
@ -141,9 +189,23 @@ const drawAreaChart = () => {
|
|||||||
}, 500);
|
}, 500);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --- Watchers ---
|
||||||
|
watch(
|
||||||
|
() => props.djRsList,
|
||||||
|
() => {
|
||||||
|
console.log("等级段数据变化:", props.djRsList);
|
||||||
|
if (hasValidData.value) {
|
||||||
|
drawAreaChart();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
// --- Lifecycle ---
|
// --- Lifecycle ---
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
drawAreaChart();
|
if (hasValidData.value) {
|
||||||
|
drawAreaChart();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -12,8 +12,9 @@
|
|||||||
id="GradeAnalysisDonutChart"
|
id="GradeAnalysisDonutChart"
|
||||||
class="charts"
|
class="charts"
|
||||||
/>
|
/>
|
||||||
<view v-if="isLoading" class="tb-placeholder">
|
<view v-if="isLoading" class="tb-placeholder"> 图表加载中... </view>
|
||||||
图表加载中或无数据...
|
<view v-else-if="!hasValidData" class="tb-placeholder">
|
||||||
|
暂无分数段数据
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</uni-section>
|
</uni-section>
|
||||||
@ -21,7 +22,7 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import uCharts from "@/components/charts/u-charts.js";
|
import uCharts from "@/components/charts/u-charts.js";
|
||||||
import { nextTick, onMounted, ref } from "vue";
|
import { computed, nextTick, onMounted, ref, watch } from "vue";
|
||||||
import { ringOption } from "./cj.data";
|
import { ringOption } from "./cj.data";
|
||||||
|
|
||||||
// --- Interfaces ---
|
// --- Interfaces ---
|
||||||
@ -31,25 +32,71 @@ interface FsDuan {
|
|||||||
color: string;
|
color: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface DjRsInfo {
|
||||||
|
dj: string;
|
||||||
|
rs: number;
|
||||||
|
zgf: string;
|
||||||
|
zdf: string;
|
||||||
|
}
|
||||||
|
|
||||||
// --- Props ---
|
// --- Props ---
|
||||||
interface Props {
|
interface Props {
|
||||||
fsDuanLb?: FsDuan[];
|
djRsList?: DjRsInfo[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
fsDuanLb: () => [
|
djRsList: () => [],
|
||||||
{ name: "240-269", value: 5, color: "#1890ff" },
|
|
||||||
{ name: "210-239", value: 12, color: "#2fc25b" },
|
|
||||||
{ name: "180-210", value: 18, color: "#facc14" },
|
|
||||||
{ name: "180以下", value: 10, color: "#f04864" },
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- State ---
|
// --- State ---
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
|
|
||||||
|
// --- Computed ---
|
||||||
|
const hasValidData = computed(() => {
|
||||||
|
return (
|
||||||
|
props.djRsList &&
|
||||||
|
props.djRsList.length > 0 &&
|
||||||
|
props.djRsList.some((item) => item.rs > 0)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const processedData = computed(() => {
|
||||||
|
if (!props.djRsList || props.djRsList.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义等级颜色映射
|
||||||
|
const djColorMap: { [key: string]: string } = {
|
||||||
|
A: "#1890ff",
|
||||||
|
B: "#2fc25b",
|
||||||
|
C: "#facc14",
|
||||||
|
D: "#f04864",
|
||||||
|
E: "#999999",
|
||||||
|
};
|
||||||
|
|
||||||
|
// 过滤掉人数为0的数据,并按分数段排序
|
||||||
|
return props.djRsList
|
||||||
|
.filter((item) => item.rs > 0)
|
||||||
|
.map((item) => ({
|
||||||
|
name: `${item.zdf}-${item.zgf}`, // 使用 zdf-zgf 作为分数段名称
|
||||||
|
value: item.rs,
|
||||||
|
color: djColorMap[item.dj] || "#666666", // 根据等级分配颜色
|
||||||
|
}))
|
||||||
|
.sort((a, b) => {
|
||||||
|
// 尝试按分数段排序(假设格式为 "数字-数字")
|
||||||
|
const aNum = parseFloat(a.name.split("-")[0] || "0");
|
||||||
|
const bNum = parseFloat(b.name.split("-")[0] || "0");
|
||||||
|
return bNum - aNum; // 降序排列
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// --- 图表绘制逻辑 ---
|
// --- 图表绘制逻辑 ---
|
||||||
const drawDonutChart = () => {
|
const drawDonutChart = () => {
|
||||||
|
if (!hasValidData.value) {
|
||||||
|
console.log("没有有效的分数段数据");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -75,7 +122,7 @@ const drawDonutChart = () => {
|
|||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: "总分分数段",
|
name: "总分分数段",
|
||||||
data: props.fsDuanLb,
|
data: processedData.value,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@ -110,6 +157,7 @@ const drawDonutChart = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log("图表数据:", donutData);
|
console.log("图表数据:", donutData);
|
||||||
|
console.log("处理后的分数段数据:", processedData.value);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new uCharts(newOption);
|
new uCharts(newOption);
|
||||||
@ -131,9 +179,23 @@ const drawDonutChart = () => {
|
|||||||
}, 500);
|
}, 500);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --- Watchers ---
|
||||||
|
watch(
|
||||||
|
() => props.djRsList,
|
||||||
|
() => {
|
||||||
|
console.log("分数段数据变化:", props.djRsList);
|
||||||
|
if (hasValidData.value) {
|
||||||
|
drawDonutChart();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
// --- Lifecycle ---
|
// --- Lifecycle ---
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
drawDonutChart();
|
if (hasValidData.value) {
|
||||||
|
drawDonutChart();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user