480 lines
17 KiB
Vue
480 lines
17 KiB
Vue
<template>
|
||
<div class="app-container status-change-page">
|
||
<!-- ==================== 1. 查询条件 ==================== -->
|
||
<el-card shadow="never" class="search-card">
|
||
<el-form ref="searchFormRef" :model="searchForm" label-width="90px" class="search-form">
|
||
<el-row :gutter="24">
|
||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||
<el-form-item label="编号">
|
||
<el-input v-model="searchForm.bh" placeholder="请输入编号" clearable @keyup.enter.native="handleSearch" />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||
<el-form-item label="学员编号">
|
||
<el-input v-model="searchForm.xybh" placeholder="请输入学员编号" clearable @keyup.enter.native="handleSearch" />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||
<el-form-item label="申请类型">
|
||
<el-select v-model="searchForm.sqlx" placeholder="请选择申请类型" clearable class="w-full">
|
||
<el-option v-for="item in applyTypeOptions" :key="item" :label="item" :value="item" />
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||
<el-form-item label="状态">
|
||
<el-select v-model="searchForm.zt" placeholder="请选择状态" clearable class="w-full">
|
||
<el-option v-for="(item, key) in statusMap" :key="key" :label="item.label" :value="Number(key)" />
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-row>
|
||
<el-col :span="24" class="search-actions">
|
||
<div class="search-buttons">
|
||
<el-button type="primary" @click="handleSearch">查询</el-button>
|
||
<el-button @click="handleReset">重置</el-button>
|
||
</div>
|
||
</el-col>
|
||
</el-row>
|
||
</el-form>
|
||
</el-card>
|
||
|
||
<!-- ==================== 2. 列表 ==================== -->
|
||
<el-card shadow="never" class="table-card">
|
||
<div class="table-header">
|
||
<span class="table-title">学籍异动申请列表:</span>
|
||
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新增学籍异动申请</el-button>
|
||
</div>
|
||
<el-table v-loading="loading" :data="tableData" stripe border highlight-current-row>
|
||
<el-table-column prop="bh" label="编号" min-width="140" show-overflow-tooltip />
|
||
<el-table-column prop="xybh" label="学员编号" min-width="120" show-overflow-tooltip />
|
||
<el-table-column prop="sqlx" label="申请类型" width="100" align="center" />
|
||
<el-table-column prop="sy" label="事由" min-width="140" show-overflow-tooltip />
|
||
<el-table-column prop="bz" label="备注" min-width="140" show-overflow-tooltip />
|
||
<el-table-column label="状态" width="90" align="center">
|
||
<template slot-scope="{ row }">
|
||
<el-tag :type="statusTagType(row.zt)" size="mini">{{ statusLabel(row.zt) }}</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="cjsj" label="创建时间" width="160" show-overflow-tooltip />
|
||
<el-table-column prop="xgsj" label="修改时间" width="160" show-overflow-tooltip />
|
||
<el-table-column label="操作" width="230" align="center" fixed="right">
|
||
<template slot-scope="{ row }">
|
||
<el-button type="text" size="small" icon="el-icon-upload2" @click="handleSubmit(row)">提交</el-button>
|
||
<el-button type="text" size="small" icon="el-icon-view" @click="handleDetail(row)">详情</el-button>
|
||
<el-button type="text" size="small" icon="el-icon-edit" @click="handleEdit(row)">编辑</el-button>
|
||
<el-button type="text" size="small" class="text-danger" @click="handleDelete(row)">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<el-pagination
|
||
:current-page="pageNum"
|
||
:page-size="pageSize"
|
||
:total="total"
|
||
:page-sizes="[10, 20, 50, 100]"
|
||
layout="total, sizes, prev, pager, next, jumper"
|
||
class="pagination-wrapper"
|
||
@current-change="handlePageChange"
|
||
@size-change="handleSizeChange"
|
||
/>
|
||
</el-card>
|
||
|
||
<!-- ==================== 3. 新增/编辑对话框 ==================== -->
|
||
<el-dialog
|
||
:visible="formDialogVisible"
|
||
:title="dialogTitle"
|
||
width="600px"
|
||
:close-on-click-modal="false"
|
||
@update:visible="val => formDialogVisible = val"
|
||
>
|
||
<el-form ref="formRef" :model="form" :rules="formRules" label-width="110px" class="add-form">
|
||
<el-form-item label="编号" prop="bh">
|
||
<el-input v-model="form.bh" placeholder="请输入编号" :disabled="!isAdd" />
|
||
</el-form-item>
|
||
<el-form-item label="学员编号" prop="xybh">
|
||
<el-input v-model="form.xybh" placeholder="请输入学员编号" />
|
||
</el-form-item>
|
||
<el-form-item label="申请类型" prop="sqlx">
|
||
<el-select v-model="form.sqlx" placeholder="请选择申请类型" class="w-full">
|
||
<el-option v-for="item in applyTypeOptions" :key="item" :label="item" :value="item" />
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="事由" prop="sy">
|
||
<el-input v-model="form.sy" type="textarea" :rows="3" placeholder="请输入事由" />
|
||
</el-form-item>
|
||
<el-form-item label="备注">
|
||
<el-input v-model="form.bz" type="textarea" :rows="3" placeholder="请输入备注" />
|
||
</el-form-item>
|
||
<el-form-item label="状态" prop="zt">
|
||
<el-select v-model="form.zt" placeholder="请选择状态" class="w-full">
|
||
<el-option v-for="(item, key) in statusMap" :key="key" :label="item.label" :value="Number(key)" />
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-form>
|
||
<div slot="footer">
|
||
<el-button @click="formDialogVisible = false">取消</el-button>
|
||
<el-button type="primary" :loading="formSaving" @click="handleFormSubmit">确定</el-button>
|
||
</div>
|
||
</el-dialog>
|
||
|
||
<!-- ==================== 4. 详情对话框 ==================== -->
|
||
<el-dialog title="学籍异动申请详情" :visible="detailDialogVisible" width="760px" :close-on-click-modal="false"
|
||
@update:visible="val => detailDialogVisible = val">
|
||
<div v-loading="detailLoading" class="detail-body">
|
||
<el-descriptions :column="2" border>
|
||
<el-descriptions-item label="编号">{{ detailForm.bh || '-' }}</el-descriptions-item>
|
||
<el-descriptions-item label="学员编号">{{ detailForm.xybh || '-' }}</el-descriptions-item>
|
||
<el-descriptions-item label="申请类型">{{ detailForm.sqlx || '-' }}</el-descriptions-item>
|
||
<el-descriptions-item label="状态">
|
||
<el-tag :type="statusTagType(detailForm.zt)" size="mini">{{ statusLabel(detailForm.zt) }}</el-tag>
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="事由" :span="2">{{ detailForm.sy || '-' }}</el-descriptions-item>
|
||
<el-descriptions-item label="备注" :span="2">{{ detailForm.bz || '-' }}</el-descriptions-item>
|
||
<el-descriptions-item label="创建时间">{{ detailForm.cjsj || '-' }}</el-descriptions-item>
|
||
<el-descriptions-item label="修改时间">{{ detailForm.xgsj || '-' }}</el-descriptions-item>
|
||
<el-descriptions-item label="提交时间">{{ detailForm.tjsj || '-' }}</el-descriptions-item>
|
||
<el-descriptions-item label="学员队审核意见">{{ detailForm.xydshyj || '-' }}</el-descriptions-item>
|
||
<el-descriptions-item label="学员队干部编号">{{ detailForm.xydgbbh || '-' }}</el-descriptions-item>
|
||
<el-descriptions-item label="学员队干部审核时间">{{ detailForm.xydshsj || '-' }}</el-descriptions-item>
|
||
<el-descriptions-item label="管理员账户编号">{{ detailForm.glyzhbh || '-' }}</el-descriptions-item>
|
||
<el-descriptions-item label="管理员审核意见">{{ detailForm.glyshyj || '-' }}</el-descriptions-item>
|
||
<el-descriptions-item label="管理员审核时间">{{ detailForm.glyshsj || '-' }}</el-descriptions-item>
|
||
</el-descriptions>
|
||
</div>
|
||
<div slot="footer">
|
||
<el-button @click="detailDialogVisible = false">关闭</el-button>
|
||
</div>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import {
|
||
listApplication,
|
||
getApplication,
|
||
addApplication,
|
||
updateApplication,
|
||
delApplication
|
||
} from '@/api/studentRecords/application'
|
||
|
||
export default {
|
||
name: 'StatusChangeIndex',
|
||
data() {
|
||
return {
|
||
// ==================== 申请类型选项(学籍异动) ====================
|
||
applyTypeOptions: ['休学', '复学', '退学', '转学', '留级', '转专业'],
|
||
|
||
// ==================== 状态映射:0-待审核 1-已审核 2-驳回等 ====================
|
||
statusMap: {
|
||
0: { label: '待审核', type: 'warning' },
|
||
1: { label: '已审核', type: 'success' },
|
||
2: { label: '驳回', type: 'danger' }
|
||
},
|
||
|
||
// ==================== 查询条件 ====================
|
||
searchForm: {
|
||
bh: '',
|
||
xybh: '',
|
||
sqlx: '',
|
||
zt: undefined
|
||
},
|
||
|
||
// ==================== 列表数据 ====================
|
||
loading: false,
|
||
tableData: [],
|
||
total: 0,
|
||
pageNum: 1,
|
||
pageSize: 20,
|
||
|
||
// ==================== 新增/编辑 ====================
|
||
formDialogVisible: false,
|
||
dialogTitle: '新增学籍异动申请',
|
||
isAdd: true,
|
||
formSaving: false,
|
||
form: this.createEmptyForm(),
|
||
formRules: {
|
||
bh: [{ required: true, message: '请输入编号', trigger: 'blur' }],
|
||
xybh: [{ required: true, message: '请输入学员编号', trigger: 'blur' }],
|
||
sqlx: [{ required: true, message: '请选择申请类型', trigger: 'change' }],
|
||
sy: [{ required: true, message: '请输入事由', trigger: 'blur' }],
|
||
zt: [{ required: true, message: '请选择状态', trigger: 'change' }]
|
||
},
|
||
|
||
// ==================== 详情 ====================
|
||
detailDialogVisible: false,
|
||
detailLoading: false,
|
||
detailForm: {}
|
||
}
|
||
},
|
||
mounted() {
|
||
this.fetchList()
|
||
},
|
||
methods: {
|
||
createEmptyForm() {
|
||
return {
|
||
bh: '',
|
||
xybh: '',
|
||
sqlx: '',
|
||
sy: '',
|
||
bz: '',
|
||
zt: 0
|
||
}
|
||
},
|
||
|
||
// ==================== 状态展示 ====================
|
||
statusLabel(zt) {
|
||
const item = this.statusMap[zt]
|
||
return item ? item.label : (zt !== null && zt !== undefined ? String(zt) : '-')
|
||
},
|
||
statusTagType(zt) {
|
||
const item = this.statusMap[zt]
|
||
return item ? item.type : 'info'
|
||
},
|
||
|
||
// ==================== 查询列表 ====================
|
||
fetchList() {
|
||
this.loading = true
|
||
const params = {
|
||
pageNum: this.pageNum,
|
||
pageSize: this.pageSize
|
||
}
|
||
// 等值筛选,留空不传
|
||
;['bh', 'xybh', 'sqlx'].forEach(key => {
|
||
const value = this.searchForm[key]
|
||
if (value !== '' && value !== null && value !== undefined) {
|
||
params[key] = String(value).trim()
|
||
}
|
||
})
|
||
if (this.searchForm.zt !== undefined && this.searchForm.zt !== '' && this.searchForm.zt !== null) {
|
||
params.zt = this.searchForm.zt
|
||
}
|
||
listApplication(params).then(response => {
|
||
const data = response.data || {}
|
||
this.tableData = data.records || []
|
||
this.total = data.total || 0
|
||
this.loading = false
|
||
}).catch(() => {
|
||
this.tableData = []
|
||
this.total = 0
|
||
this.loading = false
|
||
})
|
||
},
|
||
|
||
handleSearch() {
|
||
this.pageNum = 1
|
||
this.fetchList()
|
||
},
|
||
|
||
handleReset() {
|
||
this.$refs.searchFormRef.resetFields()
|
||
this.pageNum = 1
|
||
this.fetchList()
|
||
},
|
||
|
||
handlePageChange(current) {
|
||
this.pageNum = current
|
||
this.fetchList()
|
||
},
|
||
|
||
handleSizeChange(size) {
|
||
this.pageSize = size
|
||
this.pageNum = 1
|
||
this.fetchList()
|
||
},
|
||
|
||
// ==================== 新增/编辑 ====================
|
||
handleAdd() {
|
||
this.isAdd = true
|
||
this.dialogTitle = '新增学籍异动申请'
|
||
this.form = this.createEmptyForm()
|
||
this.formDialogVisible = true
|
||
this.$nextTick(() => {
|
||
this.$refs.formRef && this.$refs.formRef.clearValidate()
|
||
})
|
||
},
|
||
|
||
handleEdit(row) {
|
||
this.isAdd = false
|
||
this.dialogTitle = '编辑学籍异动申请'
|
||
this.form = this.createEmptyForm()
|
||
this.formDialogVisible = true
|
||
this.$nextTick(() => {
|
||
this.$refs.formRef && this.$refs.formRef.clearValidate()
|
||
})
|
||
getApplication(row.bh).then(response => {
|
||
const data = response.data || {}
|
||
this.form = {
|
||
bh: data.bh || '',
|
||
xybh: data.xybh || '',
|
||
sqlx: data.sqlx || '',
|
||
sy: data.sy || '',
|
||
bz: data.bz || '',
|
||
zt: data.zt !== null && data.zt !== undefined ? Number(data.zt) : 0
|
||
}
|
||
}).catch(() => {})
|
||
},
|
||
|
||
buildPayload() {
|
||
const f = this.form
|
||
const payload = {
|
||
bh: f.bh,
|
||
xybh: f.xybh,
|
||
sqlx: f.sqlx,
|
||
sy: f.sy,
|
||
zt: Number(f.zt)
|
||
}
|
||
// 备注留空则移除
|
||
if (f.bz !== '' && f.bz !== null && f.bz !== undefined) {
|
||
payload.bz = f.bz
|
||
}
|
||
return payload
|
||
},
|
||
|
||
handleFormSubmit() {
|
||
this.$refs.formRef.validate(valid => {
|
||
if (!valid) return
|
||
this.formSaving = true
|
||
const payload = this.buildPayload()
|
||
const request = this.isAdd ? addApplication(payload) : updateApplication(payload)
|
||
request.then(() => {
|
||
this.$message.success(this.isAdd ? '新增成功' : '修改成功')
|
||
this.formDialogVisible = false
|
||
this.fetchList()
|
||
}).catch(() => {
|
||
}).finally(() => {
|
||
this.formSaving = false
|
||
})
|
||
})
|
||
},
|
||
|
||
// ==================== 提交 ====================
|
||
// 无独立提交接口,通过编辑接口写入提交时间 tjsj(zt 保持原值不变)
|
||
formatNow() {
|
||
const d = new Date()
|
||
const pad = n => String(n).padStart(2, '0')
|
||
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
|
||
},
|
||
|
||
handleSubmit(row) {
|
||
this.$confirm(`确定要提交编号为「${row.bh}」的学籍异动申请吗?`, '系统提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}).then(() => {
|
||
const payload = {
|
||
bh: row.bh,
|
||
xybh: row.xybh,
|
||
sqlx: row.sqlx,
|
||
sy: row.sy,
|
||
zt: row.zt !== null && row.zt !== undefined ? Number(row.zt) : 0,
|
||
tjsj: this.formatNow()
|
||
}
|
||
if (row.bz) {
|
||
payload.bz = row.bz
|
||
}
|
||
return updateApplication(payload)
|
||
}).then(() => {
|
||
this.$message.success('提交成功')
|
||
this.fetchList()
|
||
}).catch(() => {})
|
||
},
|
||
|
||
// ==================== 删除 ====================
|
||
handleDelete(row) {
|
||
this.$confirm(`确定要删除编号为「${row.bh}」的学籍异动申请吗?`, '系统提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}).then(() => {
|
||
return delApplication(row.bh)
|
||
}).then(() => {
|
||
this.$message.success('删除成功')
|
||
this.fetchList()
|
||
}).catch(() => {})
|
||
},
|
||
|
||
// ==================== 详情 ====================
|
||
handleDetail(row) {
|
||
this.detailDialogVisible = true
|
||
this.detailLoading = true
|
||
this.detailForm = {}
|
||
getApplication(row.bh).then(response => {
|
||
this.detailForm = response.data || {}
|
||
this.detailLoading = false
|
||
}).catch(() => {
|
||
this.detailLoading = false
|
||
})
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.app-container {
|
||
padding: 20px;
|
||
}
|
||
|
||
.status-change-page {
|
||
.search-card {
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.search-form {
|
||
.w-full {
|
||
width: 100%;
|
||
}
|
||
|
||
.search-actions {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding-top: 8px;
|
||
|
||
.search-tip {
|
||
font-size: 12px;
|
||
color: #909399;
|
||
}
|
||
|
||
.search-buttons {
|
||
display: flex;
|
||
gap: 12px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.table-card {
|
||
.table-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
margin-bottom: 16px;
|
||
|
||
.table-title {
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
color: #303133;
|
||
}
|
||
}
|
||
|
||
.pagination-wrapper {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
margin-top: 16px;
|
||
}
|
||
}
|
||
|
||
.add-form {
|
||
max-height: 60vh;
|
||
overflow-y: auto;
|
||
padding-right: 4px;
|
||
}
|
||
|
||
.text-danger {
|
||
color: #f56c6c;
|
||
padding: 0;
|
||
}
|
||
}
|
||
</style>
|