mirror of
https://github.com/ZeroCatDev/Classworks.git
synced 2025-12-08 13:49:37 +00:00
803 lines
20 KiB
Vue
803 lines
20 KiB
Vue
<template>
|
||
<v-dialog
|
||
v-model="dialog"
|
||
fullscreen-breakpoint="sm"
|
||
max-width="600"
|
||
persistent
|
||
>
|
||
<v-card
|
||
border
|
||
class="random-picker-card"
|
||
rounded="xl"
|
||
>
|
||
<v-card-title class="text-h5 d-flex align-center">
|
||
<v-icon
|
||
class="mr-2"
|
||
icon="mdi-account-question"
|
||
/>
|
||
随机点名
|
||
<v-spacer />
|
||
<v-btn
|
||
icon="mdi-close"
|
||
variant="text"
|
||
@click="dialog = false"
|
||
/>
|
||
</v-card-title>
|
||
|
||
<v-card-text
|
||
v-if="!isPickingStarted"
|
||
class="text-center py-6"
|
||
>
|
||
<div class="text-h6 mb-4">
|
||
请选择抽取人数
|
||
</div>
|
||
|
||
<div class="d-flex justify-center align-center counter-container">
|
||
<v-btn
|
||
:disabled="count <= 1"
|
||
class="counter-btn"
|
||
color="primary"
|
||
icon="mdi-minus"
|
||
size="x-large"
|
||
variant="tonal"
|
||
@click="decrementCount"
|
||
/>
|
||
|
||
<div class="count-display mx-8">
|
||
<span class="text-h2 font-weight-bold">{{ count }}</span>
|
||
<span class="text-subtitle-1 ml-2">人</span>
|
||
</div>
|
||
|
||
<v-btn
|
||
:disabled="count >= maxAllowedCount"
|
||
class="counter-btn"
|
||
color="primary"
|
||
icon="mdi-plus"
|
||
size="x-large"
|
||
variant="tonal"
|
||
@click="incrementCount"
|
||
/>
|
||
</div>
|
||
|
||
<!-- 添加模式切换 -->
|
||
<div class="mode-switch-container mt-6">
|
||
<v-btn-toggle
|
||
v-model="pickerMode"
|
||
class="mode-toggle"
|
||
color="primary"
|
||
mandatory
|
||
rounded="pill"
|
||
>
|
||
<v-btn
|
||
prepend-icon="mdi-account"
|
||
value="name"
|
||
>
|
||
姓名模式
|
||
</v-btn>
|
||
<v-btn
|
||
prepend-icon="mdi-numeric"
|
||
value="number"
|
||
>
|
||
学号模式
|
||
</v-btn>
|
||
</v-btn-toggle>
|
||
</div>
|
||
|
||
<!-- 学号范围设置 -->
|
||
<div
|
||
v-if="pickerMode === 'number'"
|
||
class="number-range-container mt-4"
|
||
>
|
||
<div class="text-subtitle-1 mb-2">
|
||
学号范围设置
|
||
</div>
|
||
<div class="d-flex justify-center align-center gap-4">
|
||
<v-text-field
|
||
v-model.number="minNumber"
|
||
class="number-input"
|
||
density="compact"
|
||
hide-details
|
||
label="最小值"
|
||
max="100"
|
||
min="1"
|
||
type="number"
|
||
/>
|
||
<span class="mx-2">至</span>
|
||
<v-text-field
|
||
v-model.number="maxNumber"
|
||
class="number-input"
|
||
density="compact"
|
||
hide-details
|
||
label="最大值"
|
||
max="100"
|
||
min="1"
|
||
type="number"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="mt-4">
|
||
<v-btn
|
||
:disabled="filteredStudents.length === 0"
|
||
class="start-btn"
|
||
color="primary"
|
||
prepend-icon="mdi-dice-multiple"
|
||
size="x-large"
|
||
@click="startPicking"
|
||
>
|
||
开始抽取
|
||
</v-btn>
|
||
</div>
|
||
|
||
<div
|
||
v-if="filteredStudents.length === 0"
|
||
class="mt-4 text-error"
|
||
>
|
||
<template v-if="pickerMode === 'name'">
|
||
没有可抽取的学生,请调整过滤选项
|
||
</template>
|
||
<template v-else>
|
||
请设置有效的学号范围
|
||
</template>
|
||
</div>
|
||
|
||
<div class="mt-4 text-caption">
|
||
当前可抽取学生: {{ filteredStudents.length }}人
|
||
<v-tooltip
|
||
v-if="pickerMode === 'name'"
|
||
location="bottom"
|
||
>
|
||
<template #activator="{ props }">
|
||
<v-icon
|
||
class="ml-1"
|
||
icon="mdi-information-outline"
|
||
size="small"
|
||
v-bind="props"
|
||
/>
|
||
</template>
|
||
<div class="pa-2">
|
||
<div v-if="tempFilters.excludeAbsent">
|
||
• 已排除请假学生 ({{ absentCount }}人)
|
||
</div>
|
||
<div v-if="tempFilters.excludeLate">
|
||
• 已排除迟到学生 ({{ lateCount }}人)
|
||
</div>
|
||
<div v-if="tempFilters.excludeExcluded">
|
||
• 已排除不参与学生 ({{ excludedCount }}人)
|
||
</div>
|
||
</div>
|
||
</v-tooltip>
|
||
|
||
<!-- 添加临时过滤选项 -->
|
||
<div
|
||
v-if="pickerMode === 'name'"
|
||
class="d-flex flex-wrap justify-center gap-2 mt-4"
|
||
>
|
||
<v-chip
|
||
:color="tempFilters.excludeLate ? 'warning' : 'default'"
|
||
:variant="tempFilters.excludeLate ? 'elevated' : 'text'"
|
||
class="filter-chip"
|
||
prepend-icon="mdi-clock-alert"
|
||
@click="tempFilters.excludeLate = !tempFilters.excludeLate"
|
||
>
|
||
{{ tempFilters.excludeLate ? "排除" : "包含" }}迟到学生
|
||
</v-chip>
|
||
<v-chip
|
||
:color="tempFilters.excludeAbsent ? 'error' : 'default'"
|
||
:variant="tempFilters.excludeAbsent ? 'elevated' : 'text'"
|
||
class="filter-chip"
|
||
prepend-icon="mdi-account-off"
|
||
@click="tempFilters.excludeAbsent = !tempFilters.excludeAbsent"
|
||
>
|
||
{{ tempFilters.excludeAbsent ? "排除" : "包含" }}请假学生
|
||
</v-chip>
|
||
|
||
<v-chip
|
||
:color="tempFilters.excludeExcluded ? 'grey' : 'default'"
|
||
:variant="tempFilters.excludeExcluded ? 'elevated' : 'text'"
|
||
class="filter-chip"
|
||
prepend-icon="mdi-account-cancel"
|
||
@click="tempFilters.excludeExcluded = !tempFilters.excludeExcluded"
|
||
>
|
||
{{ tempFilters.excludeExcluded ? "排除" : "包含" }}不参与学生
|
||
</v-chip>
|
||
</div>
|
||
</div>
|
||
</v-card-text>
|
||
|
||
<v-card-text
|
||
v-else
|
||
class="text-center py-6"
|
||
>
|
||
<div
|
||
v-if="isAnimating"
|
||
class="animation-container"
|
||
>
|
||
<div class="animation-wrapper">
|
||
<transition-group
|
||
class="shuffle-container"
|
||
name="shuffle"
|
||
tag="div"
|
||
>
|
||
<div
|
||
v-for="(student, index) in animationStudents"
|
||
:key="student.id"
|
||
:class="{ highlighted: highlightedIndices.includes(index) }"
|
||
class="student-item"
|
||
>
|
||
{{ student.name }}
|
||
</div>
|
||
</transition-group>
|
||
</div>
|
||
</div>
|
||
|
||
<div
|
||
v-else
|
||
class="result-container"
|
||
>
|
||
<div class="text-h6 mb-4">
|
||
抽取结果
|
||
</div>
|
||
<v-card
|
||
v-for="(student, index) in pickedStudents"
|
||
:key="index"
|
||
class="mb-2 result-card"
|
||
color="primary"
|
||
variant="outlined"
|
||
>
|
||
<v-card-text
|
||
class="text-h4 text-center py-4 d-flex align-center justify-center"
|
||
>
|
||
{{ student }}
|
||
<v-btn
|
||
:disabled="remainingStudents.length === 0"
|
||
:title="
|
||
remainingStudents.length === 0
|
||
? '没有更多可用学生'
|
||
: '重新抽取此学生'
|
||
"
|
||
class="ml-2 refresh-btn"
|
||
icon="mdi-refresh"
|
||
size="small"
|
||
variant="text"
|
||
@click="refreshSingleStudent(index)"
|
||
/>
|
||
</v-card-text>
|
||
</v-card>
|
||
|
||
<div class="mt-8 d-flex justify-center">
|
||
<v-btn
|
||
class="mx-2"
|
||
color="primary"
|
||
prepend-icon="mdi-refresh"
|
||
size="large"
|
||
@click="resetPicker"
|
||
>
|
||
重新抽取
|
||
</v-btn>
|
||
<v-btn
|
||
class="mx-2"
|
||
color="grey"
|
||
size="large"
|
||
variant="outlined"
|
||
@click="dialog = false"
|
||
>
|
||
关闭
|
||
</v-btn>
|
||
</div>
|
||
</div>
|
||
</v-card-text>
|
||
</v-card>
|
||
</v-dialog>
|
||
</template>
|
||
|
||
<script>
|
||
import {getSetting, setSetting} from "@/utils/settings";
|
||
|
||
export default {
|
||
name: "RandomPicker",
|
||
props: {
|
||
studentList: {
|
||
type: Array,
|
||
required: true,
|
||
},
|
||
attendance: {
|
||
type: Object,
|
||
required: true,
|
||
default: () => ({absent: [], late: [], exclude: []}),
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
dialog: false,
|
||
count: getSetting("randomPicker.defaultCount"),
|
||
isPickingStarted: false,
|
||
isAnimating: false,
|
||
pickedStudents: [],
|
||
animationStudents: [],
|
||
highlightedIndices: [],
|
||
animationTimer: null,
|
||
getSetting,
|
||
// 添加临时过滤选项
|
||
tempFilters: {
|
||
excludeAbsent: getSetting("randomPicker.excludeAbsent"),
|
||
excludeLate: getSetting("randomPicker.excludeLate"),
|
||
excludeExcluded: getSetting("randomPicker.excludeExcluded"),
|
||
},
|
||
pickerMode: getSetting("randomPicker.mode"),
|
||
minNumber: getSetting("randomPicker.minNumber"),
|
||
maxNumber: getSetting("randomPicker.maxNumber"),
|
||
};
|
||
},
|
||
computed: {
|
||
// 计算请假、迟到、不参与的学生数量
|
||
absentCount() {
|
||
return this.attendance.absent ? this.attendance.absent.length : 0;
|
||
},
|
||
lateCount() {
|
||
return this.attendance.late ? this.attendance.late.length : 0;
|
||
},
|
||
excludedCount() {
|
||
return this.attendance.exclude ? this.attendance.exclude.length : 0;
|
||
},
|
||
|
||
// 添加数字模式的学生列表
|
||
numberModeStudents() {
|
||
if (this.pickerMode !== "number") return [];
|
||
const students = [];
|
||
for (let i = this.minNumber; i <= this.maxNumber; i++) {
|
||
students.push(i.toString().padStart(2, "0") + "号");
|
||
}
|
||
return students;
|
||
},
|
||
|
||
// 修改 filteredStudents 计算属性
|
||
filteredStudents() {
|
||
if (this.pickerMode === "number") {
|
||
return this.numberModeStudents;
|
||
}
|
||
|
||
if (!this.studentList || !this.studentList.length) return [];
|
||
|
||
return this.studentList.filter((student) => {
|
||
if (
|
||
this.tempFilters.excludeAbsent &&
|
||
this.attendance.absent.includes(student)
|
||
) {
|
||
return false;
|
||
}
|
||
if (
|
||
this.tempFilters.excludeLate &&
|
||
this.attendance.late.includes(student)
|
||
) {
|
||
return false;
|
||
}
|
||
if (
|
||
this.tempFilters.excludeExcluded &&
|
||
this.attendance.exclude.includes(student)
|
||
) {
|
||
return false;
|
||
}
|
||
return true;
|
||
});
|
||
},
|
||
|
||
// 兼容性:保留原有的 availableStudents 计算属性,但使用新的过滤逻辑
|
||
availableStudents() {
|
||
return this.filteredStudents;
|
||
},
|
||
|
||
maxAllowedCount() {
|
||
return Math.min(10, this.filteredStudents.length);
|
||
},
|
||
|
||
// 计算剩余可用学生(排除已抽取的学生)
|
||
remainingStudents() {
|
||
return this.filteredStudents.filter(
|
||
(student) => !this.pickedStudents.includes(student)
|
||
);
|
||
},
|
||
},
|
||
watch: {
|
||
dialog(newVal) {
|
||
if (newVal) {
|
||
// 打开对话框时重置状态
|
||
this.count = getSetting("randomPicker.defaultCount");
|
||
this.isPickingStarted = false;
|
||
this.isAnimating = false;
|
||
this.pickedStudents = [];
|
||
|
||
// 重置临时过滤选项为设置中的值
|
||
this.tempFilters = {
|
||
excludeAbsent: getSetting("randomPicker.excludeAbsent"),
|
||
excludeLate: getSetting("randomPicker.excludeLate"),
|
||
excludeExcluded: getSetting("randomPicker.excludeExcluded"),
|
||
};
|
||
} else {
|
||
// 关闭对话框时清除计时器
|
||
if (this.animationTimer) {
|
||
clearTimeout(this.animationTimer);
|
||
this.animationTimer = null;
|
||
}
|
||
}
|
||
},
|
||
|
||
// 监听过滤选项变化,确保count不超过可用学生数
|
||
tempFilters: {
|
||
handler() {
|
||
if (this.count > this.maxAllowedCount) {
|
||
this.count = Math.max(1, this.maxAllowedCount);
|
||
}
|
||
},
|
||
deep: true,
|
||
},
|
||
|
||
// 添加模式切换监听
|
||
pickerMode: {
|
||
handler(newMode) {
|
||
setSetting("randomPicker.mode", newMode);
|
||
},
|
||
},
|
||
minNumber: {
|
||
handler(newValue) {
|
||
if (newValue > this.maxNumber) {
|
||
this.minNumber = this.maxNumber;
|
||
}
|
||
if (newValue < 1) {
|
||
this.minNumber = 1;
|
||
}
|
||
setSetting("randomPicker.minNumber", this.minNumber);
|
||
},
|
||
},
|
||
maxNumber: {
|
||
handler(newValue) {
|
||
if (newValue < this.minNumber) {
|
||
this.maxNumber = this.minNumber;
|
||
}
|
||
if (newValue > 100) {
|
||
this.maxNumber = 100;
|
||
}
|
||
setSetting("randomPicker.maxNumber", this.maxNumber);
|
||
},
|
||
},
|
||
},
|
||
methods: {
|
||
open() {
|
||
this.dialog = true;
|
||
},
|
||
incrementCount() {
|
||
if (this.count < this.maxAllowedCount) {
|
||
this.count++;
|
||
}
|
||
},
|
||
decrementCount() {
|
||
if (this.count > 1) {
|
||
this.count--;
|
||
}
|
||
},
|
||
startPicking() {
|
||
if (this.filteredStudents.length === 0) return;
|
||
|
||
this.isPickingStarted = true;
|
||
|
||
if (getSetting("randomPicker.animation")) {
|
||
this.startAnimation();
|
||
} else {
|
||
this.finishPicking();
|
||
}
|
||
},
|
||
startAnimation() {
|
||
this.isAnimating = true;
|
||
|
||
// 创建动画用的学生列表(添加ID以便于动画)
|
||
this.animationStudents = this.filteredStudents.map((name, index) => ({
|
||
id: `student-${index}`,
|
||
name,
|
||
}));
|
||
|
||
// 随机高亮显示
|
||
this.animateHighlight();
|
||
},
|
||
animateHighlight() {
|
||
const totalSteps = 5; // 动画总步数
|
||
let currentStep = 0;
|
||
const intervalTime = 50; // 初始间隔时间
|
||
|
||
const animate = () => {
|
||
// 清除之前的高亮
|
||
this.highlightedIndices = [];
|
||
|
||
// 随机选择要高亮的索引
|
||
const indices = [];
|
||
for (let i = 0; i < this.count; i++) {
|
||
let randomIndex;
|
||
do {
|
||
randomIndex = Math.floor(
|
||
Math.random() * this.animationStudents.length
|
||
);
|
||
} while (indices.includes(randomIndex));
|
||
indices.push(randomIndex);
|
||
}
|
||
|
||
this.highlightedIndices = indices;
|
||
|
||
currentStep++;
|
||
|
||
// 逐渐增加间隔时间,使动画变慢
|
||
const nextInterval = intervalTime + currentStep * 20;
|
||
|
||
if (currentStep < totalSteps) {
|
||
this.animationTimer = setTimeout(animate, nextInterval);
|
||
} else {
|
||
// 动画结束,显示最终结果
|
||
setTimeout(() => {
|
||
this.finishPicking();
|
||
}, 500);
|
||
}
|
||
};
|
||
|
||
// 开始动画
|
||
animate();
|
||
},
|
||
finishPicking() {
|
||
this.isAnimating = false;
|
||
|
||
// 随机选择学生
|
||
const shuffled = [...this.filteredStudents].sort(
|
||
() => 0.5 - Math.random()
|
||
);
|
||
this.pickedStudents = shuffled.slice(0, this.count);
|
||
},
|
||
resetPicker() {
|
||
this.isPickingStarted = false;
|
||
this.isAnimating = false;
|
||
this.pickedStudents = [];
|
||
if (this.animationTimer) {
|
||
clearTimeout(this.animationTimer);
|
||
this.animationTimer = null;
|
||
}
|
||
},
|
||
// 刷新单个学生
|
||
refreshSingleStudent(index) {
|
||
if (this.remainingStudents.length === 0) return;
|
||
|
||
// 从剩余学生中随机选择一个
|
||
const randomIndex = Math.floor(
|
||
Math.random() * this.remainingStudents.length
|
||
);
|
||
const newStudent = this.remainingStudents[randomIndex];
|
||
|
||
// 替换指定位置的学生
|
||
this.pickedStudents[index] = newStudent;
|
||
|
||
// 添加动画效果
|
||
const resultCards = document.querySelectorAll(".result-card");
|
||
if (resultCards[index]) {
|
||
resultCards[index].classList.add("refresh-animation");
|
||
setTimeout(() => {
|
||
resultCards[index].classList.remove("refresh-animation");
|
||
}, 500);
|
||
}
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.random-picker-card {
|
||
overflow: hidden;
|
||
}
|
||
|
||
.counter-container {
|
||
margin: 2rem 0;
|
||
}
|
||
|
||
.counter-btn {
|
||
width: 64px;
|
||
height: 64px;
|
||
border-radius: 50%;
|
||
}
|
||
|
||
.count-display {
|
||
min-width: 100px;
|
||
text-align: center;
|
||
}
|
||
|
||
.start-btn {
|
||
min-width: 200px;
|
||
height: 64px;
|
||
border-radius: 32px;
|
||
font-size: 1.2rem;
|
||
}
|
||
|
||
// 过滤选项卡片样式
|
||
.filter-options-card {
|
||
max-width: 450px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.filter-chip {
|
||
cursor: pointer;
|
||
transition: all 0.2s ease;
|
||
|
||
&:active {
|
||
transform: scale(0.95);
|
||
}
|
||
}
|
||
|
||
// 学生列表提示框样式
|
||
.student-list-tooltip {
|
||
max-height: 200px;
|
||
overflow-y: auto;
|
||
margin-top: 5px;
|
||
font-size: 0.9em;
|
||
}
|
||
|
||
.animation-container {
|
||
min-height: 300px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
|
||
.animation-wrapper {
|
||
width: 100%;
|
||
max-width: 400px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.shuffle-container {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
gap: 10px;
|
||
}
|
||
|
||
.student-item {
|
||
padding: 10px 15px;
|
||
background-color: rgba(var(--v-theme-surface-variant), 0.7);
|
||
border-radius: 8px;
|
||
transition: all 0.3s ease;
|
||
font-size: 1.2rem;
|
||
|
||
&.highlighted {
|
||
background-color: rgb(var(--v-theme-primary));
|
||
color: rgb(var(--v-theme-on-primary));
|
||
transform: scale(1.1);
|
||
font-weight: bold;
|
||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||
}
|
||
}
|
||
|
||
.result-container {
|
||
min-height: 300px;
|
||
}
|
||
|
||
.result-card {
|
||
max-width: 400px;
|
||
margin: 0 auto;
|
||
transition: transform 0.3s ease;
|
||
|
||
&:hover {
|
||
transform: translateY(-4px);
|
||
|
||
.refresh-btn {
|
||
opacity: 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
.refresh-btn {
|
||
opacity: 0.7;
|
||
transition: opacity 0.3s ease;
|
||
|
||
&:hover {
|
||
opacity: 1;
|
||
}
|
||
}
|
||
|
||
// 刷新动画
|
||
@keyframes refresh-pulse {
|
||
0% {
|
||
transform: scale(1);
|
||
box-shadow: 0 0 0 rgba(var(--v-theme-primary), 0.5);
|
||
}
|
||
|
||
50% {
|
||
transform: scale(1.05);
|
||
box-shadow: 0 0 15px rgba(var(--v-theme-primary), 0.7);
|
||
}
|
||
|
||
100% {
|
||
transform: scale(1);
|
||
box-shadow: 0 0 0 rgba(var(--v-theme-primary), 0.5);
|
||
}
|
||
}
|
||
|
||
.refresh-animation {
|
||
animation: refresh-pulse 0.5s ease;
|
||
}
|
||
|
||
// 动画效果
|
||
.shuffle-enter-active,
|
||
.shuffle-leave-active {
|
||
transition: all 0.5s ease;
|
||
}
|
||
|
||
.shuffle-enter-from,
|
||
.shuffle-leave-to {
|
||
opacity: 0;
|
||
transform: translateY(30px);
|
||
}
|
||
|
||
.shuffle-move {
|
||
transition: transform 0.5s ease;
|
||
}
|
||
|
||
// 触摸屏优化
|
||
@media (hover: none) {
|
||
.counter-btn,
|
||
.start-btn {
|
||
min-height: 72px;
|
||
}
|
||
|
||
.student-item {
|
||
padding: 12px 20px;
|
||
font-size: 1.4rem;
|
||
}
|
||
|
||
.refresh-btn {
|
||
opacity: 1;
|
||
min-width: 36px;
|
||
min-height: 36px;
|
||
}
|
||
|
||
.filter-chip {
|
||
min-height: 40px;
|
||
font-size: 1rem;
|
||
}
|
||
}
|
||
|
||
// 添加模式切换样式
|
||
.mode-switch-container {
|
||
.mode-toggle {
|
||
border: 1px solid rgba(var(--v-theme-primary), 0.2);
|
||
border-radius: 50px;
|
||
padding: 4px;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||
|
||
.v-btn {
|
||
min-width: 120px;
|
||
height: 40px;
|
||
font-weight: 500;
|
||
letter-spacing: 0.5px;
|
||
|
||
&.v-btn--active {
|
||
transform: scale(1.02);
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 添加学号范围设置样式
|
||
.number-range-container {
|
||
max-width: 300px;
|
||
margin: 0 auto;
|
||
padding: 16px;
|
||
background: rgba(var(--v-theme-surface-variant), 0.1);
|
||
border-radius: 12px;
|
||
border: 1px solid rgba(var(--v-theme-primary), 0.1);
|
||
|
||
.number-input {
|
||
width: 100px;
|
||
|
||
:deep(.v-field) {
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||
}
|
||
}
|
||
}
|
||
</style>
|