2025-10-30 19:30:06 +08:00
|
|
|
<template>
|
|
|
|
|
<div class="task-performance-page">
|
2025-11-25 17:37:02 +08:00
|
|
|
<BaseTable tableName="TASK_PERFORMANCE" ref="baseTableRef" showCheckbox hidePagination :actionList="actionList">
|
2025-10-30 19:30:06 +08:00
|
|
|
<template #leftOptions>
|
|
|
|
|
<div class="operate-box">
|
|
|
|
|
<el-upload
|
|
|
|
|
class="mr12"
|
|
|
|
|
:limit="1"
|
|
|
|
|
accept=".xls,.xlsx"
|
|
|
|
|
:auto-upload="true"
|
|
|
|
|
:show-file-list="false"
|
2025-11-26 18:49:29 +08:00
|
|
|
:on-change="handleLocalChangeExcelFun"
|
|
|
|
|
:before-upload="(File: any) => uploadLocalFileFun(File)"
|
2025-10-30 19:30:06 +08:00
|
|
|
>
|
|
|
|
|
<el-button icon="">导入Excel</el-button>
|
|
|
|
|
</el-upload>
|
2025-11-26 18:49:29 +08:00
|
|
|
<el-button icon="" @click="exportFileFun">导出Excel</el-button>
|
|
|
|
|
<el-button type="primary" @click="openAddPerformanceWindFun">新增</el-button>
|
|
|
|
|
<el-button v-if="showSaveButton" type="primary" @click="saveFun">保存</el-button>
|
2025-10-30 19:30:06 +08:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<template #operate="{ row }">
|
|
|
|
|
<el-button type="danger" link @click="delPerformance(row)">删除</el-button>
|
|
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
</BaseTable>
|
|
|
|
|
|
|
|
|
|
<addTaskPerformance
|
|
|
|
|
v-if="performanceVisible"
|
|
|
|
|
:tableName="'TASK_PERFORMANCE'"
|
|
|
|
|
@cancel="performanceVisible = false"
|
2025-11-26 18:49:29 +08:00
|
|
|
@submit="addPerformanceFun"
|
2025-10-30 19:30:06 +08:00
|
|
|
>
|
|
|
|
|
</addTaskPerformance>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2025-11-13 18:12:35 +08:00
|
|
|
import { ref, onMounted } from 'vue';
|
2025-10-30 19:30:06 +08:00
|
|
|
import BaseTable from '@/components/common/table/baseTable.vue';
|
|
|
|
|
import { ElMessage } from 'element-plus';
|
2025-11-25 17:37:02 +08:00
|
|
|
import { getTaskPerformanceApi, batchAddTaskPerformanceApi, batchDeleteTaskPerformanceApi, getRunPerformanceApi } from '@/api/task/taskpool';
|
2025-11-12 15:36:24 +08:00
|
|
|
import { cloneDeep } from 'lodash-es';
|
2025-11-14 15:10:32 +08:00
|
|
|
import { FileUtil } from '@/utils/file';
|
2025-11-25 17:37:02 +08:00
|
|
|
import addTaskPerformance from './addTaskPerformance.vue';
|
2025-10-30 19:30:06 +08:00
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
taskId: {
|
|
|
|
|
type: Number,
|
|
|
|
|
default: 100,
|
|
|
|
|
},
|
2025-11-25 17:37:02 +08:00
|
|
|
runInfo: {
|
|
|
|
|
type: Object,
|
|
|
|
|
default: () => {},
|
|
|
|
|
},
|
2025-11-25 19:56:52 +08:00
|
|
|
taskInfo: {
|
|
|
|
|
type: Object,
|
|
|
|
|
default: () => {},
|
|
|
|
|
},
|
2025-11-25 17:37:02 +08:00
|
|
|
showSaveButton: {
|
|
|
|
|
type: Boolean,
|
|
|
|
|
default: false,
|
|
|
|
|
},
|
|
|
|
|
paramType: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: 'task',
|
|
|
|
|
},
|
2025-10-30 19:30:06 +08:00
|
|
|
});
|
|
|
|
|
const baseTableRef = ref();
|
|
|
|
|
const performanceVisible = ref(false);
|
|
|
|
|
|
|
|
|
|
const performanceData = ref<any>([]);
|
2025-11-26 18:49:29 +08:00
|
|
|
const getTaskPerformanceDataFun = async () => {
|
2025-10-30 19:30:06 +08:00
|
|
|
console.log(props.taskId);
|
2025-11-25 17:37:02 +08:00
|
|
|
console.log(props.runInfo);
|
2025-11-25 19:56:52 +08:00
|
|
|
const res: any = props.paramType === 'task' ? await getTaskPerformanceApi({ taskId: props.taskInfo?.id }) : await getRunPerformanceApi({ runId: props.runInfo?.uuid }) ;
|
2025-10-30 19:30:06 +08:00
|
|
|
if (res && res.code === 200) {
|
|
|
|
|
performanceData.value = res.data;
|
|
|
|
|
|
|
|
|
|
console.log(performanceData.value);
|
|
|
|
|
if (baseTableRef.value) {
|
|
|
|
|
baseTableRef.value.setDataFun(performanceData.value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
// ElMessage.success('获取任务性能指标数据' + props.taskId);
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-26 18:49:29 +08:00
|
|
|
const openAddPerformanceWindFun = () => {
|
2025-10-30 19:30:06 +08:00
|
|
|
performanceVisible.value = true;
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-26 18:49:29 +08:00
|
|
|
const addPerformanceFun = async (data: any) => {
|
2025-10-30 19:30:06 +08:00
|
|
|
|
|
|
|
|
console.log(data, 'data');
|
|
|
|
|
data.flag = 'add';
|
|
|
|
|
const { fullData, visibleData, tableData, footerData } = baseTableRef.value.tableRef.getTableData();
|
|
|
|
|
|
|
|
|
|
const existPerformance = fullData.find((item: any) => {
|
2025-11-25 19:56:52 +08:00
|
|
|
return item.nodeName === data.nodeName;
|
2025-10-30 19:30:06 +08:00
|
|
|
}) || null;
|
|
|
|
|
|
|
|
|
|
if (existPerformance) {
|
|
|
|
|
ElMessage.warning('已存在该指标,无法新增!');
|
|
|
|
|
} else {
|
|
|
|
|
baseTableRef.value.tableRef.insertAt(data, -1);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log(fullData, 'fullData');
|
|
|
|
|
console.log(visibleData, 'visibleData');
|
|
|
|
|
console.log(tableData, 'tableData');
|
|
|
|
|
console.log(footerData, 'footerData');
|
|
|
|
|
|
|
|
|
|
performanceVisible.value = false;
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const deletePerformanceList = ref<any>([]);
|
|
|
|
|
const delPerformance = (row: any) => {
|
|
|
|
|
baseTableRef.value.tableRef.remove(row);
|
|
|
|
|
if (row.flag != 'add') {
|
|
|
|
|
deletePerformanceList.value.push(row);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-26 18:49:29 +08:00
|
|
|
const batchAddTaskPerformanceFun = async () => {
|
2025-10-30 19:30:06 +08:00
|
|
|
|
|
|
|
|
const list = baseTableRef.value.tableRef.getInsertRecords();
|
|
|
|
|
|
|
|
|
|
console.log(list, 'list');
|
2025-11-25 19:56:52 +08:00
|
|
|
console.log(props.paramType, 'paramType');
|
2025-10-30 19:30:06 +08:00
|
|
|
|
|
|
|
|
const performanceList: any = [];
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < list.length; i++) {
|
2025-11-25 17:37:02 +08:00
|
|
|
const obj :any = {
|
2025-10-30 19:30:06 +08:00
|
|
|
uuid: '',
|
|
|
|
|
nodeId: '',
|
|
|
|
|
performanceName: list[i].performanceName,
|
|
|
|
|
nodeName: list[i].nodeName,
|
|
|
|
|
englishName: list[i].englishName,
|
|
|
|
|
nodeCode: list[i].nodeCode,
|
|
|
|
|
poolName: list[i].poolName,
|
|
|
|
|
performanceType: list[i].performanceType,
|
|
|
|
|
unit: list[i].unit,
|
|
|
|
|
targetValue: list[i].targetValue,
|
|
|
|
|
lowValue: list[i].lowValue,
|
|
|
|
|
highValue: list[i].highValue,
|
|
|
|
|
method: list[i].method,
|
|
|
|
|
description: list[i].description,
|
|
|
|
|
taskName: list[i].taskName,
|
|
|
|
|
standard: list[i].standard,
|
|
|
|
|
tenantId: list[i].tenantId,
|
|
|
|
|
createTime: list[i].createTime,
|
|
|
|
|
pid: 0,
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-25 17:37:02 +08:00
|
|
|
if (props.paramType === 'task') {
|
2025-11-25 19:56:52 +08:00
|
|
|
obj.taskId = props.taskInfo?.uuid;
|
2025-11-25 17:37:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (props.paramType === 'run') {
|
2025-11-25 19:56:52 +08:00
|
|
|
obj.runId = props.runInfo.uuid;
|
|
|
|
|
obj.taskId = props.runInfo.taskId;
|
2025-11-25 17:37:02 +08:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log(obj, 'objobjobj');
|
|
|
|
|
|
2025-10-30 19:30:06 +08:00
|
|
|
performanceList.push(obj);
|
|
|
|
|
}
|
2025-11-25 17:37:02 +08:00
|
|
|
|
2025-10-30 19:30:06 +08:00
|
|
|
if (!list.length) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-11-25 17:37:02 +08:00
|
|
|
|
|
|
|
|
const param:any = {
|
2025-10-30 19:30:06 +08:00
|
|
|
performanceList: performanceList,
|
2025-11-25 17:37:02 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (props.paramType === 'task') {
|
2025-11-25 19:56:52 +08:00
|
|
|
param.taskId = props.taskInfo?.uuid;
|
2025-11-25 17:37:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (props.paramType === 'run') {
|
2025-11-25 19:56:52 +08:00
|
|
|
param.taskId = props.runInfo.taskId;
|
|
|
|
|
param.runId = props.runInfo.uuid;
|
2025-11-25 17:37:02 +08:00
|
|
|
}
|
|
|
|
|
const res: any = await batchAddTaskPerformanceApi(param);
|
2025-10-30 19:30:06 +08:00
|
|
|
if (res && res.code === 200) {
|
|
|
|
|
// ElMessage.success('新增成功!');
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-26 18:49:29 +08:00
|
|
|
const batchDeleteTaskPerformanceFun = async () => {
|
2025-10-30 19:30:06 +08:00
|
|
|
const ids = deletePerformanceList.value.map((item: any) => {
|
|
|
|
|
return item.id;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!ids.length) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const res: any = await batchDeleteTaskPerformanceApi(ids);
|
|
|
|
|
if (res && res.code === 200) {
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-26 18:49:29 +08:00
|
|
|
const saveFun = async () => {
|
2025-10-30 19:30:06 +08:00
|
|
|
|
2025-11-26 18:49:29 +08:00
|
|
|
await batchAddTaskPerformanceFun();
|
|
|
|
|
await batchDeleteTaskPerformanceFun();
|
2025-10-30 19:30:06 +08:00
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-26 18:49:29 +08:00
|
|
|
const uploadLocalFileFun = async (File: any) => {
|
2025-10-30 19:30:06 +08:00
|
|
|
console.log(File);
|
|
|
|
|
|
|
|
|
|
ElMessage.success('正在导入列表,请勿重复导入!');
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const performanceInfoList = [
|
|
|
|
|
{
|
|
|
|
|
chineseName: '指标名称',
|
2025-11-20 14:40:05 +08:00
|
|
|
englishName: 'nodeName',
|
2025-10-30 19:30:06 +08:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: '英文名',
|
|
|
|
|
englishName: 'englishName',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: '指标类型',
|
|
|
|
|
englishName: 'performanceType',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: '达标方式',
|
|
|
|
|
englishName: 'method',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: '目标值',
|
|
|
|
|
englishName: 'highValue',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: '分析值',
|
|
|
|
|
englishName: 'value',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: '单位',
|
|
|
|
|
englishName: 'unit',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: '描述',
|
|
|
|
|
englishName: 'description',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: '低性能',
|
|
|
|
|
englishName: 'lowValue',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: '节点编号',
|
|
|
|
|
englishName: 'nodeCode',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: '节点id',
|
|
|
|
|
englishName: 'nodeId',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: '节点名称',
|
|
|
|
|
englishName: 'nodeName',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: 'pid',
|
|
|
|
|
englishName: 'pid',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: '库名称',
|
|
|
|
|
englishName: 'poolName',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: '标准',
|
|
|
|
|
englishName: 'standard',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: 'targetValue',
|
|
|
|
|
englishName: 'targetValue',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: '任务名称',
|
|
|
|
|
englishName: 'taskName',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: 'tenantId',
|
|
|
|
|
englishName: 'tenantId',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
chineseName: 'uuid',
|
|
|
|
|
englishName: 'uuid',
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const performanceFile = ref<any>({});
|
2025-11-26 18:49:29 +08:00
|
|
|
const handleLocalChangeExcelFun = async (uploadFile: any, uploadFiles: any) => {
|
2025-10-30 19:30:06 +08:00
|
|
|
performanceFile.value = uploadFile.raw;
|
|
|
|
|
console.log(uploadFiles);
|
|
|
|
|
|
|
|
|
|
let fileInfo: any = [];
|
2025-11-14 15:10:32 +08:00
|
|
|
await FileUtil.parsingExcelFile(performanceFile.value).then((result: any) => {
|
2025-10-30 19:30:06 +08:00
|
|
|
fileInfo = result;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
conversionName(fileInfo, performanceInfoList, 'chineseName', 'englishName');
|
|
|
|
|
const newList = arraysConvertedToObjects(fileInfo);
|
|
|
|
|
|
|
|
|
|
const newData = baseTableRef.value.tableRef.getTableData().visibleData;
|
|
|
|
|
const commonNameList: any = [];
|
|
|
|
|
for (let i = 0; i < newData.length; i++) {
|
|
|
|
|
for (let j = 0; j < newList.length; j++) {
|
|
|
|
|
if (newData[i].code === newList[j].code) {
|
|
|
|
|
commonNameList.push(newList[j].code);
|
|
|
|
|
for (const key in newData[i]) {
|
|
|
|
|
if (key != 'change_flag' && key != 'id' && key != 'value') {
|
|
|
|
|
newData[i][key] = newList[j][key];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (key === 'value') {
|
|
|
|
|
if (newData[i][key] != newList[j][key]) {
|
|
|
|
|
if (newData[i].flag != 'add') {
|
|
|
|
|
newData[i].flag = 'edit';
|
|
|
|
|
}
|
|
|
|
|
newData[i][key] = newList[j][key];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if (newData[i].change_flag != 'add') {
|
|
|
|
|
// newData[i].change_flag = 'edit';
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (let i = 0; i < newList.length; i++) {
|
|
|
|
|
if (!commonNameList.includes(newList[i].performanceName)) {
|
|
|
|
|
|
|
|
|
|
baseTableRef.value.tableRef.insertAt(newList[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const allData = baseTableRef.value.tableRef.getTableData().visibleData;
|
|
|
|
|
|
|
|
|
|
console.log(allData, 'allData.allData');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 性能指标数组中英名称转换
|
|
|
|
|
const conversionName = (data: any, names: any, before: string, after: string) => {
|
|
|
|
|
for (let i = 0; i < data[0].length; i++) {
|
|
|
|
|
for (let j = 0; j < names.length; j++) {
|
|
|
|
|
if (data[0][i] === names[j][before]) {
|
|
|
|
|
data[0][i] = names[j][after];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 数据转化成第一行为属性的对象
|
|
|
|
|
const arraysConvertedToObjects = (arr: any) => {
|
|
|
|
|
const herder = arr[0];
|
|
|
|
|
const body = arr.slice(1);
|
|
|
|
|
|
|
|
|
|
const newArr: any = [];
|
|
|
|
|
for (let i = 0; i < body.length; i++) {
|
|
|
|
|
const obj: any = {};
|
|
|
|
|
for (let j = 0; j < herder.length; j++) {
|
|
|
|
|
obj[herder[j]] = body[i][j];
|
|
|
|
|
}
|
|
|
|
|
obj.change_flag = 'add';
|
|
|
|
|
newArr.push(obj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return newArr;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 导出excel
|
2025-11-26 18:49:29 +08:00
|
|
|
const exportFileFun = () => {
|
2025-10-30 19:30:06 +08:00
|
|
|
const statusList = [
|
|
|
|
|
{
|
|
|
|
|
label: '不合格',
|
|
|
|
|
label2: '不合格',
|
|
|
|
|
value: 1,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '风险可控',
|
|
|
|
|
label2: '风险可控',
|
|
|
|
|
value: 2,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '未分析',
|
|
|
|
|
label2: '未评估',
|
|
|
|
|
value: 3,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '合格',
|
|
|
|
|
label2: '合格',
|
|
|
|
|
value: 4,
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
const newData = cloneDeep(baseTableRef.value.tableRef.getTableData().visibleData);
|
|
|
|
|
|
|
|
|
|
console.log(1111111111111);
|
|
|
|
|
|
|
|
|
|
newData.forEach((item: any) => {
|
|
|
|
|
item.status = statusList.find((item_2: any) => {
|
|
|
|
|
return item_2.value === item.status;
|
|
|
|
|
})?.label;
|
|
|
|
|
item.risk =
|
|
|
|
|
statusList.find((item_2: any) => {
|
|
|
|
|
return item_2.value === item.risk;
|
|
|
|
|
})?.label2 || '未评估';
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
FileUtil.exportExcel(newData, '指标', performanceInfoList);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
defineExpose({
|
2025-11-26 18:49:29 +08:00
|
|
|
saveFun,
|
2025-11-26 17:18:25 +08:00
|
|
|
baseTableRef,
|
2025-10-30 19:30:06 +08:00
|
|
|
});
|
|
|
|
|
|
2025-11-25 17:37:02 +08:00
|
|
|
const actionList = ref([
|
|
|
|
|
{
|
|
|
|
|
title: '删除',
|
|
|
|
|
type: 'danger',
|
|
|
|
|
needConfirm: true,
|
|
|
|
|
confirmTip: '确认删除吗?',
|
|
|
|
|
click: (row:any) => {
|
|
|
|
|
delPerformance(row);
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
]);
|
|
|
|
|
|
2025-10-30 19:30:06 +08:00
|
|
|
onMounted(async () => {
|
2025-11-26 18:49:29 +08:00
|
|
|
await getTaskPerformanceDataFun();
|
2025-10-30 19:30:06 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
.task-performance-page {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
|
|
|
|
.operate-box {
|
|
|
|
|
width: 100%;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.mr12 {
|
|
|
|
|
margin-right: 12px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|