解决所有bug 优化table内容

This commit is contained in:
2026-01-21 18:43:39 +08:00
parent 9984200814
commit 7f0280ec8a
80 changed files with 5202 additions and 744 deletions

View File

@@ -0,0 +1,457 @@
<template>
<div class="layout-padding">
<div class="layout-padding-auto layout-padding-view">
<!-- 搜索表单 -->
<el-row v-show="showSearch">
<el-form :model="searchForm" ref="searchFormRef" :inline="true" @keyup.enter="handleSearch">
<el-form-item label="楼号" prop="buildingNo">
<el-select
v-model="searchForm.buildingNo"
placeholder="请选择楼号"
clearable
filterable
style="width: 200px">
<el-option
v-for="item in buildingList"
:key="item.buildingNo"
:label="item.buildingNo"
:value="item.buildingNo">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="班级" prop="classCode">
<el-select
v-model="searchForm.classCode"
placeholder="请选择班级"
clearable
filterable
style="width: 200px">
<el-option
v-for="item in classList"
:key="item.classCode"
:label="item.classNo"
:value="item.classCode">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="月份" prop="month">
<el-date-picker
v-model="searchForm.month"
type="month"
placeholder="请选择月份"
format="YYYY-MM"
value-format="YYYY-MM"
clearable
style="width: 200px" />
</el-form-item>
<el-form-item>
<el-button type="primary" plain icon="Search" @click="handleSearch">查询</el-button>
<el-button icon="Refresh" @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
</el-row>
<!-- 操作按钮 -->
<el-row>
<div class="mb8" style="width: 100%">
<right-toolbar
v-model:showSearch="showSearch"
class="ml10 mr20"
style="float: right;"
@queryTable="getDataList">
</right-toolbar>
</div>
</el-row>
<!-- 表格 -->
<el-table
:data="state.dataList"
v-loading="state.loading"
border
:cell-style="tableStyle.cellStyle"
:header-cell-style="tableStyle.headerCellStyle"
@sort-change="sortChangeHandle">
<el-table-column type="index" label="序号" width="60" align="center">
<template #header>
<el-icon><List /></el-icon>
</template>
</el-table-column>
<el-table-column prop="totalScore" label="总分" show-overflow-tooltip align="center">
<template #header>
<el-icon><DataAnalysis /></el-icon>
<span style="margin-left: 4px">总分</span>
</template>
<template #default="scope">
<el-tag v-if="scope.row.totalScore !== undefined && scope.row.totalScore !== null" size="small" type="success" effect="plain">
{{ scope.row.totalScore }}
</el-tag>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column prop="rank" label="排名" show-overflow-tooltip align="center">
<template #header>
<el-icon><Trophy /></el-icon>
<span style="margin-left: 4px">排名</span>
</template>
<template #default="scope">
<el-tag v-if="scope.row.rank" size="small" :type="scope.row.rank <= 3 ? 'warning' : 'info'" effect="plain">
{{ scope.row.rank }}
</el-tag>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column prop="classNo" label="班级" show-overflow-tooltip>
<template #header>
<el-icon><Grid /></el-icon>
<span style="margin-left: 4px">班级</span>
</template>
</el-table-column>
<!-- 动态日期列 -->
<el-table-column
v-for="day in dayColumns"
:key="day"
:prop="`day${day}`"
:label="`${day}日`"
show-overflow-tooltip
align="center"
width="80">
<template #header>
<el-icon><Calendar /></el-icon>
<span style="margin-left: 4px">{{ day }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="150" align="center" fixed="right">
<template #header>
<el-icon><Setting /></el-icon>
<span style="margin-left: 4px">操作</span>
</template>
<template #default="scope">
<el-button
icon="Plus"
text
type="success"
@click="handleAddScore(scope.row)">
加分
</el-button>
<el-button
icon="Minus"
text
type="danger"
@click="handleSubtractScore(scope.row)">
减分
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 此接口不支持分页不显示分页组件 -->
</div>
<!-- 加分/减分对话框 -->
<el-dialog
v-model="scoreDialogVisible"
:title="scoreDialogTitle"
:close-on-click-modal="false"
draggable
width="500px">
<el-form
ref="scoreFormRef"
:model="scoreForm"
label-width="100px">
<el-form-item label="班级" prop="classNo">
<el-input
v-model="scoreForm.classNo"
disabled />
</el-form-item>
<el-form-item label="日期" prop="date">
<el-date-picker
v-model="scoreForm.date"
type="date"
placeholder="请选择日期"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
style="width: 100%" />
</el-form-item>
<el-form-item label="分数" prop="score">
<el-input-number
v-model="scoreForm.score"
:precision="0"
:step="1"
:min="0"
placeholder="请输入分数"
style="width: 100%" />
</el-form-item>
<el-form-item label="说明" prop="note">
<el-input
v-model="scoreForm.note"
type="textarea"
:rows="3"
placeholder="请输入说明"
maxlength="500"
show-word-limit />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="scoreDialogVisible = false"> </el-button>
<el-button type="primary" @click="submitScore"> </el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts" name="ClassRoomHygieneDailyAnalysis">
import { ref, reactive, defineAsyncComponent, onMounted, computed } from 'vue'
import { BasicTableProps, useTable } from "/@/hooks/table";
import { fetchList } from "/@/api/stuwork/classroomhygienedailyanalysis";
import { useMessage } from "/@/hooks/message";
import { getBuildingList } from '/@/api/stuwork/teachbuilding'
import { getClassListByRole } from '/@/api/basic/basicclass'
import { List, DataAnalysis, Trophy, Grid, Calendar, Setting } from '@element-plus/icons-vue'
// 定义变量内容
const searchFormRef = ref()
const scoreFormRef = ref()
// 搜索变量
const showSearch = ref(true)
const buildingList = ref<any[]>([])
const classList = ref<any[]>([])
const scoreDialogVisible = ref(false)
const scoreDialogTitle = ref('加分')
const isAddScore = ref(true) // true: 加分, false: 减分
// 加分/减分表单
const scoreForm = reactive({
classCode: '',
classNo: '',
date: '',
score: 0,
note: ''
})
// 搜索表单
const searchForm = reactive({
buildingNo: '',
classCode: '',
month: ''
})
// 计算月份的天数列
const dayColumns = computed(() => {
if (!searchForm.month) {
return []
}
const [year, month] = searchForm.month.split('-').map(Number)
const daysInMonth = new Date(year, month, 0).getDate()
return Array.from({ length: daysInMonth }, (_, i) => i + 1)
})
// 配置 useTable - 接口参数为 buildingNo 和 month数组格式
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: searchForm,
isPage: false, // 接口不支持分页
pageList: async (queryParams: any) => {
const params: any = {}
// 接口文档要求 buildingNo 和 month 都是数组格式
if (searchForm.buildingNo) {
params.buildingNo = Array.isArray(searchForm.buildingNo) ? searchForm.buildingNo : [searchForm.buildingNo]
}
if (searchForm.month) {
params.month = Array.isArray(searchForm.month) ? searchForm.month : [searchForm.month]
}
if (searchForm.classCode) {
params.classCode = searchForm.classCode
}
const res = await fetchList(params)
// 接口返回的数据结构:数组,每个元素包含日期字段(如 2025-12-01和班级信息
// 需要确保返回数组格式给 useTable
let dataList = []
if (Array.isArray(res.data)) {
dataList = res.data
} else if (res.data && Array.isArray(res.data.records)) {
dataList = res.data.records
} else if (res.data && Array.isArray(res.data.list)) {
dataList = res.data.list
} else if (res.data && typeof res.data === 'object') {
// 如果 res.data 是单个对象,转换为数组
dataList = [res.data]
}
// 处理数据:将日期字段转换为 day1, day2 等格式,方便表格显示
const processedData = dataList.map((item: any) => {
const processed: any = {
classCode: item.classCode || '',
classNo: item.classNo || '',
totalScore: item.scoreTotal || 0,
rank: item.order || 0,
isAddScore: item.isAddScore || 0
}
// 提取所有日期字段(格式为 YYYY-MM-DD
const datePattern = /^\d{4}-\d{2}-\d{2}$/
Object.keys(item).forEach(key => {
if (datePattern.test(key)) {
// 将日期转换为 day1, day2 等格式(根据日期中的天数)
const date = new Date(key)
const day = date.getDate()
processed[`day${day}`] = item[key]
}
})
// 确保所有日期字段都存在即使值为0或null避免表格列无法显示
if (searchForm.month) {
const [year, month] = searchForm.month.split('-').map(Number)
const daysInMonth = new Date(year, month, 0).getDate()
for (let i = 1; i <= daysInMonth; i++) {
if (!processed.hasOwnProperty(`day${i}`)) {
processed[`day${i}`] = 0
}
}
}
return processed
})
return {
...res,
data: processedData
}
},
props: {
item: 'records',
totalCount: 'total'
},
createdIsNeed: false // 不自动加载,需要手动调用
})
// table hook
const {
getDataList,
currentChangeHandle,
sizeChangeHandle,
sortChangeHandle,
tableStyle
} = useTable(state)
// 查询
const handleSearch = () => {
if (!searchForm.month) {
useMessage().warning('请选择月份')
return
}
getDataList()
}
// 重置
const handleReset = () => {
searchFormRef.value?.resetFields()
searchForm.buildingNo = ''
searchForm.classCode = ''
searchForm.month = ''
getDataList()
}
// 加分
const handleAddScore = (row: any) => {
isAddScore.value = true
scoreDialogTitle.value = '加分'
Object.assign(scoreForm, {
classCode: row.classCode || '',
classNo: row.classNo || '',
date: '',
score: 0,
note: ''
})
scoreDialogVisible.value = true
}
// 减分
const handleSubtractScore = (row: any) => {
isAddScore.value = false
scoreDialogTitle.value = '减分'
Object.assign(scoreForm, {
classCode: row.classCode || '',
classNo: row.classNo || '',
date: '',
score: 0,
note: ''
})
scoreDialogVisible.value = true
}
// 提交加分/减分
const submitScore = async () => {
if (!scoreForm.date) {
useMessage().warning('请选择日期')
return
}
if (!scoreForm.score || scoreForm.score <= 0) {
useMessage().warning('请输入有效的分数')
return
}
try {
// TODO: 调用加分/减分接口
// const api = isAddScore.value ? addScore : subtractScore
// await api(scoreForm)
useMessage().success(isAddScore.value ? '加分成功' : '减分成功')
scoreDialogVisible.value = false
getDataList()
} catch (err: any) {
useMessage().error(err.msg || (isAddScore.value ? '加分失败' : '减分失败'))
}
}
// 获取楼号列表(教学楼)
const getBuildingListData = async () => {
try {
const res = await getBuildingList()
if (res.data) {
// 处理返回的数据,可能是分页数据
if (res.data.records) {
buildingList.value = Array.isArray(res.data.records) ? res.data.records : []
} else if (Array.isArray(res.data)) {
buildingList.value = res.data
} else {
buildingList.value = []
}
}
} catch (err) {
console.error('获取楼号列表失败', err)
buildingList.value = []
}
}
// 获取班级列表
const getClassListData = async () => {
try {
const res = await getClassListByRole({})
if (res.data) {
if (Array.isArray(res.data.records)) {
classList.value = res.data.records
} else if (Array.isArray(res.data)) {
classList.value = res.data
} else {
classList.value = []
}
} else {
classList.value = []
}
} catch (err) {
console.error('获取班级列表失败', err)
classList.value = []
}
}
// 初始化
onMounted(() => {
getBuildingListData()
getClassListData()
})
</script>