531 lines
16 KiB
Vue
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> |