增加学员头像上传 + 学员修改

This commit is contained in:
buliping committed 2026-09-28 17:11:30 +08:00
1 parent ad533c55fb
commit 86c04320fd
2 files changed
+164 -8

No files matched your search

+9
View File
@@ -26,6 +26,15 @@ export function addStudent(data) {
})
}
// 修改教师信息
export function updateStudent(data) {
return request({
url: '/train/student/' + (data.sId || ''),
method: 'put',
data: data
})
}
// 查询可关联学员的系统用户候选列表
export function getStudentBindableUsers(keyword) {
return request({
+155 -8
View File
@@ -59,6 +59,20 @@
</el-row>
<el-table v-loading="loading" :data="studentList">
<el-table-column label="头像" align="center" width="80">
<template slot-scope="scope">
<el-image
:src="avatarUrl(scope.row.avatar)"
:preview-src-list="[avatarUrl(scope.row.avatar)]"
fit="cover"
class="student-avatar"
>
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline" />
</div>
</el-image>
</template>
</el-table-column>
<el-table-column label="学员姓名" align="center" prop="sName" min-width="110" />
<el-table-column label="性别" align="center" prop="sGender" width="70">
<template slot-scope="scope">
@@ -99,7 +113,7 @@
<el-tag v-else type="info" size="mini">未关联</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="210">
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="280">
<template slot-scope="scope">
<el-button
v-hasPermi="['train:student:query']"
@@ -108,6 +122,13 @@
icon="el-icon-view"
@click="handleDetail(scope.row)"
>详情</el-button>
<el-button
v-hasPermi="['train:student:edit']"
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>修改</el-button>
<el-button
v-if="!scope.row.userName && !scope.row.userId"
v-hasPermi="['train:student:bindUser']"
@@ -145,8 +166,11 @@
@pagination="getList"
/>
<el-dialog title="新增学员主档" :visible.sync="createOpen" width="560px" append-to-body @closed="resetCreate">
<el-dialog :title="createTitle" :visible.sync="createOpen" width="560px" append-to-body @closed="resetCreate">
<el-form ref="createForm" :model="createForm" :rules="rules" label-width="90px">
<el-form-item label="学员头像" prop="avatar">
<studentAvatar :user="{ avatar: createForm.avatar }" @success="handleAvatarSuccess" />
</el-form-item>
<el-form-item label="学员姓名" prop="sName">
<el-input v-model="createForm.sName" placeholder="请输入学员姓名" maxlength="50" show-word-limit />
</el-form-item>
@@ -199,6 +223,16 @@
<el-dialog title="学员主档详情" :visible.sync="detailOpen" width="560px" append-to-body>
<el-form :model="detail" label-width="110px" class="student-detail">
<el-form-item label="学员头像">
<el-image
v-if="detail.avatar"
:src="avatarUrl(detail.avatar)"
:preview-src-list="[avatarUrl(detail.avatar)]"
fit="cover"
class="student-avatar"
/>
<span v-else>-</span>
</el-form-item>
<el-form-item label="学员姓名"><span>{{ detail.sName || '-' }}</span></el-form-item>
<el-form-item label="系统编号"><span>{{ detail.sId || '-' }}</span></el-form-item>
<el-form-item label="关联系统账号">
@@ -277,14 +311,17 @@
</template>
<script>
import { addStudent, getStudent, listStudent, delStudent, getStudentBindableUsers, bindStudentUser, unbindStudentUser } from '@/api/train/student'
import request from '@/utils/request'
import { addStudent, getStudent, listStudent, delStudent, getStudentBindableUsers, bindStudentUser, unbindStudentUser, updateStudent } from '@/api/train/student'
import {deptTreeSelect} from "@/api/system/user";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import {listDept} from "@/api/system/dept";
import studentAvatar from "./studentAvatar.vue";
import {addTeacher, updateTeacher} from "@/api/train/teacher";
export default {
name: 'Student',
components: { Treeselect },
components: { studentAvatar, Treeselect },
data() {
const validateIdCard = (rule, value, callback) => {
if (!value || value.trim() === '') {
@@ -304,6 +341,9 @@ export default {
total: 0,
studentList: [],
createOpen: false,
createTitle: '新增学员主档',
// 弹窗是否为修改模式(true=修改,false=新增),用于复用同一弹窗
isEdit: false,
detailOpen: false,
detail: {},
// 账号关联弹窗
@@ -326,6 +366,8 @@ export default {
deptOptions: undefined,
deptArr: {},
createForm: {},
// 头像上传组件用的学员对象(avatar 为入库的相对地址)
user: { avatar: '' },
rules: {
sName: [
{ required: true, message: '学员姓名不能为空', trigger: 'blur' },
@@ -411,10 +453,43 @@ export default {
},
handleAdd() {
this.resetCreate()
this.isEdit = false
this.createTitle = '新增学员主档'
this.createOpen = true
},
/** 修改按钮:复用新增弹窗,回填学员信息 */
handleUpdate(row) {
this.resetCreate()
this.isEdit = true
this.createTitle = '修改学员主档'
// 身份证号为脱敏字段,不回显;留空表示不修改
this.createForm = {
sId: row.sId,
avatar: row.avatar || null,
sName: row.sName || null,
sGender: row.sGender || '男',
sBirth: row.sBirth || null,
orgName: this.toDeptValue(row.orgName),
sPhone: row.sPhone || null,
sEmail: row.sEmail || null,
idCard: null,
faceRef: row.faceRef || null,
remark: row.remark || null
}
// 同步头像组件预览
this.user = { avatar: this.createForm.avatar || '' }
this.createOpen = true
},
/** 部门值归一化:数字字符串转 Number,保证与部门树选项 id 类型一致 */
toDeptValue(value) {
if (value === null || value === undefined || value === '') {
return null
}
return /^\d+$/.test(String(value)) ? Number(value) : value
},
resetCreate() {
this.createForm = {
avatar: null,
sName: null,
sGender: '男',
sBirth: null,
@@ -425,23 +500,77 @@ export default {
faceRef: null,
remark: null
}
// 重置头像组件预览
this.user = { avatar: '' }
this.$set(this.createForm, "avatar", null);
// 还原为新增模式
this.isEdit = false
this.createTitle = '新增学员主档'
if (this.$refs.createForm) {
this.resetForm('createForm')
}
},
// 接收子组件上传成功抛出的头像地址:写入新增表单,随其他学员信息一并提交入库
handleAvatarSuccess(imgUrl) {
if (!imgUrl) {
return
}
this.$set(this.createForm, 'avatar', imgUrl)
// 校验通过后清除该项的校验提示
if (this.$refs.createForm) {
this.$refs.createForm.clearValidate('avatar')
}
},
// 头像地址解析:补全 baseApi,空值使用默认头像
avatarUrl(avatar) {
if (!avatar) {
return require('@/assets/images/profile.jpg')
}
if (avatar.indexOf('http') === 0 || avatar.indexOf('data:') === 0) {
return avatar
}
return process.env.VUE_APP_BASE_API + avatar
},
submitCreate() {
this.$refs.createForm.validate(valid => {
/*this.$refs.createForm.validate(valid => {
if (!valid) {
return
}
this.submitting = true
addStudent(this.createForm).then(() => {
this.$modal.msgSuccess('新增成功')
// 头像地址由子组件上传后写入 createForm.avatar,与其他学员信息一并提交
const payload = Object.assign({}, this.createForm, {
avatar: this.createForm.avatar || (this.user && this.user.avatar) || null
})
// 修改模式调用 PUT /train/student,新增模式调用 POST /train/student
const submitRequest = this.isEdit
? request({ url: '/train/student', method: 'put', data: payload })
: addStudent(payload)
submitRequest.then(() => {
this.$modal.msgSuccess(this.isEdit ? '修改成功' : '新增成功')
this.createOpen = false
this.resetCreate();
this.getList()
}).finally(() => {
this.submitting = false
})
})*/
this.$refs.createForm.validate(valid => {
if (valid) {
if (this.createForm.sId != null) {
updateStudent(this.createForm).then(response => {
this.$modal.msgSuccess('修改成功')
this.createOpen = false
this.getList()
})
} else {
addStudent(this.createForm).then(response => {
this.$modal.msgSuccess('新增成功')
this.createOpen = false
this.getList()
})
}
}
})
},
handleDetail(row) {
@@ -545,8 +674,26 @@ export default {
}
</script>
<style scoped>
<style scoped lang="scss">
.student-detail ::v-deep .el-form-item {
margin-bottom: 8px;
}
.student-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
vertical-align: middle;
background: #f5f7fa;
}
.student-avatar .image-slot {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
color: #c0c4cc;
font-size: 18px;
}
</style>