2026-04-22 18:04:19 +08:00

531 lines
16 KiB
Vue

<template>
<commonManage>
<div class="head">
<div class="left">
<div class="search-item">
<p class="desctipt">用户姓名:</p>
<el-input v-model="data.tableNeed.userName" class="m-2" clearable placeholder="请输入用户姓名" />
</div>
<div class="search-item">
<p class="desctipt">年级:</p>
<el-select v-model="data.tableNeed.gradeId" class="m-2" clearable placeholder="请选择年级">
<el-option label="一年级" value="1" />
<el-option label="二年级" value="2" />
<el-option label="三年级" value="3" />
<el-option label="四年级" value="4" />
<el-option label="五年级" value="5" />
<el-option label="六年级" value="6" />
<el-option label="初一" value="7" />
<el-option label="初二" value="8" />
<el-option label="初三" value="9" />
<el-option label="高一" value="10" />
<el-option label="高二" value="11" />
<el-option label="高三" value="12" />
<el-option label="大一" value="13" />
<el-option label="大二" value="14" />
<el-option label="大三" value="15" />
<el-option label="大四" value="16" />
</el-select>
</div>
<div class="search-item">
<p class="desctipt">性别:</p>
<el-select v-model="data.tableNeed.gender" class="m-2" clearable placeholder="请选择性别">
<el-option label="男" :value="1" />
<el-option label="女" :value="2" />
</el-select>
</div>
</div>
<div class="right">
<p v-for="(item, index) in handelData" :key="index" :class="item.className"
@click="btnClick(item.engName)">
{{ item.chinName }}</p>
</div>
</div>
<div class="cont">
<el-table :data="data.tableNeed.tableData" style="width: calc(100% - 40px) ;height: calc(100vh - 210px); margin:0 20px ;"
fit="true"
:header-cell-style="{ 'text-align': 'center', 'font-size': '12px', 'color': '#3F404A', padding: '3px', background: '#F8F8FA', height: '50px' }"
:cell-style="getCellStyles" :row-style="{ height: '0px' }">
<el-table-column fixed prop="ind" label="序号" />
<el-table-column prop="userName" label="用户名" />
<el-table-column prop="gradeName" label="年级" />
<el-table-column prop="birthDate" label="出生年月" />
<el-table-column prop="gender" label="性别">
<template #default="scope">
{{ scope.row.gender === 1 ? '男' : scope.row.gender === 2 ? '女' : '未知' }}
</template>
</el-table-column>
<el-table-column prop="address" label="地区" />
<el-table-column prop="height" label="身高(cm)" />
<el-table-column prop="weight" label="体重(kg)" />
<el-table-column prop="role" label="拥有身份" />
<el-table-column prop="createDate" label="创建时间" />
<el-table-column label="操作" width="200">
<template v-slot="{ row }">
<div class="operate">
<p class="edit" @click="showTrainingRecord(row)">训练记录</p>
<p class="edit" @click="showCheckInDetails(row)">打卡详情</p>
</div>
</template>
</el-table-column>
</el-table>
<el-pagination class="pagination" :current-page="data.tableNeed.pageIndex"
:page-size="data.tableNeed.pageSize" :page-sizes="[10, 50, 100, 200]"
layout="total, sizes, prev, pager, next, jumper" :total="data.tableNeed.total"
@size-change="handleSizeChange" @current-change="changePage" />
</div>
</commonManage>
<!-- 新增/编辑用户对话框 -->
<commonDialog :list="data.dialogData" @cancle="cancle" @confirm="confirm" v-if="data.dialogData.dialogVisible">
<template #cont>
<div class="dialogManage">
<el-form ref="formRef" :model="ruleForm" :rules="rules" label-width="120px" class="demo-ruleForm"
size="default" status-icon>
<el-form-item label="用户名:" prop="userName">
<el-input :disabled="disabled" v-model="ruleForm.userName" placeholder="请输入用户名" />
</el-form-item>
<el-form-item label="真实姓名:" prop="userTrueName">
<el-input :disabled="disabled" v-model="ruleForm.userTrueName" placeholder="请输入真实姓名" />
</el-form-item>
<el-form-item label="年级:" prop="grade">
<el-select :disabled="disabled" v-model="ruleForm.grade" placeholder="请选择年级">
<el-option label="一年级" value="一年级" />
<el-option label="二年级" value="二年级" />
<el-option label="三年级" value="三年级" />
<el-option label="四年级" value="四年级" />
<el-option label="五年级" value="五年级" />
</el-select>
</el-form-item>
<el-form-item label="出生年月:" prop="birthDate">
<el-input :disabled="disabled" v-model="ruleForm.birthDate" placeholder="请输入出生年月" />
</el-form-item>
<el-form-item label="性别:" prop="gender">
<el-select :disabled="disabled" v-model="ruleForm.gender" placeholder="请选择性别">
<el-option label="男" :value="1" />
<el-option label="女" :value="2" />
</el-select>
</el-form-item>
<el-form-item label="地区:" prop="region">
<el-input :disabled="disabled" v-model="ruleForm.region" placeholder="请输入地区" />
</el-form-item>
<el-form-item label="身高(cm):" prop="height">
<el-input :disabled="disabled" v-model="ruleForm.height" placeholder="请输入身高" />
</el-form-item>
<el-form-item label="体重(kg):" prop="weight">
<el-input :disabled="disabled" v-model="ruleForm.weight" placeholder="请输入体重" />
</el-form-item>
</el-form>
</div>
</template>
</commonDialog>
<!-- 训练记录对话框 -->
<TrainingRecord
v-if="data.trainingRecord.visible"
:userId="data.trainingRecord.userId"
v-model:visible="data.trainingRecord.visible"
/>
<!-- 打卡详情对话框 -->
<CheckInDetails
v-if="data.checkInDetails.visible"
:userId="data.checkInDetails.userId"
v-model:visible="data.checkInDetails.visible"
/>
</template>
<script lang="ts" setup>
import { ref, onMounted, reactive } from 'vue';
import commonManage from '@/components/commonManage/index.vue';
import commonDialog from '@/components/commonDialog/index.vue';
import TrainingRecord from './trainingRecord.vue';
import CheckInDetails from './checkInDetails.vue';
import { useRoute } from 'vue-router';
import { useStore } from 'vuex';
import * as _api from '@/api/user';
import { ElMessage, ElMessageBox } from 'element-plus';
const formRef = ref(null);
const route = useRoute();
const currentRoute = route.path; // 获取当前页面路由
const store = useStore();
let disabled = ref(false);
// 获取权限按钮
let buttons = store.getters.getPermission(currentRoute).permission;
let contrast = {
'查询': 'Search',
'新增': 'Add',
}; // 对照表
let handelData = ref<any>([]);
buttons.map((i) => {
handelData.value.push({
engName: i,
chinName: '',
className: i
});
});
// 给每个按钮添加中文名
for (let i in contrast) {
handelData.value.map((v) => {
if (v.engName == contrast[i]) {
v.chinName = i;
}
});
}
// 按钮排序
const customOrder = {
"Search": 1,
'Add': 2,
};
handelData.value.sort((a, b) => {
const orderA = customOrder[a.engName];
const orderB = customOrder[b.engName];
if (orderA < orderB) {
return -1;
} else if (orderA > orderB) {
return 1;
} else {
return 0;
}
});
// 添加重置按钮
handelData.value.unshift({
engName: 'reset',
chinName: '重置',
className: 'reset'
});
// 表单验证规则
const rules = ref({
userName: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
],
userTrueName: [
{ required: true, message: '请输入真实姓名', trigger: 'blur' },
],
grade: [
{ required: true, message: '请选择年级', trigger: 'change' },
],
gender: [
{ required: true, message: '请选择性别', trigger: 'change' },
],
});
// 表单数据
const ruleForm = ref({
user_Id: 0,
userName: '',
userTrueName: '',
grade: '',
birthDate: '',
gender: null,
region: '',
height: '',
weight: '',
identity: ''
});
// 页面数据
const data = reactive({
tableNeed: {
pageIndex: 1,
pageSize: 10,
total: 0,
userTrueName: '',
grade: '',
gender: null,
tableData: []
},
dialogData: {
dialogVisible: false,
title: '',
confirmText: '确定',
cancleText: '取消',
},
trainingRecord: {
visible: false,
userId: 0
},
checkInDetails: {
visible: false,
userId: 0
}
});
// 单元格样式
const getCellStyles = ({ row, column, rowIndex, columnIndex }) => {
return {
'text-align': 'center',
'font-size': '12px',
'color': '#3F404A',
'padding': '3px',
'height': '50px'
};
};
// 获取用户列表
const getList = async () => {
try {
const res = await _api.getUserList(
data.tableNeed.pageIndex,
data.tableNeed.pageSize,
data.tableNeed.userTrueName,
data.tableNeed.grade,
data.tableNeed.gender
);
if (res.data) {
data.tableNeed.tableData = res.data.datas.map((item, index) => {
return {
...item,
ind: (data.tableNeed.pageIndex - 1) * data.tableNeed.pageSize + index + 1
};
});
data.tableNeed.total = res.data.total;
}
} catch (error) {
console.error('获取用户列表失败', error);
}
};
// 按钮点击事件
const btnClick = (type) => {
switch (type) {
case 'Search':
getList();
break;
case 'reset':
data.tableNeed.userTrueName = '';
data.tableNeed.grade = '';
data.tableNeed.gender = null;
break;
case 'Add':
data.dialogData.dialogVisible = true;
data.dialogData.title = '新增用户';
disabled.value = false;
ruleForm.value = {
user_Id: 0,
userName: '',
userTrueName: '',
grade: '',
birthDate: '',
gender: null,
region: '',
height: '',
weight: '',
identity: ''
};
break;
}
};
// 编辑用户
const editTable = async (row) => {
try {
const res = await _api.getUserDetails(row.user_Id);
if (res.data) {
ruleForm.value = res.data;
data.dialogData.dialogVisible = true;
data.dialogData.title = '编辑用户';
disabled.value = false;
}
} catch (error) {
console.error('获取用户详情失败', error);
}
};
// 查看用户详情
const detail = async (row) => {
try {
const res = await _api.getUserDetails(row.user_Id);
if (res.data) {
ruleForm.value = res.data;
data.dialogData.dialogVisible = true;
data.dialogData.title = '用户详情';
disabled.value = true;
}
} catch (error) {
console.error('获取用户详情失败', error);
}
};
// 删除用户
const deleteUser = (row) => {
ElMessageBox.confirm('确定要删除该用户吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(async () => {
try {
await _api.deleteUser(row.user_Id);
ElMessage.success('删除成功');
getList();
} catch (error) {
console.error('删除用户失败', error);
}
}).catch(() => {
// 取消删除
});
};
// 显示训练记录
const showTrainingRecord = (row) => {
data.trainingRecord.userId = row.user_Id;
data.trainingRecord.visible = true;
};
// 显示打卡详情
const showCheckInDetails = (row) => {
data.checkInDetails.userId = row.user_Id;
data.checkInDetails.visible = true;
};
// 对话框取消
const cancle = () => {
data.dialogData.dialogVisible = false;
};
// 对话框确认
const confirm = async () => {
if (!formRef.value) return;
await formRef.value.validate(async (valid) => {
if (valid) {
try {
if (ruleForm.value.user_Id === 0) {
// 新增
await _api.addUser(ruleForm.value);
ElMessage.success('新增成功');
} else {
// 编辑
await _api.updateUser(ruleForm.value);
ElMessage.success('更新成功');
}
data.dialogData.dialogVisible = false;
getList();
} catch (error) {
console.error('保存用户失败', error);
}
}
});
};
// 分页大小变化
const handleSizeChange = (val) => {
data.tableNeed.pageSize = val;
data.tableNeed.pageIndex = 1;
getList();
};
// 页码变化
const changePage = (val) => {
data.tableNeed.pageIndex = val;
getList();
};
// 页面加载时获取列表
onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped>
.head {
width: 100%;
height: 60px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
box-sizing: border-box;
.left {
display: flex;
align-items: center;
margin-right: 20px;
.search-item {
display: flex;
align-items: center;
margin-right: 20px;
}
.desctipt {
font-size: 14px;
font-weight: 400;
color: #3F404A;
margin-right: 10px;
white-space: nowrap;
}
.m-2 {
width: 150px;
}
}
.right {
display: flex;
align-items: center;
p {
width: 80px;
height: 32px;
background: #3E7BFA;
border-radius: 4px;
font-size: 14px;
font-weight: 400;
color: #FFFFFF;
line-height: 32px;
text-align: center;
margin-left: 10px;
cursor: pointer;
}
.reset {
background: #F8F8FA;
color: #3F404A;
}
}
}
.cont {
width: 100%;
height: calc(100% - 60px);
box-sizing: border-box;
position: relative;
.pagination {
position: absolute;
bottom: 20px;
right: 20px;
}
.operate {
display: flex;
justify-content: center;
p {
margin: 0 5px;
color: #3E7BFA;
cursor: pointer;
}
}
.green {
color: #67C23A;
}
.red {
color: #F56C6C;
}
}
.dialogManage {
width: 100%;
padding: 20px;
box-sizing: border-box;
}
</style>