Merge branch 'main' of https://gitea.fengyingkj.top/zhaichao/education
This commit is contained in:
@@ -0,0 +1,110 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 课程教学运行管理(CourseRunningController /course-running)
|
||||||
|
// 接口依据:course-running 控制器(前端 baseURL 为 /api,此处不重复 /api 前缀)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询教学实施计划课次列表
|
||||||
|
* GET /course-running/plan/list
|
||||||
|
* 查询参数(TeachingPlanQueryDTO):
|
||||||
|
* sskcbh 实施_课程编号、nd 年度、jxff 教学方法、
|
||||||
|
* rqStart 日期范围开始、rqEnd 日期范围结束(均传 ISO 格式,如 2026-08-23T00:00:00)、
|
||||||
|
* txzt 填写状态(0-未填写 1-已填写 2-已提交)、pageNum、pageSize
|
||||||
|
* 返回:PageResult<TeachingPlanLessonVO>(records/total)
|
||||||
|
*/
|
||||||
|
export function listTeachingPlan(params) {
|
||||||
|
return request({
|
||||||
|
url: '/course-running/plan/list',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 调课申请管理 /course-running/adjust ====================
|
||||||
|
// 接口依据:CourseRunningController(类上 @RequestMapping("/course-running"),前端 baseURL 为 /api,此处不重复 /api 前缀)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询调课申请列表
|
||||||
|
* GET /course-running/adjust/list
|
||||||
|
* 查询参数(ScheduleAdjustQueryDTO):sskcbbh 课次编号、sqjybh 申请教员编号、nd 年度、
|
||||||
|
* jyspzzt 教研室审批状态、jyscszt 教研室查收状态、sczt 删除状态、
|
||||||
|
* cjsjStart/cjsjEnd 申请日期范围(ISO 格式)、pageNum、pageSize
|
||||||
|
* 返回:PageResult<ScheduleAdjustApplyVO>(records/total)
|
||||||
|
*/
|
||||||
|
export function listScheduleAdjust(params) {
|
||||||
|
return request({
|
||||||
|
url: '/course-running/adjust/list',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询当前教员可供调课的课次
|
||||||
|
* GET /course-running/adjust/lessons
|
||||||
|
* 查询参数:nd 年度(可选)
|
||||||
|
* 返回:List<AdjustableLessonVO>,包含提交所需的课次主字段及教室、教员、学员队、保障明细。
|
||||||
|
*/
|
||||||
|
export function listAdjustableLessons(params) {
|
||||||
|
return request({
|
||||||
|
url: '/course-running/adjust/lessons',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询调课申请详情
|
||||||
|
* GET /course-running/adjust/detail
|
||||||
|
* @param ssdksqbh 调课申请编号
|
||||||
|
* 返回:ScheduleAdjustDetailVO
|
||||||
|
*/
|
||||||
|
export function getScheduleAdjustDetail(ssdksqbh) {
|
||||||
|
return request({
|
||||||
|
url: '/course-running/adjust/detail',
|
||||||
|
method: 'get',
|
||||||
|
params: { ssdksqbh }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交调课申请
|
||||||
|
* POST /course-running/adjust/submit
|
||||||
|
* 请求体(ScheduleAdjustApplyDTO)核心字段:sskcbbh 课次编号、sy 调课事由、rq 调课后新日期、
|
||||||
|
* jc 调课后新节次、nd 年度;sqjybh/xydrwbh/kbh/kcbbh/xjsbh 为可选关联字段,
|
||||||
|
* roomList/teacherList/teamList/supportList 为调整后的关联明细。
|
||||||
|
*/
|
||||||
|
export function submitScheduleAdjust(data) {
|
||||||
|
return request({
|
||||||
|
url: '/course-running/adjust/submit',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 教研室审批调课申请
|
||||||
|
* POST /course-running/adjust/audit/jys
|
||||||
|
* 请求体(ScheduleAdjustAuditDTO):ssdksqbh(必填)、spzt(1同意/2发回/3拒绝)、
|
||||||
|
* fhyj(审批意见,发回时填写)、sprbh(审批人编号,不传时取当前登录人;点审批即已查收)
|
||||||
|
*/
|
||||||
|
export function auditByTeachingOffice(data) {
|
||||||
|
return request({
|
||||||
|
url: '/course-running/adjust/audit/jys',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销调课申请
|
||||||
|
* DELETE /course-running/adjust/cancel
|
||||||
|
* @param params { ssdksqbh, sqjybh }
|
||||||
|
*/
|
||||||
|
export function cancelScheduleAdjust(params) {
|
||||||
|
return request({
|
||||||
|
url: '/course-running/adjust/cancel',
|
||||||
|
method: 'delete',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ import request from '@/utils/request'
|
|||||||
/**
|
/**
|
||||||
* 今日课表
|
* 今日课表
|
||||||
* GET /kcb/today/list
|
* GET /kcb/today/list
|
||||||
* @param params TimetableQuery:nd、xydbh(均可选)
|
* @param params offset 日期偏移量、rq 基准日期(yyyy-MM-dd)
|
||||||
* 返回:今日课表记录(实体字段 bh/sksj/kc/zrdw/bc/jy/cd/jxnrxff/bz)
|
* 返回:今日课表记录(实体字段 bh/sksj/kc/zrdw/bc/jy/cd/jxnrxff/bz)
|
||||||
*/
|
*/
|
||||||
export function listToday(data) {
|
export function listToday(data) {
|
||||||
@@ -21,7 +21,7 @@ export function listToday(data) {
|
|||||||
/**
|
/**
|
||||||
* 本周课表
|
* 本周课表
|
||||||
* GET /kcb/week/list
|
* GET /kcb/week/list
|
||||||
* @param params TimetableQuery:nd、xydbh(均可选)
|
* @param params offset 周偏移量、rq 基准日期(yyyy-MM-dd)
|
||||||
* 返回:本周课表记录
|
* 返回:本周课表记录
|
||||||
*/
|
*/
|
||||||
export function listWeek(data) {
|
export function listWeek(data) {
|
||||||
|
|||||||
@@ -0,0 +1,498 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container student-info-page">
|
||||||
|
<!-- ==================== 1. 查询条件区域 ==================== -->
|
||||||
|
<el-card shadow="never" class="search-card">
|
||||||
|
<el-form :model="searchForm" label-width="110px" class="search-form">
|
||||||
|
<el-row :gutter="24">
|
||||||
|
<!-- 左栏 -->
|
||||||
|
<el-col :xs="24" :md="12">
|
||||||
|
<el-form-item label="学号">
|
||||||
|
<el-input v-model="searchForm.xh" placeholder="请输入学号" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="姓名">
|
||||||
|
<el-input v-model="searchForm.xm" placeholder="请输入姓名" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="性别">
|
||||||
|
<el-select v-model="searchForm.xb" placeholder="请选择性别" clearable class="full-width">
|
||||||
|
<el-option label="男" value="男" />
|
||||||
|
<el-option label="女" value="女" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="证件号码">
|
||||||
|
<el-input v-model="searchForm.zjhm" placeholder="请输入证件号码" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="政治面貌">
|
||||||
|
<el-input v-model="searchForm.zzmm" placeholder="请输入政治面貌" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="民族">
|
||||||
|
<el-input v-model="searchForm.mz" placeholder="请输入民族" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="籍贯">
|
||||||
|
<el-input v-model="searchForm.jg" placeholder="请输入籍贯" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学位">
|
||||||
|
<el-input v-model="searchForm.xw" placeholder="请输入学位" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<!-- 右栏 -->
|
||||||
|
<el-col :xs="24" :md="12">
|
||||||
|
<el-form-item label="原部职别">
|
||||||
|
<el-input v-model="searchForm.ybzb" placeholder="请输入原部职别" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="身份证号">
|
||||||
|
<el-input v-model="searchForm.sfzh" placeholder="请输入身份证号" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="文化程度">
|
||||||
|
<el-input v-model="searchForm.whcd" placeholder="请输入文化程度" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="本科毕业院校">
|
||||||
|
<el-input v-model="searchForm.bkbyyx" placeholder="请输入本科毕业院校" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="标签">
|
||||||
|
<el-input v-model="searchForm.bq" placeholder="请输入标签" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="联系电话">
|
||||||
|
<el-input v-model="searchForm.lxdh" placeholder="请输入联系电话" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="通信地址">
|
||||||
|
<el-input v-model="searchForm.txdz" placeholder="请输入通信地址" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<div class="search-actions">
|
||||||
|
<el-button type="primary" icon="el-icon-search" @click="handleSearch">查询</el-button>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- ==================== 2. 数据表格区域 ==================== -->
|
||||||
|
<el-card shadow="never" class="table-card">
|
||||||
|
<div class="list-header">
|
||||||
|
<div class="list-title">学员信息列表</div>
|
||||||
|
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新增学员</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table v-loading="loading" :data="tableData" stripe border>
|
||||||
|
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||||
|
<el-table-column prop="xh" label="学号" width="55" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="xm" label="姓名" width="55" />
|
||||||
|
<el-table-column prop="xb" label="性别" width="55" align="center" />
|
||||||
|
<el-table-column prop="nj" label="年级" width="55" align="center" />
|
||||||
|
<el-table-column prop="zy" label="专业" width="55" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="db" label="队别" width="55" align="center" />
|
||||||
|
<el-table-column prop="bc" label="班次" width="55" align="center" />
|
||||||
|
<el-table-column prop="pxlx" label="培训类型" width="85" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="pxcc" label="培训层次" width="85" align="center" />
|
||||||
|
<el-table-column prop="zzmm" label="政治面貌" width="85" align="center" />
|
||||||
|
<el-table-column prop="mz" label="民族" width="55" align="center" />
|
||||||
|
<el-table-column prop="jg" label="籍贯" width="55" align="center" />
|
||||||
|
<el-table-column prop="xw" label="学位" width="55" align="center" />
|
||||||
|
<el-table-column prop="zczt" label="注册状态" width="85" align="center" />
|
||||||
|
<el-table-column prop="xjyd" label="学籍异动状态" width="110" align="center" />
|
||||||
|
<el-table-column prop="ksqk" label="考试情况" width="85" align="center" />
|
||||||
|
<el-table-column prop="bjgm" label="不及格门数" width="110" align="center" />
|
||||||
|
<el-table-column prop="gljg" label="管理机构" width="85" align="center" />
|
||||||
|
<el-table-column label="操作" align="center" fixed="right">
|
||||||
|
<template slot-scope="{ row }">
|
||||||
|
<el-button type="text" class="text-primary" @click="handleEdit(row)">编辑</el-button>
|
||||||
|
<el-button type="text" class="text-success" @click="handleGrades(row)">成绩</el-button>
|
||||||
|
<el-button type="text" class="danger-text" @click="handleDelete(row)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div class="pagination">
|
||||||
|
<el-pagination
|
||||||
|
:current-page="pagination.pageNum"
|
||||||
|
:page-size="pagination.pageSize"
|
||||||
|
:total="pagination.total"
|
||||||
|
:page-sizes="[10, 20, 50, 100]"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
background
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handlePageChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 新增/编辑弹窗 -->
|
||||||
|
<el-dialog
|
||||||
|
:visible="dialogVisible"
|
||||||
|
:title="dialogTitle"
|
||||||
|
width="780px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
@update:visible="val => dialogVisible = val"
|
||||||
|
>
|
||||||
|
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="120px">
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12"><el-form-item label="编号" prop="bh"><el-input v-model="formData.bh" placeholder="请输入编号" /></el-form-item></el-col>
|
||||||
|
<el-col :span="12"><el-form-item label="学号" prop="xh"><el-input v-model="formData.xh" placeholder="请输入学号" /></el-form-item></el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12"><el-form-item label="姓名" prop="xm"><el-input v-model="formData.xm" placeholder="请输入姓名" /></el-form-item></el-col>
|
||||||
|
<el-col :span="12"><el-form-item label="性别" prop="xb"><el-select v-model="formData.xb" placeholder="请选择" class="full-width"><el-option label="男" value="1" /><el-option label="女" value="0" /></el-select></el-form-item></el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12"><el-form-item label="出生日期" prop="csrq"><el-date-picker v-model="formData.csrq" type="date" placeholder="请选择" value-format="yyyy-MM-dd" class="full-width" /></el-form-item></el-col>
|
||||||
|
<el-col :span="12"><el-form-item label="民族" prop="mz"><el-input v-model="formData.mz" placeholder="请输入民族" /></el-form-item></el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12"><el-form-item label="籍贯" prop="jg"><el-input v-model="formData.jg" placeholder="请输入籍贯" /></el-form-item></el-col>
|
||||||
|
<el-col :span="12"><el-form-item label="政治面貌" prop="zzmm"><el-input v-model="formData.zzmm" placeholder="请输入政治面貌" /></el-form-item></el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12"><el-form-item label="文化程度" prop="whcd"><el-input v-model="formData.whcd" placeholder="请输入文化程度" /></el-form-item></el-col>
|
||||||
|
<el-col :span="12"><el-form-item label="学员类别" prop="xylb"><el-input v-model="formData.xylb" placeholder="请输入学员类别" /></el-form-item></el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12"><el-form-item label="学员队期编号" prop="xydqbh"><el-input v-model="formData.xydqbh" placeholder="请输入学员队期编号" /></el-form-item></el-col>
|
||||||
|
<el-col :span="12"><el-form-item label="证件号码" prop="zjhm"><el-input v-model="formData.zjhm" placeholder="请输入证件号码" /></el-form-item></el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12"><el-form-item label="所属军区" prop="ssjq"><el-input v-model="formData.ssjq" placeholder="请输入所属军区" /></el-form-item></el-col>
|
||||||
|
<el-col :span="12"><el-form-item label="当前班次编号" prop="dqbzbh"><el-input v-model="formData.dqbzbh" placeholder="请输入当前班次编号" /></el-form-item></el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12"><el-form-item label="军人证件类型" prop="jrzjlx"><el-input v-model="formData.jrzjlx" placeholder="请输入军人证件类型" /></el-form-item></el-col>
|
||||||
|
<el-col :span="12"><el-form-item label="退学状态" prop="txzt"><el-input v-model="formData.txzt" placeholder="请输入退学状态" /></el-form-item></el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="8"><el-form-item label="国防生" prop="gfs"><el-select v-model="formData.gfs" placeholder="请选择" class="full-width"><el-option label="是" value="1" /><el-option label="否" value="0" /></el-select></el-form-item></el-col>
|
||||||
|
<el-col :span="8"><el-form-item label="留级状态" prop="ljzt"><el-input v-model="formData.ljzt" placeholder="请输入" /></el-form-item></el-col>
|
||||||
|
<el-col :span="8"><el-form-item label="分班状态" prop="fbzt"><el-input v-model="formData.fbzt" placeholder="请输入" /></el-form-item></el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="8"><el-form-item label="允许查看成绩" prop="yxckcj"><el-select v-model="formData.yxckcj" placeholder="请选择" class="full-width"><el-option label="是" value="1" /><el-option label="否" value="0" /></el-select></el-form-item></el-col>
|
||||||
|
<el-col :span="8"><el-form-item label="已注册" prop="yzc"><el-select v-model="formData.yzc" placeholder="请选择" class="full-width"><el-option label="是" value="1" /><el-option label="否" value="0" /></el-select></el-form-item></el-col>
|
||||||
|
<el-col :span="8" />
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12"><el-form-item label="联系电话" prop="lxdh"><el-input v-model="formData.lxdh" placeholder="请输入联系电话" /></el-form-item></el-col>
|
||||||
|
<el-col :span="12"><el-form-item label="通讯地址" prop="txdz"><el-input v-model="formData.txdz" placeholder="请输入通讯地址" /></el-form-item></el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="24"><el-form-item label="备注" prop="bz"><el-input v-model="formData.bz" type="textarea" :rows="2" placeholder="请输入备注" /></el-form-item></el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer">
|
||||||
|
<el-button @click="dialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" :loading="submitting" @click="handleSubmit">确定</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 成绩弹窗 -->
|
||||||
|
<el-dialog
|
||||||
|
:visible="gradesVisible"
|
||||||
|
title="学员成绩"
|
||||||
|
width="600px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
@update:visible="val => gradesVisible = val"
|
||||||
|
>
|
||||||
|
<p><strong>学员:</strong>{{ gradesStudent }}</p>
|
||||||
|
<el-tabs v-model="gradesTab">
|
||||||
|
<el-tab-pane label="成绩" name="grades">
|
||||||
|
<div v-loading="gradesLoading">
|
||||||
|
<pre v-if="gradesData">{{ gradesData }}</pre>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="进程成绩" name="process">
|
||||||
|
<div v-loading="gradesLoading">
|
||||||
|
<pre v-if="processGradesData">{{ processGradesData }}</pre>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
<div slot="footer">
|
||||||
|
<el-button type="primary" @click="handleExportGrades">导出成绩</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
listStudentRecord,
|
||||||
|
getStudentRecord,
|
||||||
|
addStudentRecord,
|
||||||
|
updateStudentRecord,
|
||||||
|
delStudentRecord
|
||||||
|
} from "@/api/studentRecords/studentRecords"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'StudentInfoIndex',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// ==================== 查询条件 ====================
|
||||||
|
// 仅保留后端 XYXX 实体支持的字段:/student-records/list 会按实体字段动态构建查询条件
|
||||||
|
searchForm: {
|
||||||
|
xh: '', xm: '', xb: '', zjhm: '', zzmm: '', mz: '', jg: '', xw: '',
|
||||||
|
ybzb: '', sfzh: '', whcd: '', bkbyyx: '', bq: '', lxdh: '', txdz: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 数据表格 ====================
|
||||||
|
loading: false,
|
||||||
|
tableData: [],
|
||||||
|
pagination: { pageNum: 1, pageSize: 20, total: 0 },
|
||||||
|
|
||||||
|
// ==================== 新增/编辑弹窗 ====================
|
||||||
|
dialogVisible: false,
|
||||||
|
dialogTitle: '新增学员',
|
||||||
|
submitting: false,
|
||||||
|
formData: this.createEmptyForm(),
|
||||||
|
formRules: {
|
||||||
|
bh: [{ required: true, message: '请输入编号', trigger: 'blur' }],
|
||||||
|
xh: [{ required: true, message: '请输入学号', trigger: 'blur' }],
|
||||||
|
xm: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
|
||||||
|
xydqbh: [{ required: true, message: '请输入学员队期编号', trigger: 'blur' }],
|
||||||
|
zjhm: [{ required: true, message: '请输入证件号码', trigger: 'blur' }],
|
||||||
|
zzmm: [{ required: true, message: '请输入政治面貌', trigger: 'blur' }],
|
||||||
|
xb: [{ required: true, message: '请选择性别', trigger: 'change' }],
|
||||||
|
csrq: [{ required: true, message: '请选择出生日期', trigger: 'change' }],
|
||||||
|
mz: [{ required: true, message: '请输入民族', trigger: 'blur' }],
|
||||||
|
jg: [{ required: true, message: '请输入籍贯', trigger: 'blur' }],
|
||||||
|
whcd: [{ required: true, message: '请输入文化程度', trigger: 'blur' }],
|
||||||
|
xylb: [{ required: true, message: '请输入学员类别', trigger: 'blur' }],
|
||||||
|
ssjq: [{ required: true, message: '请输入所属军区', trigger: 'blur' }],
|
||||||
|
gfs: [{ required: true, message: '请选择国防生', trigger: 'change' }],
|
||||||
|
txzt: [{ required: true, message: '请输入退学状态', trigger: 'blur' }],
|
||||||
|
ljzt: [{ required: true, message: '请输入留级状态', trigger: 'blur' }],
|
||||||
|
fbzt: [{ required: true, message: '请输入分班状态', trigger: 'blur' }],
|
||||||
|
yxckcj: [{ required: true, message: '请选择允许查看成绩', trigger: 'change' }],
|
||||||
|
dqbzbh: [{ required: true, message: '请输入当前班次编号', trigger: 'blur' }],
|
||||||
|
yzc: [{ required: true, message: '请选择已注册', trigger: 'change' }],
|
||||||
|
jrzjlx: [{ required: true, message: '请输入军人证件类型', trigger: 'blur' }]
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 成绩弹窗 ====================
|
||||||
|
gradesVisible: false,
|
||||||
|
gradesTab: 'grades',
|
||||||
|
gradesData: null,
|
||||||
|
processGradesData: null,
|
||||||
|
gradesStudent: '',
|
||||||
|
currentBh: '',
|
||||||
|
gradesLoading: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.loadData()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 创建空白表单 */
|
||||||
|
createEmptyForm() {
|
||||||
|
return {
|
||||||
|
bh: '', xh: '', xm: '', xydqbh: '', zjhm: '', zzmm: '', xb: '', csrq: '', mz: '', jg: '',
|
||||||
|
whcd: '', xylb: '', ssjq: '', gfs: '', txzt: '', ljzt: '', fbzt: '', yxckcj: '', dqbzbh: '', yzc: '',
|
||||||
|
jrzjlx: '', sfzh: '', lxdh: '', txdz: '', bz: '', dtsj: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 列表加载 ====================
|
||||||
|
loadData() {
|
||||||
|
this.loading = true
|
||||||
|
const params = {
|
||||||
|
pageNum: this.pagination.pageNum,
|
||||||
|
pageSize: this.pagination.pageSize
|
||||||
|
}
|
||||||
|
this.buildQueryParams(params)
|
||||||
|
listStudentRecord(params).then(res => {
|
||||||
|
const data = res.data || {}
|
||||||
|
this.tableData = data.records || []
|
||||||
|
this.pagination.total = data.total || 0
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.tableData = []
|
||||||
|
this.pagination.total = 0
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 组装查询参数:仅传后端 XYXX 实体支持的字符串字段,空值忽略 */
|
||||||
|
buildQueryParams(params) {
|
||||||
|
const textFields = ['xh', 'xm', 'zjhm', 'zzmm', 'mz', 'jg', 'xw', 'ybzb', 'sfzh', 'whcd', 'bkbyyx', 'bq', 'lxdh', 'txdz']
|
||||||
|
textFields.forEach(key => {
|
||||||
|
const v = this.searchForm[key]
|
||||||
|
if (v !== '' && v !== null && v !== undefined) params[key] = v.trim()
|
||||||
|
})
|
||||||
|
if (this.searchForm.xb) params.xb = this.searchForm.xb
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 查询/分页 ====================
|
||||||
|
handleSearch() {
|
||||||
|
this.pagination.pageNum = 1
|
||||||
|
this.loadData()
|
||||||
|
},
|
||||||
|
handlePageChange(page) {
|
||||||
|
this.pagination.pageNum = page
|
||||||
|
this.loadData()
|
||||||
|
},
|
||||||
|
handleSizeChange(size) {
|
||||||
|
this.pagination.pageSize = size
|
||||||
|
this.pagination.pageNum = 1
|
||||||
|
this.loadData()
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 新增/编辑弹窗 ====================
|
||||||
|
resetForm() {
|
||||||
|
Object.assign(this.formData, this.createEmptyForm())
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.formRef) {
|
||||||
|
this.$refs.formRef.clearValidate()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
handleAdd() {
|
||||||
|
this.dialogTitle = '新增学员'
|
||||||
|
this.resetForm()
|
||||||
|
this.dialogVisible = true
|
||||||
|
},
|
||||||
|
|
||||||
|
handleEdit(row) {
|
||||||
|
this.dialogTitle = '编辑学员'
|
||||||
|
this.resetForm()
|
||||||
|
if (!row.bh) {
|
||||||
|
Object.assign(this.formData, this.createEmptyForm(), row)
|
||||||
|
this.dialogVisible = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
getStudentRecord(row.bh).then(res => {
|
||||||
|
const data = res.data || {}
|
||||||
|
Object.assign(this.formData, this.createEmptyForm(), data)
|
||||||
|
this.dialogVisible = true
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 新增/编辑提交 ====================
|
||||||
|
handleSubmit() {
|
||||||
|
this.$refs.formRef.validate(valid => {
|
||||||
|
if (!valid) return
|
||||||
|
this.submitting = true
|
||||||
|
const isAdd = this.dialogTitle === '新增学员'
|
||||||
|
const payload = { ...this.formData }
|
||||||
|
const request = isAdd ? addStudentRecord(payload) : updateStudentRecord(payload)
|
||||||
|
request.then(() => {
|
||||||
|
this.$message.success(isAdd ? '新增成功' : '编辑成功')
|
||||||
|
this.dialogVisible = false
|
||||||
|
this.loadData()
|
||||||
|
}).catch(() => {
|
||||||
|
}).finally(() => {
|
||||||
|
this.submitting = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 删除 ====================
|
||||||
|
handleDelete(row) {
|
||||||
|
this.$confirm(`确定要删除"${row.xm}"吗?`, '删除确认', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
return delStudentRecord(row.bh)
|
||||||
|
}).then(() => {
|
||||||
|
this.$message.success('删除成功')
|
||||||
|
this.loadData()
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 成绩弹窗 ====================
|
||||||
|
// TODO: 后端接口未提供,成绩数据为前端模拟;接口就绪后替换为 getStudentGrades / getStudentProcessGrades
|
||||||
|
handleGrades(row) {
|
||||||
|
this.gradesStudent = row.xm || ''
|
||||||
|
this.currentBh = row.bh || ''
|
||||||
|
this.gradesData = null
|
||||||
|
this.processGradesData = null
|
||||||
|
this.gradesTab = 'grades'
|
||||||
|
this.gradesVisible = true
|
||||||
|
this.gradesLoading = true
|
||||||
|
setTimeout(() => {
|
||||||
|
this.gradesData = { 学员: row.xm, 学号: row.xh, 课程: '通信原理', 成绩: 92, 学分: 3.0 }
|
||||||
|
this.processGradesData = { 进程成绩: [{ 名称: '平时成绩', 得分: 95 }, { 名称: '期末成绩', 得分: 88 }] }
|
||||||
|
this.gradesLoading = false
|
||||||
|
}, 300)
|
||||||
|
},
|
||||||
|
|
||||||
|
// TODO: 后端接口未提供,导出为前端模拟;接口就绪后替换为 exportStudentGrades
|
||||||
|
handleExportGrades() {
|
||||||
|
this.$message.success(`已导出学员${this.gradesStudent}成绩(前端模拟)`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.student-info-page {
|
||||||
|
.search-card {
|
||||||
|
.search-form {
|
||||||
|
.range-control {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.el-input {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-sep {
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-tip {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #f56c6c;
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding-top: 12px;
|
||||||
|
border-top: 1px solid #ebeef5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-card {
|
||||||
|
.list-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.list-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-primary {
|
||||||
|
color: #409eff;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-success {
|
||||||
|
color: #67c23a;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.danger-text {
|
||||||
|
color: #f56c6c;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.full-width {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,541 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container warning-condition-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="8" :xl="8">
|
||||||
|
<el-form-item label="名称">
|
||||||
|
<el-input v-model="searchForm.mc" placeholder="请输入名称" clearable @keyup.enter.native="handleSearch" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
|
||||||
|
<el-form-item label="培训类型">
|
||||||
|
<el-input v-model="searchForm.pxlx" placeholder="请输入培训类型" clearable @keyup.enter.native="handleSearch" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
|
||||||
|
<el-form-item label="培训层次">
|
||||||
|
<el-input v-model="searchForm.pxcc" placeholder="请输入培训层次" clearable @keyup.enter.native="handleSearch" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
|
||||||
|
<el-form-item label="停用">
|
||||||
|
<el-radio-group v-model="searchForm.ty">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row class="search-actions-row">
|
||||||
|
<el-col :span="24" class="search-actions">
|
||||||
|
<el-button type="primary" icon="el-icon-search" @click="handleSearch">查询</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
|
||||||
|
</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>
|
||||||
|
<div class="table-actions">
|
||||||
|
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新增预警条件</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-table v-loading="loading" :data="tableData" stripe border highlight-current-row>
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="bh" label="编号" width="100" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="mc" label="名称" min-width="140" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="pxlx" label="培训类型" width="120" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="pxcc" label="培训层次" width="120" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="bb" label="版本" width="100" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="xgsj" label="修改时间" width="170" show-overflow-tooltip />
|
||||||
|
<el-table-column label="停用" width="80" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag
|
||||||
|
:type="scope.row.ty === 1 || scope.row.ty === true ? 'danger' : 'success'"
|
||||||
|
class="ty-tag"
|
||||||
|
@click.native="handleToggleDisable(scope.row, scope.row.ty === 1 || scope.row.ty === true ? 0 : 1)"
|
||||||
|
>
|
||||||
|
{{ scope.row.ty === 1 || scope.row.ty === true ? '是' : '否' }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button type="text" size="small" icon="el-icon-view" @click="handleView(scope.row)">详情</el-button>
|
||||||
|
<el-button type="text" size="small" icon="el-icon-edit" @click="handleEdit(scope.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
|
||||||
|
:title="formTitle"
|
||||||
|
:visible.sync="formDialogVisible"
|
||||||
|
width="900px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-form ref="formRef" :model="form" :rules="formRules" label-width="130px" class="form-dialog-form">
|
||||||
|
<el-divider content-position="left">基本信息</el-divider>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="名称" prop="mc">
|
||||||
|
<el-input v-model="form.mc" placeholder="请输入名称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="培训类型" prop="pxlx">
|
||||||
|
<el-input v-model="form.pxlx" placeholder="请输入培训类型" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="培训层次" prop="pxcc">
|
||||||
|
<el-input v-model="form.pxcc" placeholder="请输入培训层次" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="版本" prop="bb">
|
||||||
|
<el-input v-model="form.bb" placeholder="请输入版本" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="停用" prop="ty">
|
||||||
|
<el-switch v-model="form.ty" :active-value="1" :inactive-value="0" active-text="是" inactive-text="否" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="修改时间" prop="xgsj">
|
||||||
|
<el-date-picker v-model="form.xgsj" type="datetime" placeholder="请选择修改时间" value-format="yyyy-MM-dd HH:mm:ss" style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-divider content-position="left">当前学期门数限制</el-divider>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="考试不及格门数下限">
|
||||||
|
<el-input-number v-model="form.dqxqksbjgmsxx" :min="0" :max="999" controls-position="right" style="width: 100%" placeholder="请输入考试不及格门数下限" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="考试不及格门数上限">
|
||||||
|
<el-input-number v-model="form.dqxqksbjgmssx" :min="0" :max="999" controls-position="right" style="width: 100%" placeholder="请输入考试不及格门数上限" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="考查不及格门数下限">
|
||||||
|
<el-input-number v-model="form.dqxqkcbjgmsxx" :min="0" :max="999" controls-position="right" style="width: 100%" placeholder="请输入考查不及格门数下限" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="考查不及格门数上限">
|
||||||
|
<el-input-number v-model="form.dqxqkcbjgmssx" :min="0" :max="999" controls-position="right" style="width: 100%" placeholder="请输入考查不及格门数上限" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="不及格门数下限">
|
||||||
|
<el-input-number v-model="form.dqxqbjgmsxx" :min="0" :max="999" controls-position="right" style="width: 100%" placeholder="请输入不及格门数下限" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="不及格门数上限">
|
||||||
|
<el-input-number v-model="form.dqxqbjgmssx" :min="0" :max="999" controls-position="right" style="width: 100%" placeholder="请输入不及格门数上限" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-divider content-position="left">全部门数限制</el-divider>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="考试不及格门数下限">
|
||||||
|
<el-input-number v-model="form.qbksbjgmsxx" :min="0" :max="999" controls-position="right" style="width: 100%" placeholder="请输入考试不及格门数下限" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="考试不及格门数上限">
|
||||||
|
<el-input-number v-model="form.qbksbjgmssx" :min="0" :max="999" controls-position="right" style="width: 100%" placeholder="请输入考试不及格门数上限" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="考查不及格门数下限">
|
||||||
|
<el-input-number v-model="form.qbkcbjgmsxx" :min="0" :max="999" controls-position="right" style="width: 100%" placeholder="请输入考查不及格门数下限" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="考查不及格门数上限">
|
||||||
|
<el-input-number v-model="form.qbkcbjgmssx" :min="0" :max="999" controls-position="right" style="width: 100%" placeholder="请输入考查不及格门数上限" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="不及格门数下限">
|
||||||
|
<el-input-number v-model="form.qbbjgmsxx" :min="0" :max="999" controls-position="right" style="width: 100%" placeholder="请输入不及格门数下限" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="不及格门数上限">
|
||||||
|
<el-input-number v-model="form.qbbjgmssx" :min="0" :max="999" controls-position="right" style="width: 100%" placeholder="请输入不及格门数上限" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-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.sync="viewDialogVisible" width="800px" :close-on-click-modal="false">
|
||||||
|
<div v-loading="viewLoading" class="detail-body">
|
||||||
|
<el-descriptions :column="2" border>
|
||||||
|
<el-descriptions-item label="编号">{{ viewForm.bh || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="名称">{{ viewForm.mc || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="培训类型">{{ viewForm.pxlx || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="培训层次">{{ viewForm.pxcc || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="版本">{{ viewForm.bb || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="修改时间">{{ viewForm.xgsj || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="当前学期考试不及格门数下限">{{ formatValue(viewForm.dqxqksbjgmsxx) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="当前学期考试不及格门数上限">{{ formatValue(viewForm.dqxqksbjgmssx) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="当前学期考查不及格门数下限">{{ formatValue(viewForm.dqxqkcbjgmsxx) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="当前学期考查不及格门数上限">{{ formatValue(viewForm.dqxqkcbjgmssx) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="当前学期不及格门数下限">{{ formatValue(viewForm.dqxqbjgmsxx) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="当前学期不及格门数上限">{{ formatValue(viewForm.dqxqbjgmssx) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="全部考试不及格门数下限">{{ formatValue(viewForm.qbksbjgmsxx) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="全部考试不及格门数上限">{{ formatValue(viewForm.qbksbjgmssx) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="全部考查不及格门数下限">{{ formatValue(viewForm.qbkcbjgmsxx) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="全部考查不及格门数上限">{{ formatValue(viewForm.qbkcbjgmssx) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="全部不及格门数下限">{{ formatValue(viewForm.qbbjgmsxx) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="全部不及格门数上限">{{ formatValue(viewForm.qbbjgmssx) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="停用">
|
||||||
|
<el-tag :type="viewForm.ty === 1 || viewForm.ty === true ? 'danger' : 'success'" size="mini">
|
||||||
|
{{ viewForm.ty === 1 || viewForm.ty === true ? '是' : '否' }}
|
||||||
|
</el-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</div>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="viewDialogVisible = false">关 闭</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
listWarningCondition,
|
||||||
|
getWarningCondition,
|
||||||
|
addWarningCondition,
|
||||||
|
updateWarningCondition
|
||||||
|
} from "@/api/studentRecords/warningCondition"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "WarningCondition",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// ==================== 查询条件 ====================
|
||||||
|
searchForm: {
|
||||||
|
mc: '',
|
||||||
|
pxlx: '',
|
||||||
|
pxcc: '',
|
||||||
|
ty: 0
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 列表数据 ====================
|
||||||
|
loading: false,
|
||||||
|
tableData: [],
|
||||||
|
total: 0,
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
|
||||||
|
// ==================== 新增/编辑 ====================
|
||||||
|
formDialogVisible: false,
|
||||||
|
formTitle: '新增预警条件',
|
||||||
|
isAdd: true,
|
||||||
|
formSaving: false,
|
||||||
|
form: this.createEmptyForm(),
|
||||||
|
formRules: {
|
||||||
|
mc: [{ required: true, message: "名称不能为空", trigger: "blur" }],
|
||||||
|
ty: [{ required: true, message: "停用不能为空", trigger: "change" }],
|
||||||
|
bb: [{ required: true, message: "版本不能为空", trigger: "blur" }],
|
||||||
|
xgsj: [{ required: true, message: "修改时间不能为空", trigger: "change" }]
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 详情 ====================
|
||||||
|
viewDialogVisible: false,
|
||||||
|
viewLoading: false,
|
||||||
|
viewForm: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.fetchList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 创建空表单 */
|
||||||
|
createEmptyForm() {
|
||||||
|
return {
|
||||||
|
mc: '',
|
||||||
|
pxlx: '',
|
||||||
|
pxcc: '',
|
||||||
|
dqxqksbjgmssx: undefined,
|
||||||
|
dqxqksbjgmsxx: undefined,
|
||||||
|
dqxqkcbjgmssx: undefined,
|
||||||
|
dqxqkcbjgmsxx: undefined,
|
||||||
|
dqxqbjgmssx: undefined,
|
||||||
|
dqxqbjgmsxx: undefined,
|
||||||
|
qbksbjgmssx: undefined,
|
||||||
|
qbksbjgmsxx: undefined,
|
||||||
|
qbkcbjgmssx: undefined,
|
||||||
|
qbkcbjgmsxx: undefined,
|
||||||
|
qbbjgmssx: undefined,
|
||||||
|
qbbjgmsxx: undefined,
|
||||||
|
ty: 0,
|
||||||
|
bb: '',
|
||||||
|
xgsj: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 查询列表 ====================
|
||||||
|
fetchList() {
|
||||||
|
this.loading = true
|
||||||
|
const params = {
|
||||||
|
pageNum: this.pageNum,
|
||||||
|
pageSize: this.pageSize
|
||||||
|
}
|
||||||
|
params.ty = this.searchForm.ty
|
||||||
|
// 其余文本条件非空时才传
|
||||||
|
;['mc', 'pxlx', 'pxcc'].forEach(key => {
|
||||||
|
if (this.searchForm[key] !== '' && this.searchForm[key] !== null && this.searchForm[key] !== undefined) {
|
||||||
|
params[key] = this.searchForm[key].trim()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
listWarningCondition(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.searchForm = {
|
||||||
|
mc: '',
|
||||||
|
pxlx: '',
|
||||||
|
pxcc: '',
|
||||||
|
ty: 0
|
||||||
|
}
|
||||||
|
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.formTitle = '新增预警条件'
|
||||||
|
this.form = this.createEmptyForm()
|
||||||
|
this.formDialogVisible = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.formRef && this.$refs.formRef.clearValidate()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
handleEdit(row) {
|
||||||
|
this.isAdd = false
|
||||||
|
this.formTitle = '编辑预警条件'
|
||||||
|
this.form = this.createEmptyForm()
|
||||||
|
this.formDialogVisible = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.formRef && this.$refs.formRef.clearValidate()
|
||||||
|
})
|
||||||
|
getWarningCondition(row.bh).then(response => {
|
||||||
|
const data = response.data || {}
|
||||||
|
this.fillFormData(data)
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 回填表单数据 */
|
||||||
|
fillFormData(data) {
|
||||||
|
const fieldKeys = [
|
||||||
|
'mc', 'pxlx', 'pxcc',
|
||||||
|
'dqxqksbjgmssx', 'dqxqksbjgmsxx',
|
||||||
|
'dqxqkcbjgmssx', 'dqxqkcbjgmsxx',
|
||||||
|
'dqxqbjgmssx', 'dqxqbjgmsxx',
|
||||||
|
'qbksbjgmssx', 'qbksbjgmsxx',
|
||||||
|
'qbkcbjgmssx', 'qbkcbjgmsxx',
|
||||||
|
'qbbjgmssx', 'qbbjgmsxx',
|
||||||
|
'bb', 'xgsj'
|
||||||
|
]
|
||||||
|
const result = this.createEmptyForm()
|
||||||
|
fieldKeys.forEach(key => {
|
||||||
|
result[key] = data[key] !== null && data[key] !== undefined ? data[key] : result[key]
|
||||||
|
})
|
||||||
|
result.bh = data.bh
|
||||||
|
result.ty = data.ty === 1 || data.ty === true ? 1 : 0
|
||||||
|
this.form = result
|
||||||
|
},
|
||||||
|
|
||||||
|
handleFormSubmit() {
|
||||||
|
this.$refs.formRef.validate(valid => {
|
||||||
|
if (!valid) return
|
||||||
|
this.formSaving = true
|
||||||
|
const payload = { ...this.form }
|
||||||
|
if (!this.isAdd) {
|
||||||
|
payload.bh = this.form.bh
|
||||||
|
}
|
||||||
|
const request = this.isAdd ? addWarningCondition(payload) : updateWarningCondition(payload)
|
||||||
|
request.then(() => {
|
||||||
|
this.$message.success(this.isAdd ? '新增成功' : '修改成功')
|
||||||
|
this.formDialogVisible = false
|
||||||
|
this.fetchList()
|
||||||
|
}).catch(() => {
|
||||||
|
}).finally(() => {
|
||||||
|
this.formSaving = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 停用/启用切换 ====================
|
||||||
|
handleToggleDisable(row, val) {
|
||||||
|
const isDisable = val === 1 || val === true
|
||||||
|
const prevTy = isDisable ? 0 : 1
|
||||||
|
const actionName = isDisable ? '停用' : '启用'
|
||||||
|
this.$confirm(`确定要${actionName}「${row.mc || row.bh || '该预警条件'}」吗?`, '系统提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
return updateWarningCondition({ ...row, ty: isDisable ? 1 : 0 })
|
||||||
|
}).then(() => {
|
||||||
|
this.$message.success(actionName + '成功')
|
||||||
|
this.fetchList()
|
||||||
|
}).catch(() => {
|
||||||
|
// 取消或接口失败时回滚开关状态并刷新
|
||||||
|
row.ty = prevTy
|
||||||
|
this.fetchList()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 详情 ====================
|
||||||
|
handleView(row) {
|
||||||
|
this.viewDialogVisible = true
|
||||||
|
this.viewLoading = true
|
||||||
|
this.viewForm = {}
|
||||||
|
getWarningCondition(row.bh).then(response => {
|
||||||
|
this.viewForm = response.data || {}
|
||||||
|
this.viewLoading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.viewLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 空值显示占位符 */
|
||||||
|
formatValue(val) {
|
||||||
|
return val !== null && val !== undefined ? val : '-'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.warning-condition-page {
|
||||||
|
.search-card {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
::v-deep .el-form-item {
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-actions-row {
|
||||||
|
margin-top: 2px;
|
||||||
|
border-top: 1px dashed #ebeef5;
|
||||||
|
padding-top: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-dialog-form {
|
||||||
|
max-height: 62vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding-right: 6px;
|
||||||
|
|
||||||
|
::v-deep .el-divider--horizontal {
|
||||||
|
margin: 4px 0 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ty-tag {
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,560 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container discipline-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.zymc" 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.zydm" 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.zyfx" 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.xnz" 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="停用" class="checkbox-form-item">
|
||||||
|
<el-radio-group v-model="searchForm.ty">
|
||||||
|
<el-radio :label="false">否</el-radio>
|
||||||
|
<el-radio :label="true">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||||
|
<el-form-item label="培训类型2">
|
||||||
|
<el-select v-model="searchForm.pxlx2" placeholder="请选择" clearable class="w-full">
|
||||||
|
<el-option label="类型1" value="1" />
|
||||||
|
<el-option label="类型2" value="2" />
|
||||||
|
<el-option label="其他" value="3" />
|
||||||
|
</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 type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="序号" width="60" align="center">
|
||||||
|
<template slot-scope="scope">{{ fmtXh(scope.$index) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="jxgljgbh" label="教学管理机构" width="200" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="zydm" label="专业代码" width="200" />
|
||||||
|
<el-table-column prop="zymc" label="专业名称" width="200" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="zdyfl" label="分类" width="150" align="center" />
|
||||||
|
<el-table-column prop="xylb" label="学员类别" width="150" align="center" />
|
||||||
|
<el-table-column prop="xnz" label="学年制" width="120" align="center" />
|
||||||
|
<el-table-column prop="xqs" label="学期数" width="120" align="center" />
|
||||||
|
<el-table-column prop="zgzy" label="主干专业" align="center" />
|
||||||
|
<el-table-column label="操作" width="230" align="center" fixed="right">
|
||||||
|
<template slot-scope="{ row }">
|
||||||
|
<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 v-if="row.ty === 1" type="text" size="small" class="text-success" @click="handleEnable(row)">
|
||||||
|
启用
|
||||||
|
</el-button>
|
||||||
|
<el-button v-else type="text" size="small" class="text-danger" @click="handleDisable(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="750px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
@update:visible="val => formDialogVisible = val"
|
||||||
|
>
|
||||||
|
<el-form ref="formRef" :model="form" label-width="130px" class="add-form">
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="规范名称">
|
||||||
|
<el-input v-model="form.gfmc" placeholder="请输入规范名称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="序号">
|
||||||
|
<el-input-number v-model="form.xh" :min="0" controls-position="right" style="width: 100%" placeholder="请输入序号" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="专业代码">
|
||||||
|
<el-input v-model="form.zydm" placeholder="请输入专业代码" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="专业名称">
|
||||||
|
<el-input v-model="form.zymc" placeholder="请输入专业名称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="专业方向">
|
||||||
|
<el-input v-model="form.zyfx" placeholder="请输入专业方向" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="学年制">
|
||||||
|
<el-input v-model="form.xnz" placeholder="请输入学年制" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="学期数">
|
||||||
|
<el-input-number v-model="form.xqs" :min="0" controls-position="right" style="width: 100%" placeholder="请输入学期数" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="培训层次">
|
||||||
|
<el-input v-model="form.pxcc" placeholder="请输入培训层次" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="培训类型">
|
||||||
|
<el-input v-model="form.pxlx" placeholder="请输入培训类型" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="培训类型2">
|
||||||
|
<el-input v-model="form.pxlx2" placeholder="请输入培训类型2" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="教学管理机构编号">
|
||||||
|
<el-input v-model="form.jxgljgbh" placeholder="请输入教学管理机构编号" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="学员类别">
|
||||||
|
<el-input v-model="form.xylb" placeholder="请输入学员类别" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="自定义分类">
|
||||||
|
<el-input v-model="form.zdyfl" placeholder="请输入自定义分类" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="主干专业">
|
||||||
|
<el-input v-model="form.zgzy" placeholder="请输入主干专业" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="JSON字段">
|
||||||
|
<el-input v-model="form.jsonzd" placeholder="请输入JSON字段" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-form-item label="备注">
|
||||||
|
<el-input v-model="form.bz" type="textarea" :rows="3" placeholder="请输入备注" />
|
||||||
|
</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="700px" :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.gfmc || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="序号">{{ fmtValue(detailForm.xh) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="专业代码">{{ detailForm.zydm || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="专业名称">{{ detailForm.zymc || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="专业方向">{{ detailForm.zyfx || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="学年制">{{ detailForm.xnz || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="学期数">{{ fmtValue(detailForm.xqs) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="培训层次">{{ detailForm.pxcc || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="培训类型">{{ detailForm.pxlx || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="培训类型2">{{ detailForm.pxlx2 || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="教学管理机构编号">{{ detailForm.jxgljgbh || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="学员类别">{{ detailForm.xylb || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="自定义分类">{{ detailForm.zdyfl || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="主干专业">{{ detailForm.zgzy || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="停用">
|
||||||
|
<el-tag :type="detailForm.ty === 1 ? 'danger' : 'success'" size="mini">
|
||||||
|
{{ detailForm.ty === 1 ? '是' : '否' }}
|
||||||
|
</el-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="停用时间">{{ detailForm.tysj || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="JSON字段" :span="2">{{ detailForm.jsonzd || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="备注" :span="2">{{ detailForm.bz || '-' }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</div>
|
||||||
|
<div slot="footer">
|
||||||
|
<el-button @click="detailDialogVisible = false">关闭</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
listDiscipline,
|
||||||
|
getDiscipline,
|
||||||
|
addDiscipline,
|
||||||
|
updateDiscipline,
|
||||||
|
disableDiscipline
|
||||||
|
} from '@/api/subjectMajor/discipline'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'DisciplineIndex',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// ==================== 查询条件 ====================
|
||||||
|
searchForm: {
|
||||||
|
zymc: '',
|
||||||
|
zydm: '',
|
||||||
|
zyfx: '',
|
||||||
|
xnz: '',
|
||||||
|
ty: false,
|
||||||
|
pxlx2: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 列表数据 ====================
|
||||||
|
loading: false,
|
||||||
|
tableData: [],
|
||||||
|
total: 0,
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
|
||||||
|
// ==================== 新增/编辑 ====================
|
||||||
|
formDialogVisible: false,
|
||||||
|
dialogTitle: '新增学科专业',
|
||||||
|
isAdd: true,
|
||||||
|
formSaving: false,
|
||||||
|
form: this.createEmptyForm(),
|
||||||
|
|
||||||
|
// ==================== 详情 ====================
|
||||||
|
detailDialogVisible: false,
|
||||||
|
detailLoading: false,
|
||||||
|
detailForm: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.fetchList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 序号:按当前页数据索引生成跨页连续的序号 */
|
||||||
|
fmtXh(index) {
|
||||||
|
return (this.pageNum - 1) * this.pageSize + index + 1
|
||||||
|
},
|
||||||
|
|
||||||
|
createEmptyForm() {
|
||||||
|
return {
|
||||||
|
bsh: '',
|
||||||
|
gfmc: '',
|
||||||
|
xh: undefined,
|
||||||
|
zydm: '',
|
||||||
|
zymc: '',
|
||||||
|
zyfx: '',
|
||||||
|
xnz: '',
|
||||||
|
xqs: undefined,
|
||||||
|
pxcc: '',
|
||||||
|
pxlx: '',
|
||||||
|
pxlx2: '',
|
||||||
|
jxgljgbh: '',
|
||||||
|
xylb: '',
|
||||||
|
zdyfl: '',
|
||||||
|
jsonzd: '',
|
||||||
|
zgzy: '',
|
||||||
|
bz: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 查询列表 ====================
|
||||||
|
fetchList() {
|
||||||
|
this.loading = true
|
||||||
|
const params = {
|
||||||
|
pageNum: this.pageNum,
|
||||||
|
pageSize: this.pageSize
|
||||||
|
}
|
||||||
|
params.ty = this.searchForm.ty ? 1 : 0
|
||||||
|
// 其余文本条件非空时才传
|
||||||
|
;['zymc', 'zydm', 'zyfx', 'xnz', 'pxlx2'].forEach(key => {
|
||||||
|
const value = this.searchForm[key]
|
||||||
|
if (value !== '' && value !== null && value !== undefined) {
|
||||||
|
params[key] = String(value).trim()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
listDiscipline(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()
|
||||||
|
})
|
||||||
|
getDiscipline(row.bsh).then(response => {
|
||||||
|
const data = response.data || {}
|
||||||
|
this.form = {
|
||||||
|
bsh: data.bsh || '',
|
||||||
|
gfmc: data.gfmc || '',
|
||||||
|
xh: data.xh !== null && data.xh !== undefined ? data.xh : undefined,
|
||||||
|
zydm: data.zydm || '',
|
||||||
|
zymc: data.zymc || '',
|
||||||
|
zyfx: data.zyfx || '',
|
||||||
|
xnz: data.xnz || '',
|
||||||
|
xqs: data.xqs !== null && data.xqs !== undefined ? data.xqs : undefined,
|
||||||
|
pxcc: data.pxcc || '',
|
||||||
|
pxlx: data.pxlx || '',
|
||||||
|
pxlx2: data.pxlx2 || '',
|
||||||
|
jxgljgbh: data.jxgljgbh || '',
|
||||||
|
xylb: data.xylb || '',
|
||||||
|
zdyfl: data.zdyfl || '',
|
||||||
|
jsonzd: data.jsonzd || '',
|
||||||
|
zgzy: data.zgzy || '',
|
||||||
|
bz: data.bz || ''
|
||||||
|
}
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
|
||||||
|
buildPayload() {
|
||||||
|
const f = this.form
|
||||||
|
const payload = {
|
||||||
|
bsh: f.bsh || undefined,
|
||||||
|
gfmc: f.gfmc,
|
||||||
|
zydm: f.zydm,
|
||||||
|
zymc: f.zymc,
|
||||||
|
zyfx: f.zyfx,
|
||||||
|
xnz: f.xnz,
|
||||||
|
pxcc: f.pxcc,
|
||||||
|
pxlx: f.pxlx,
|
||||||
|
pxlx2: f.pxlx2,
|
||||||
|
jxgljgbh: f.jxgljgbh,
|
||||||
|
xylb: f.xylb,
|
||||||
|
zdyfl: f.zdyfl,
|
||||||
|
zgzy: f.zgzy,
|
||||||
|
jsonzd: f.jsonzd,
|
||||||
|
bz: f.bz
|
||||||
|
}
|
||||||
|
// 序号、学期数为数值字段,转为数字后再提交
|
||||||
|
if (f.xh !== '' && f.xh !== null && f.xh !== undefined) {
|
||||||
|
payload.xh = Number(f.xh)
|
||||||
|
}
|
||||||
|
if (f.xqs !== '' && f.xqs !== null && f.xqs !== undefined) {
|
||||||
|
payload.xqs = Number(f.xqs)
|
||||||
|
}
|
||||||
|
return payload
|
||||||
|
},
|
||||||
|
|
||||||
|
handleFormSubmit() {
|
||||||
|
this.formSaving = true
|
||||||
|
const payload = this.buildPayload()
|
||||||
|
const request = this.isAdd ? addDiscipline(payload) : updateDiscipline(payload)
|
||||||
|
request.then(() => {
|
||||||
|
this.$message.success(this.isAdd ? '新增成功' : '修改成功')
|
||||||
|
this.formDialogVisible = false
|
||||||
|
this.fetchList()
|
||||||
|
}).catch(() => {
|
||||||
|
}).finally(() => {
|
||||||
|
this.formSaving = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 停用/启用 ====================
|
||||||
|
handleDisable(row) {
|
||||||
|
this.$confirm(`确定要停用「${row.zymc || row.zydm || '该专业'}」吗?`, '系统提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
return disableDiscipline(row.bsh)
|
||||||
|
}).then(() => {
|
||||||
|
this.$message.success('停用成功')
|
||||||
|
this.fetchList()
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 后端暂未提供启用接口,仅作提示
|
||||||
|
handleEnable(row) {
|
||||||
|
this.$message.info('后端暂未提供该接口')
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 详情 ====================
|
||||||
|
// 数值字段空值显示为 '-'(保留 0)
|
||||||
|
fmtValue(val) {
|
||||||
|
return val === null || val === undefined || val === '' ? '-' : val
|
||||||
|
},
|
||||||
|
|
||||||
|
handleDetail(row) {
|
||||||
|
this.detailDialogVisible = true
|
||||||
|
this.detailLoading = true
|
||||||
|
this.detailForm = {}
|
||||||
|
getDiscipline(row.bsh).then(response => {
|
||||||
|
this.detailForm = response.data || {}
|
||||||
|
this.detailLoading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.detailLoading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.discipline-page {
|
||||||
|
.search-form {
|
||||||
|
.w-full {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-form-item {
|
||||||
|
::v-deep(.el-form-item__content) {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding-top: 8px;
|
||||||
|
|
||||||
|
.search-tip {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #f56c6c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-form {
|
||||||
|
max-height: 60vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-success {
|
||||||
|
color: #67c23a;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-danger {
|
||||||
|
color: #f56c6c;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,723 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container major-page">
|
||||||
|
<!-- ==================== 1. 查询条件 ==================== -->
|
||||||
|
<el-card shadow="never" class="search-card">
|
||||||
|
<el-form ref="searchFormRef" :model="searchForm" label-width="140px" class="search-form">
|
||||||
|
<el-row :gutter="24">
|
||||||
|
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
|
||||||
|
<el-form-item label="专业名称">
|
||||||
|
<el-input v-model="searchForm.zymc" placeholder="请输入专业名称" clearable @keyup.enter.native="handleSearch" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
|
||||||
|
<el-form-item label="专业方向">
|
||||||
|
<el-input v-model="searchForm.zyfx" placeholder="请输入专业方向" clearable @keyup.enter.native="handleSearch" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
|
||||||
|
<el-form-item label="专业代码">
|
||||||
|
<el-input v-model="searchForm.zydm" placeholder="请输入专业代码" clearable @keyup.enter.native="handleSearch" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
|
||||||
|
<el-form-item label="学年制">
|
||||||
|
<el-input v-model="searchForm.xnz" placeholder="请输入学年制" clearable @keyup.enter.native="handleSearch" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
|
||||||
|
<el-form-item label="培训类型">
|
||||||
|
<el-input v-model="searchForm.pxlx" placeholder="请输入培训类型" clearable @keyup.enter.native="handleSearch" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
|
||||||
|
<el-form-item label="培训类型2">
|
||||||
|
<el-input v-model="searchForm.pxlx2" placeholder="请输入培训类型2" clearable @keyup.enter.native="handleSearch" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
|
||||||
|
<el-form-item label="培训层次">
|
||||||
|
<el-input v-model="searchForm.pxcc" placeholder="请输入培训层次" clearable @keyup.enter.native="handleSearch" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
|
||||||
|
<el-form-item label="学科专业信息标识号">
|
||||||
|
<el-input v-model="searchForm.xkzyxxbsh" placeholder="请输入学科专业信息标识号" clearable @keyup.enter.native="handleSearch" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
|
||||||
|
<el-form-item label="停用">
|
||||||
|
<el-radio-group v-model="searchForm.ty">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row class="search-actions-row">
|
||||||
|
<el-col :span="24" class="search-actions">
|
||||||
|
<el-button type="primary" icon="el-icon-search" @click="handleSearch">查询</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
|
||||||
|
</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>
|
||||||
|
<div class="table-actions">
|
||||||
|
<el-button type="primary" icon="el-icon-download" @click="handleDownloadTemplate">下载模板</el-button>
|
||||||
|
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新增专业</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-table v-loading="loading" :data="tableData" stripe border highlight-current-row>
|
||||||
|
<el-table-column label="序号" width="60" align="center">
|
||||||
|
<template slot-scope="scope">{{ fmtXh(scope.$index) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="zydh" label="专业代号" width="120" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="zymc" label="专业名称" min-width="140" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="zyfx" label="专业方向" min-width="120" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="zydm" label="专业代码" width="110" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="xnz" label="学年制" width="80" align="center" />
|
||||||
|
<el-table-column prop="xqs" label="学期数" width="80" align="center" />
|
||||||
|
<el-table-column prop="pxcc" label="培训层次" width="100" align="center" />
|
||||||
|
<el-table-column prop="pxlx" label="培训类型" width="100" align="center" />
|
||||||
|
<el-table-column prop="pxlx2" label="培训类型2" width="100" align="center" />
|
||||||
|
<el-table-column prop="xylb" label="学员类别" width="100" align="center" />
|
||||||
|
<el-table-column label="停用" width="80" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag
|
||||||
|
:type="scope.row.ty === 1 || scope.row.ty === true ? 'danger' : 'success'"
|
||||||
|
class="ty-tag"
|
||||||
|
@click.native="handleToggleDisable(scope.row, scope.row.ty === 1 || scope.row.ty === true ? 0 : 1)"
|
||||||
|
>
|
||||||
|
{{ scope.row.ty === 1 || scope.row.ty === true ? '是' : '否' }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="180" align="center" fixed="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button type="text" size="small" icon="el-icon-view" @click="handleView(scope.row)">详情</el-button>
|
||||||
|
<el-button type="text" size="small" icon="el-icon-edit" @click="handleEdit(scope.row)">编辑</el-button>
|
||||||
|
<el-button type="text" size="small" icon="el-icon-delete" class="text-danger" @click="handleDelete(scope.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
|
||||||
|
:title="formTitle"
|
||||||
|
:visible.sync="formDialogVisible"
|
||||||
|
width="900px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-form ref="formRef" :model="form" :rules="formRules" label-width="130px" class="form-dialog-form">
|
||||||
|
<el-divider content-position="left">基本信息</el-divider>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="专业代号" prop="zydh">
|
||||||
|
<el-input v-model="form.zydh" :disabled="!isAdd" placeholder="请输入专业代号" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="专业名称" prop="zymc">
|
||||||
|
<el-input v-model="form.zymc" placeholder="请输入专业名称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="专业方向" prop="zyfx">
|
||||||
|
<el-input v-model="form.zyfx" placeholder="请输入专业方向" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="专业代码" prop="zydm">
|
||||||
|
<el-input v-model="form.zydm" placeholder="请输入专业代码" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="专业版本" prop="zybb">
|
||||||
|
<el-input v-model="form.zybb" placeholder="请输入专业版本" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="学年制" prop="xnz">
|
||||||
|
<el-input v-model="form.xnz" placeholder="请输入学年制" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="学期数" prop="xqs">
|
||||||
|
<el-input-number v-model="form.xqs" :min="0" :max="999" controls-position="right" style="width: 100%" placeholder="请输入学期数" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="专业标识号" prop="zybsh">
|
||||||
|
<el-input v-model="form.zybsh" placeholder="请输入专业标识号" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="学科专业信息标识号" prop="xkzyxxbsh">
|
||||||
|
<el-input v-model="form.xkzyxxbsh" placeholder="请输入学科专业信息标识号" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="教学管理机构编号">
|
||||||
|
<el-input v-model="form.jxgljgbh" placeholder="请输入教学管理机构编号" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="规范名称">
|
||||||
|
<el-input v-model="form.gfmc" placeholder="请输入规范名称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="简称">
|
||||||
|
<el-input v-model="form.jc" placeholder="请输入简称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-divider content-position="left">培训信息</el-divider>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="培训层次" prop="pxcc">
|
||||||
|
<el-input v-model="form.pxcc" placeholder="请输入培训层次" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="培训类型" prop="pxlx">
|
||||||
|
<el-input v-model="form.pxlx" placeholder="请输入培训类型" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="培训类型2" prop="pxlx2">
|
||||||
|
<el-input v-model="form.pxlx2" placeholder="请输入培训类型2" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="学员类别" prop="xylb">
|
||||||
|
<el-input v-model="form.xylb" placeholder="请输入学员类别" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="主干专业" prop="zgzy">
|
||||||
|
<el-select v-model="form.zgzy" placeholder="请选择" clearable style="width: 100%">
|
||||||
|
<el-option label="是" value="是" />
|
||||||
|
<el-option label="否" value="否" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="自定义分类" prop="zdyfl">
|
||||||
|
<el-input v-model="form.zdyfl" placeholder="请输入自定义分类" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="节次类别" prop="jclb">
|
||||||
|
<el-input v-model="form.jclb" placeholder="请输入节次类别" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="系统模式" prop="xtms">
|
||||||
|
<el-input v-model="form.xtms" placeholder="请输入系统模式" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-divider content-position="left">其他信息</el-divider>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="教学大纲编号">
|
||||||
|
<el-input v-model="form.jxdgbh" placeholder="请输入教学大纲编号" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="人培编号">
|
||||||
|
<el-input v-model="form.rpbh" placeholder="请输入人培编号" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="序号标识">
|
||||||
|
<el-input-number v-model="form.xhbs" :min="0" controls-position="right" style="width: 100%" placeholder="请输入序号标识" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="JSON字段">
|
||||||
|
<el-input v-model="form.jsonzd" placeholder="请输入JSON字段" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="停用" prop="ty">
|
||||||
|
<el-switch v-model="form.ty" :active-value="1" :inactive-value="0" active-text="是" inactive-text="否" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="启用时间">
|
||||||
|
<el-date-picker v-model="form.qysj" type="datetime" placeholder="请选择启用时间" value-format="yyyy-MM-dd HH:mm:ss" style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="停用时间">
|
||||||
|
<el-date-picker v-model="form.tysj" type="datetime" placeholder="请选择停用时间" value-format="yyyy-MM-dd HH:mm:ss" style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="培养目标">
|
||||||
|
<el-input v-model="form.pymb" placeholder="请输入培养目标" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="专业备注">
|
||||||
|
<el-input v-model="form.zybz" type="textarea" :rows="3" placeholder="请输入专业备注" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="专业规范">
|
||||||
|
<el-input v-model="form.zygf" type="textarea" :rows="3" placeholder="请输入专业规范" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-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.sync="viewDialogVisible" width="700px" :close-on-click-modal="false">
|
||||||
|
<div v-loading="viewLoading" class="detail-body">
|
||||||
|
<el-descriptions :column="2" border>
|
||||||
|
<el-descriptions-item label="专业代号">{{ viewForm.zydh || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="专业名称">{{ viewForm.zymc || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="专业方向">{{ viewForm.zyfx || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="专业代码">{{ viewForm.zydm || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="专业版本">{{ viewForm.zybb || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="专业标识号">{{ viewForm.zybsh || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="学年制">{{ viewForm.xnz || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="学期数">{{ viewForm.xqs || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="培训层次">{{ viewForm.pxcc || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="培训类型">{{ viewForm.pxlx || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="培训类型2">{{ viewForm.pxlx2 || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="学员类别">{{ viewForm.xylb || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="主干专业">{{ viewForm.zgzy || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="自定义分类">{{ viewForm.zdyfl || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="教学管理机构编号">{{ viewForm.jxgljgbh || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="学科专业信息标识号">{{ viewForm.xkzyxxbsh || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="简称">{{ viewForm.jc || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="规范名称">{{ viewForm.gfmc || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="节次类别">{{ viewForm.jclb || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="系统模式">{{ viewForm.xtms || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="序号标识">{{ viewForm.xhbs || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="教学大纲编号">{{ viewForm.jxdgbh || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="人培编号">{{ viewForm.rpbh || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="启用时间">{{ viewForm.qysj || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="停用时间">{{ viewForm.tysj || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="停用">
|
||||||
|
<el-tag :type="viewForm.ty === 1 || viewForm.ty === true ? 'danger' : 'success'" size="mini">
|
||||||
|
{{ viewForm.ty === 1 || viewForm.ty === true ? '是' : '否' }}
|
||||||
|
</el-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="JSON字段">{{ viewForm.jsonzd || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="培养目标" :span="2">{{ viewForm.pymb || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="专业备注" :span="2">{{ viewForm.zybz || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="专业规范" :span="2">{{ viewForm.zygf || '-' }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</div>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="viewDialogVisible = false">关 闭</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
listMajor,
|
||||||
|
getMajor,
|
||||||
|
addMajor,
|
||||||
|
updateMajor,
|
||||||
|
delMajor,
|
||||||
|
downloadMajorTemplate
|
||||||
|
} from "@/api/subjectMajor/major"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Major",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// ==================== 查询条件 ====================
|
||||||
|
searchForm: {
|
||||||
|
zymc: '',
|
||||||
|
zyfx: '',
|
||||||
|
zydm: '',
|
||||||
|
xnz: '',
|
||||||
|
pxlx: '',
|
||||||
|
pxlx2: '',
|
||||||
|
pxcc: '',
|
||||||
|
xkzyxxbsh: '',
|
||||||
|
ty: 0
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 列表数据 ====================
|
||||||
|
loading: false,
|
||||||
|
tableData: [],
|
||||||
|
total: 0,
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
|
||||||
|
// ==================== 新增/编辑 ====================
|
||||||
|
formDialogVisible: false,
|
||||||
|
formTitle: '新增专业',
|
||||||
|
isAdd: true,
|
||||||
|
formSaving: false,
|
||||||
|
form: this.createEmptyForm(),
|
||||||
|
formRules: {
|
||||||
|
zydh: [{ required: true, message: "专业代号不能为空", trigger: "blur" }],
|
||||||
|
zymc: [{ required: true, message: "专业名称不能为空", trigger: "blur" }],
|
||||||
|
zyfx: [{ required: true, message: "专业方向不能为空", trigger: "blur" }],
|
||||||
|
zydm: [{ required: true, message: "专业代码不能为空", trigger: "blur" }],
|
||||||
|
zybb: [{ required: true, message: "专业版本不能为空", trigger: "blur" }],
|
||||||
|
xnz: [{ required: true, message: "学年制不能为空", trigger: "blur" }],
|
||||||
|
xqs: [{ required: true, message: "学期数不能为空", trigger: "change" }],
|
||||||
|
zybsh: [{ required: true, message: "专业标识号不能为空", trigger: "blur" }],
|
||||||
|
pxcc: [{ required: true, message: "培训层次不能为空", trigger: "blur" }],
|
||||||
|
pxlx: [{ required: true, message: "培训类型不能为空", trigger: "blur" }],
|
||||||
|
pxlx2: [{ required: true, message: "培训类型2不能为空", trigger: "blur" }],
|
||||||
|
xylb: [{ required: true, message: "学员类别不能为空", trigger: "blur" }],
|
||||||
|
zdyfl: [{ required: true, message: "自定义分类不能为空", trigger: "blur" }],
|
||||||
|
zgzy: [{ required: true, message: "主干专业不能为空", trigger: "change" }],
|
||||||
|
jclb: [{ required: true, message: "节次类别不能为空", trigger: "blur" }],
|
||||||
|
xtms: [{ required: true, message: "系统模式不能为空", trigger: "blur" }]
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 详情 ====================
|
||||||
|
viewDialogVisible: false,
|
||||||
|
viewLoading: false,
|
||||||
|
viewForm: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.fetchList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 表格序号(跨页连续) */
|
||||||
|
fmtXh(index) {
|
||||||
|
return (this.pageNum - 1) * this.pageSize + index + 1
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 创建空表单 */
|
||||||
|
createEmptyForm() {
|
||||||
|
return {
|
||||||
|
zydh: '',
|
||||||
|
zymc: '',
|
||||||
|
zyfx: '',
|
||||||
|
xnz: '',
|
||||||
|
xqs: undefined,
|
||||||
|
zybz: '',
|
||||||
|
zygf: '',
|
||||||
|
zydm: '',
|
||||||
|
zybb: '',
|
||||||
|
ty: 0,
|
||||||
|
qysj: null,
|
||||||
|
tysj: null,
|
||||||
|
jxgljgbh: '',
|
||||||
|
pxcc: '',
|
||||||
|
pxlx: '',
|
||||||
|
xkzyxxbsh: '',
|
||||||
|
pxlx2: '',
|
||||||
|
xylb: '',
|
||||||
|
zdyfl: '',
|
||||||
|
zybsh: '',
|
||||||
|
xhbs: undefined,
|
||||||
|
jc: '',
|
||||||
|
jclb: '',
|
||||||
|
xtms: '',
|
||||||
|
jsonzd: '',
|
||||||
|
zgzy: '',
|
||||||
|
gfmc: '',
|
||||||
|
jxdgbh: '',
|
||||||
|
rpbh: '',
|
||||||
|
pymb: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 查询列表 ====================
|
||||||
|
fetchList() {
|
||||||
|
this.loading = true
|
||||||
|
const params = {
|
||||||
|
pageNum: this.pageNum,
|
||||||
|
pageSize: this.pageSize
|
||||||
|
}
|
||||||
|
params.ty = this.searchForm.ty
|
||||||
|
// 其余文本条件非空时才传
|
||||||
|
;['zymc', 'zyfx', 'zydm', 'xnz', 'pxlx', 'pxlx2', 'pxcc', 'xkzyxxbsh'].forEach(key => {
|
||||||
|
if (this.searchForm[key] !== '' && this.searchForm[key] !== null && this.searchForm[key] !== undefined) {
|
||||||
|
params[key] = this.searchForm[key].trim()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
listMajor(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.searchForm = {
|
||||||
|
zymc: '',
|
||||||
|
zyfx: '',
|
||||||
|
zydm: '',
|
||||||
|
xnz: '',
|
||||||
|
pxlx: '',
|
||||||
|
pxlx2: '',
|
||||||
|
pxcc: '',
|
||||||
|
xkzyxxbsh: '',
|
||||||
|
ty: 0
|
||||||
|
}
|
||||||
|
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.formTitle = '新增专业'
|
||||||
|
this.form = this.createEmptyForm()
|
||||||
|
this.formDialogVisible = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.formRef && this.$refs.formRef.clearValidate()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
handleEdit(row) {
|
||||||
|
this.isAdd = false
|
||||||
|
this.formTitle = '编辑专业'
|
||||||
|
this.form = this.createEmptyForm()
|
||||||
|
this.formDialogVisible = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.formRef && this.$refs.formRef.clearValidate()
|
||||||
|
})
|
||||||
|
getMajor(row.zydh).then(response => {
|
||||||
|
const data = response.data || {}
|
||||||
|
this.form = {
|
||||||
|
zydh: data.zydh,
|
||||||
|
zymc: data.zymc,
|
||||||
|
zyfx: data.zyfx,
|
||||||
|
xnz: data.xnz,
|
||||||
|
xqs: data.xqs !== null && data.xqs !== undefined ? data.xqs : undefined,
|
||||||
|
zybz: data.zybz,
|
||||||
|
zygf: data.zygf,
|
||||||
|
zydm: data.zydm,
|
||||||
|
zybb: data.zybb,
|
||||||
|
ty: data.ty === 1 || data.ty === true ? 1 : 0,
|
||||||
|
qysj: data.qysj,
|
||||||
|
tysj: data.tysj,
|
||||||
|
jxgljgbh: data.jxgljgbh,
|
||||||
|
pxcc: data.pxcc,
|
||||||
|
pxlx: data.pxlx,
|
||||||
|
xkzyxxbsh: data.xkzyxxbsh,
|
||||||
|
pxlx2: data.pxlx2,
|
||||||
|
xylb: data.xylb,
|
||||||
|
zdyfl: data.zdyfl,
|
||||||
|
zybsh: data.zybsh,
|
||||||
|
xhbs: data.xhbs,
|
||||||
|
jc: data.jc,
|
||||||
|
jclb: data.jclb,
|
||||||
|
xtms: data.xtms,
|
||||||
|
jsonzd: data.jsonzd,
|
||||||
|
zgzy: data.zgzy,
|
||||||
|
gfmc: data.gfmc,
|
||||||
|
jxdgbh: data.jxdgbh,
|
||||||
|
rpbh: data.rpbh,
|
||||||
|
pymb: data.pymb
|
||||||
|
}
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
|
||||||
|
handleFormSubmit() {
|
||||||
|
this.$refs.formRef.validate(valid => {
|
||||||
|
if (!valid) return
|
||||||
|
this.formSaving = true
|
||||||
|
const payload = { ...this.form }
|
||||||
|
const request = this.isAdd ? addMajor(payload) : updateMajor(payload)
|
||||||
|
request.then(() => {
|
||||||
|
this.$message.success(this.isAdd ? '新增成功' : '修改成功')
|
||||||
|
this.formDialogVisible = false
|
||||||
|
this.fetchList()
|
||||||
|
}).catch(() => {
|
||||||
|
}).finally(() => {
|
||||||
|
this.formSaving = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 停用/启用切换 ====================
|
||||||
|
handleToggleDisable(row, val) {
|
||||||
|
const isDisable = val === 1 || val === true
|
||||||
|
const prevTy = isDisable ? 0 : 1
|
||||||
|
const actionName = isDisable ? '停用' : '启用'
|
||||||
|
this.$confirm(`确定要${actionName}「${row.zymc || row.zydh || '该专业'}」吗?`, '系统提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
return updateMajor({ ...row, ty: isDisable ? 1 : 0 })
|
||||||
|
}).then(() => {
|
||||||
|
this.$message.success(actionName + '成功')
|
||||||
|
this.fetchList()
|
||||||
|
}).catch(() => {
|
||||||
|
// 取消或接口失败时回滚开关状态并刷新
|
||||||
|
row.ty = prevTy
|
||||||
|
this.fetchList()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 删除 ====================
|
||||||
|
handleDelete(row) {
|
||||||
|
this.$confirm(`确定要删除「${row.zymc || row.zydh || '该专业'}」吗?`, '系统提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
return delMajor(row.zydh)
|
||||||
|
}).then(() => {
|
||||||
|
this.$message.success('删除成功')
|
||||||
|
this.fetchList()
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 下载模板 ====================
|
||||||
|
handleDownloadTemplate() {
|
||||||
|
downloadMajorTemplate().then(res => {
|
||||||
|
const blob = new Blob([res], { type: 'application/vnd.ms-excel;charset=utf-8' })
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = URL.createObjectURL(blob)
|
||||||
|
link.download = '人才培养方案课程数据文件模板.xls'
|
||||||
|
link.click()
|
||||||
|
URL.revokeObjectURL(link.href)
|
||||||
|
this.$message.success('模板下载成功')
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
|
||||||
|
// ==================== 详情 ====================
|
||||||
|
handleView(row) {
|
||||||
|
this.viewDialogVisible = true
|
||||||
|
this.viewLoading = true
|
||||||
|
this.viewForm = {}
|
||||||
|
getMajor(row.zydh).then(response => {
|
||||||
|
this.viewForm = response.data || {}
|
||||||
|
this.viewLoading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.viewLoading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.major-page {
|
||||||
|
.search-card {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
::v-deep .el-form-item {
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-actions-row {
|
||||||
|
margin-top: 2px;
|
||||||
|
border-top: 1px dashed #ebeef5;
|
||||||
|
padding-top: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-dialog-form {
|
||||||
|
max-height: 62vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding-right: 6px;
|
||||||
|
|
||||||
|
::v-deep .el-divider--horizontal {
|
||||||
|
margin: 4px 0 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-danger {
|
||||||
|
color: #f56c6c;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ty-tag {
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,426 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container system-dept">
|
||||||
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
|
||||||
|
<el-form-item label="部门名称" prop="deptName">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.deptName"
|
||||||
|
placeholder="请输入部门名称"
|
||||||
|
clearable
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="停用" prop="status">
|
||||||
|
<el-radio-group v-model="queryParams.status">
|
||||||
|
<el-radio label="0">否</el-radio>
|
||||||
|
<el-radio label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="el-icon-plus"
|
||||||
|
size="mini"
|
||||||
|
@click="handleAdd"
|
||||||
|
v-hasPermi="['system:dept:add']"
|
||||||
|
>新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="warning"
|
||||||
|
plain
|
||||||
|
icon="el-icon-check"
|
||||||
|
size="mini"
|
||||||
|
@click="handleSaveSort"
|
||||||
|
v-hasPermi="['system:dept:edit']"
|
||||||
|
>保存排序</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="info"
|
||||||
|
plain
|
||||||
|
icon="el-icon-sort"
|
||||||
|
size="mini"
|
||||||
|
@click="toggleExpandAll"
|
||||||
|
>展开/折叠</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table
|
||||||
|
v-if="refreshTable"
|
||||||
|
v-loading="loading"
|
||||||
|
:data="deptList"
|
||||||
|
:height="tableHeight"
|
||||||
|
row-key="deptId"
|
||||||
|
:default-expand-all="isExpandAll"
|
||||||
|
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
|
||||||
|
>
|
||||||
|
<el-table-column prop="deptName" label="部门名称" width="260"></el-table-column>
|
||||||
|
<el-table-column prop="orderNum" label="排序" width="200">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-input-number v-model="scope.row.orderNum" controls-position="right" :min="0" size="mini" style="width: 88px" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="status" label="状态" width="100">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="创建时间" align="center" prop="createTime" width="200">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-edit"
|
||||||
|
@click="handleUpdate(scope.row)"
|
||||||
|
v-hasPermi="['system:dept:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-plus"
|
||||||
|
@click="handleAdd(scope.row)"
|
||||||
|
v-hasPermi="['system:dept:add']"
|
||||||
|
>新增</el-button>
|
||||||
|
<el-button
|
||||||
|
v-if="scope.row.parentId != 0"
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
@click="handleDelete(scope.row)"
|
||||||
|
v-hasPermi="['system:dept:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 添加或修改部门对话框 -->
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24" v-if="form.parentId !== 0">
|
||||||
|
<el-form-item label="上级部门" prop="parentId">
|
||||||
|
<treeselect v-model="form.parentId" :options="deptOptions" :normalizer="normalizer" placeholder="选择上级部门" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="部门名称" prop="deptName">
|
||||||
|
<el-input v-model="form.deptName" placeholder="请输入部门名称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="显示排序" prop="orderNum">
|
||||||
|
<el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="负责人" prop="leader">
|
||||||
|
<el-input v-model="form.leader" placeholder="请输入负责人" maxlength="20" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="联系电话" prop="phone">
|
||||||
|
<el-input v-model="form.phone" placeholder="请输入联系电话" maxlength="11" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="邮箱" prop="email">
|
||||||
|
<el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="部门状态">
|
||||||
|
<el-radio-group v-model="form.status">
|
||||||
|
<el-radio
|
||||||
|
v-for="dict in dict.type.sys_normal_disable"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.value"
|
||||||
|
>{{dict.label}}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listDept, getDept, delDept, addDept, updateDept, updateDeptSort, listDeptExcludeChild } from "@/api/system/dept"
|
||||||
|
import Treeselect from "@riophae/vue-treeselect"
|
||||||
|
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Dept",
|
||||||
|
dicts: ['sys_normal_disable'],
|
||||||
|
components: { Treeselect },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 遮罩层
|
||||||
|
loading: true,
|
||||||
|
// 显示搜索条件
|
||||||
|
showSearch: true,
|
||||||
|
// 表格高度
|
||||||
|
tableHeight: window.innerHeight - 240,
|
||||||
|
// 表格树数据
|
||||||
|
deptList: [],
|
||||||
|
// 部门树选项
|
||||||
|
deptOptions: [],
|
||||||
|
// 弹出层标题
|
||||||
|
title: "",
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
// 是否展开,默认全部展开
|
||||||
|
isExpandAll: true,
|
||||||
|
// 重新渲染表格状态
|
||||||
|
refreshTable: true,
|
||||||
|
// 记录原始排序,用于对比变更
|
||||||
|
originalOrders: {},
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
deptName: undefined,
|
||||||
|
status: '0'
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
// 表单校验
|
||||||
|
rules: {
|
||||||
|
parentId: [
|
||||||
|
{ required: true, message: "上级部门不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
deptName: [
|
||||||
|
{ required: true, message: "部门名称不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
orderNum: [
|
||||||
|
{ required: true, message: "显示排序不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
email: [
|
||||||
|
{
|
||||||
|
type: "email",
|
||||||
|
message: "请输入正确的邮箱地址",
|
||||||
|
trigger: ["blur", "change"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
phone: [
|
||||||
|
{
|
||||||
|
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
|
||||||
|
message: "请输入正确的手机号码",
|
||||||
|
trigger: "blur"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getTableHeight()
|
||||||
|
window.addEventListener('resize', this.getTableHeight)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
window.removeEventListener('resize', this.getTableHeight)
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
showSearch() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.getTableHeight()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getTableHeight() {
|
||||||
|
const offset = this.showSearch ? 240 : 190
|
||||||
|
this.tableHeight = window.innerHeight - offset
|
||||||
|
},
|
||||||
|
/** 查询部门列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
listDept(this.queryParams).then(response => {
|
||||||
|
this.deptList = this.handleTree(response.data, "deptId")
|
||||||
|
// 记录原始排序值
|
||||||
|
this.recordOriginalOrders(this.deptList)
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 转换部门数据结构 */
|
||||||
|
normalizer(node) {
|
||||||
|
if (node.children && !node.children.length) {
|
||||||
|
delete node.children
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
id: node.deptId,
|
||||||
|
label: node.deptName,
|
||||||
|
children: node.children
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 取消按钮
|
||||||
|
cancel() {
|
||||||
|
this.open = false
|
||||||
|
this.reset()
|
||||||
|
},
|
||||||
|
// 表单重置
|
||||||
|
reset() {
|
||||||
|
this.form = {
|
||||||
|
deptId: undefined,
|
||||||
|
parentId: undefined,
|
||||||
|
deptName: undefined,
|
||||||
|
orderNum: undefined,
|
||||||
|
leader: undefined,
|
||||||
|
phone: undefined,
|
||||||
|
email: undefined,
|
||||||
|
status: "0"
|
||||||
|
}
|
||||||
|
this.resetForm("form")
|
||||||
|
},
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery() {
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
resetQuery() {
|
||||||
|
this.resetForm("queryForm")
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
handleAdd(row) {
|
||||||
|
this.reset()
|
||||||
|
if (row != undefined) {
|
||||||
|
this.form.parentId = row.deptId
|
||||||
|
}
|
||||||
|
this.open = true
|
||||||
|
this.title = "添加部门"
|
||||||
|
listDept().then(response => {
|
||||||
|
this.deptOptions = this.handleTree(response.data, "deptId")
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 展开/折叠操作 */
|
||||||
|
toggleExpandAll() {
|
||||||
|
this.refreshTable = false
|
||||||
|
this.isExpandAll = !this.isExpandAll
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.refreshTable = true
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
handleUpdate(row) {
|
||||||
|
this.reset()
|
||||||
|
getDept(row.deptId).then(response => {
|
||||||
|
this.form = response.data
|
||||||
|
this.open = true
|
||||||
|
this.title = "修改部门"
|
||||||
|
listDeptExcludeChild(row.deptId).then(response => {
|
||||||
|
this.deptOptions = this.handleTree(response.data, "deptId")
|
||||||
|
if (this.deptOptions.length == 0) {
|
||||||
|
const noResultsOptions = { deptId: this.form.parentId, deptName: this.form.parentName, children: [] }
|
||||||
|
this.deptOptions.push(noResultsOptions)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 提交按钮 */
|
||||||
|
submitForm() {
|
||||||
|
this.$refs["form"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
if (this.form.deptId != undefined) {
|
||||||
|
updateDept(this.form).then(() => {
|
||||||
|
this.$modal.msgSuccess("修改成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
addDept(this.form).then(() => {
|
||||||
|
this.$modal.msgSuccess("新增成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 递归记录原始排序 */
|
||||||
|
recordOriginalOrders(list) {
|
||||||
|
list.forEach(item => {
|
||||||
|
this.originalOrders[item.deptId] = item.orderNum
|
||||||
|
if (item.children && item.children.length) {
|
||||||
|
this.recordOriginalOrders(item.children)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 保存排序 */
|
||||||
|
handleSaveSort() {
|
||||||
|
const changedDeptIds = []
|
||||||
|
const changedOrderNums = []
|
||||||
|
const collectChanged = (list) => {
|
||||||
|
list.forEach(item => {
|
||||||
|
if (String(this.originalOrders[item.deptId]) !== String(item.orderNum)) {
|
||||||
|
changedDeptIds.push(item.deptId)
|
||||||
|
changedOrderNums.push(item.orderNum)
|
||||||
|
}
|
||||||
|
if (item.children && item.children.length) {
|
||||||
|
collectChanged(item.children)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
collectChanged(this.deptList)
|
||||||
|
if (changedDeptIds.length === 0) {
|
||||||
|
this.$modal.msgWarning("未检测到排序修改")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
updateDeptSort({ deptIds: changedDeptIds.join(","), orderNums: changedOrderNums.join(",") }).then(() => {
|
||||||
|
this.$modal.msgSuccess("排序保存成功")
|
||||||
|
this.recordOriginalOrders(this.deptList)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
handleDelete(row) {
|
||||||
|
this.$modal.confirm('是否确认删除名称为"' + row.deptName + '"的数据项?').then(function() {
|
||||||
|
return delDept(row.deptId)
|
||||||
|
}).then(() => {
|
||||||
|
this.getList()
|
||||||
|
this.$modal.msgSuccess("删除成功")
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.system-dept ::v-deep .el-table ::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.system-dept ::v-deep .el-table {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
.system-dept ::v-deep .el-table__body-wrapper::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.system-dept ::v-deep .el-table__body-wrapper {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,433 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container system-dict-data">
|
||||||
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||||
|
<el-form-item label="字典名称" prop="dictType">
|
||||||
|
<el-select v-model="queryParams.dictType">
|
||||||
|
<el-option
|
||||||
|
v-for="item in typeOptions"
|
||||||
|
:key="item.dictId"
|
||||||
|
:label="item.dictName"
|
||||||
|
:value="item.dictType"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="字典标签" prop="dictLabel">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.dictLabel"
|
||||||
|
placeholder="请输入字典标签"
|
||||||
|
clearable
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="停用" prop="status">
|
||||||
|
<el-radio-group v-model="queryParams.status">
|
||||||
|
<el-radio label="0">否</el-radio>
|
||||||
|
<el-radio label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="el-icon-plus"
|
||||||
|
size="mini"
|
||||||
|
@click="handleAdd"
|
||||||
|
v-hasPermi="['system:dict:add']"
|
||||||
|
>新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
plain
|
||||||
|
icon="el-icon-edit"
|
||||||
|
size="mini"
|
||||||
|
:disabled="single"
|
||||||
|
@click="handleUpdate"
|
||||||
|
v-hasPermi="['system:dict:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
plain
|
||||||
|
icon="el-icon-delete"
|
||||||
|
size="mini"
|
||||||
|
:disabled="multiple"
|
||||||
|
@click="handleDelete"
|
||||||
|
v-hasPermi="['system:dict:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="warning"
|
||||||
|
plain
|
||||||
|
icon="el-icon-download"
|
||||||
|
size="mini"
|
||||||
|
@click="handleExport"
|
||||||
|
v-hasPermi="['system:dict:export']"
|
||||||
|
>导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
icon="el-icon-close"
|
||||||
|
size="mini"
|
||||||
|
@click="handleClose"
|
||||||
|
>关闭</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="dataList" :height="tableHeight" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="字典编码" align="center" prop="dictCode" />
|
||||||
|
<el-table-column label="字典标签" align="center" prop="dictLabel">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span v-if="(scope.row.listClass == '' || scope.row.listClass == 'default') && (scope.row.cssClass == '' || scope.row.cssClass == null)">{{ scope.row.dictLabel }}</span>
|
||||||
|
<el-tag v-else :type="scope.row.listClass == 'primary' ? '' : scope.row.listClass" :class="scope.row.cssClass">{{ scope.row.dictLabel }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="字典键值" align="center" prop="dictValue" />
|
||||||
|
<el-table-column label="字典排序" align="center" prop="dictSort" />
|
||||||
|
<el-table-column label="状态" align="center" prop="status">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
|
||||||
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-edit"
|
||||||
|
@click="handleUpdate(scope.row)"
|
||||||
|
v-hasPermi="['system:dict:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
@click="handleDelete(scope.row)"
|
||||||
|
v-hasPermi="['system:dict:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination
|
||||||
|
v-show="total>0"
|
||||||
|
:total="total"
|
||||||
|
:page.sync="queryParams.pageNum"
|
||||||
|
:limit.sync="queryParams.pageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 添加或修改参数配置对话框 -->
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="字典类型">
|
||||||
|
<el-input v-model="form.dictType" :disabled="true" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="数据标签" prop="dictLabel">
|
||||||
|
<el-input v-model="form.dictLabel" placeholder="请输入数据标签" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="数据键值" prop="dictValue">
|
||||||
|
<el-input v-model="form.dictValue" placeholder="请输入数据键值" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="样式属性" prop="cssClass">
|
||||||
|
<el-input v-model="form.cssClass" placeholder="请输入样式属性" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="显示排序" prop="dictSort">
|
||||||
|
<el-input-number v-model="form.dictSort" controls-position="right" :min="0" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="回显样式" prop="listClass">
|
||||||
|
<el-select v-model="form.listClass">
|
||||||
|
<el-option
|
||||||
|
v-for="item in listClassOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label + '(' + item.value + ')'"
|
||||||
|
:value="item.value"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态" prop="status">
|
||||||
|
<el-radio-group v-model="form.status">
|
||||||
|
<el-radio
|
||||||
|
v-for="dict in dict.type.sys_normal_disable"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.value"
|
||||||
|
>{{dict.label}}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listData, getData, delData, addData, updateData } from "@/api/system/dict/data"
|
||||||
|
import { optionselect as getDictOptionselect, getType } from "@/api/system/dict/type"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Data",
|
||||||
|
dicts: ['sys_normal_disable'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 遮罩层
|
||||||
|
loading: true,
|
||||||
|
// 选中数组
|
||||||
|
ids: [],
|
||||||
|
// 非单个禁用
|
||||||
|
single: true,
|
||||||
|
// 非多个禁用
|
||||||
|
multiple: true,
|
||||||
|
// 显示搜索条件
|
||||||
|
showSearch: true,
|
||||||
|
// 表格高度
|
||||||
|
tableHeight: window.innerHeight - 240,
|
||||||
|
// 总条数
|
||||||
|
total: 0,
|
||||||
|
// 字典表格数据
|
||||||
|
dataList: [],
|
||||||
|
// 默认字典类型
|
||||||
|
defaultDictType: "",
|
||||||
|
// 弹出层标题
|
||||||
|
title: "",
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
// 数据标签回显样式
|
||||||
|
listClassOptions: [
|
||||||
|
{
|
||||||
|
value: "default",
|
||||||
|
label: "默认"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "primary",
|
||||||
|
label: "主要"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "success",
|
||||||
|
label: "成功"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "info",
|
||||||
|
label: "信息"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "warning",
|
||||||
|
label: "警告"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "danger",
|
||||||
|
label: "危险"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 类型数据字典
|
||||||
|
typeOptions: [],
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
dictType: undefined,
|
||||||
|
dictLabel: undefined,
|
||||||
|
status: '0'
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
// 表单校验
|
||||||
|
rules: {
|
||||||
|
dictLabel: [
|
||||||
|
{ required: true, message: "数据标签不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
dictValue: [
|
||||||
|
{ required: true, message: "数据键值不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
dictSort: [
|
||||||
|
{ required: true, message: "数据顺序不能为空", trigger: "blur" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
const dictId = this.$route.params && this.$route.params.dictId
|
||||||
|
this.getType(dictId)
|
||||||
|
this.getTypeList()
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getTableHeight()
|
||||||
|
window.addEventListener('resize', this.getTableHeight)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
window.removeEventListener('resize', this.getTableHeight)
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
showSearch() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.getTableHeight()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getTableHeight() {
|
||||||
|
const offset = this.showSearch ? 240 : 190
|
||||||
|
this.tableHeight = window.innerHeight - offset
|
||||||
|
},
|
||||||
|
/** 查询字典类型详细 */
|
||||||
|
getType(dictId) {
|
||||||
|
getType(dictId).then(response => {
|
||||||
|
this.queryParams.dictType = response.data.dictType
|
||||||
|
this.defaultDictType = response.data.dictType
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 查询字典类型列表 */
|
||||||
|
getTypeList() {
|
||||||
|
getDictOptionselect().then(response => {
|
||||||
|
this.typeOptions = response.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 查询字典数据列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
listData(this.queryParams).then(response => {
|
||||||
|
this.dataList = response.rows
|
||||||
|
this.total = response.total
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 取消按钮
|
||||||
|
cancel() {
|
||||||
|
this.open = false
|
||||||
|
this.reset()
|
||||||
|
},
|
||||||
|
// 表单重置
|
||||||
|
reset() {
|
||||||
|
this.form = {
|
||||||
|
dictCode: undefined,
|
||||||
|
dictLabel: undefined,
|
||||||
|
dictValue: undefined,
|
||||||
|
cssClass: undefined,
|
||||||
|
listClass: 'default',
|
||||||
|
dictSort: 0,
|
||||||
|
status: "0",
|
||||||
|
remark: undefined
|
||||||
|
}
|
||||||
|
this.resetForm("form")
|
||||||
|
},
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
/** 返回按钮操作 */
|
||||||
|
handleClose() {
|
||||||
|
const obj = { path: "/system/dict" }
|
||||||
|
this.$tab.closeOpenPage(obj)
|
||||||
|
},
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
resetQuery() {
|
||||||
|
this.resetForm("queryForm")
|
||||||
|
this.queryParams.dictType = this.defaultDictType
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
handleAdd() {
|
||||||
|
this.reset()
|
||||||
|
this.open = true
|
||||||
|
this.title = "添加字典数据"
|
||||||
|
this.form.dictType = this.queryParams.dictType
|
||||||
|
},
|
||||||
|
// 多选框选中数据
|
||||||
|
handleSelectionChange(selection) {
|
||||||
|
this.ids = selection.map(item => item.dictCode)
|
||||||
|
this.single = selection.length != 1
|
||||||
|
this.multiple = !selection.length
|
||||||
|
},
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
handleUpdate(row) {
|
||||||
|
this.reset()
|
||||||
|
const dictCode = row.dictCode || this.ids
|
||||||
|
getData(dictCode).then(response => {
|
||||||
|
this.form = response.data
|
||||||
|
this.open = true
|
||||||
|
this.title = "修改字典数据"
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 提交按钮 */
|
||||||
|
submitForm() {
|
||||||
|
this.$refs["form"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
if (this.form.dictCode != undefined) {
|
||||||
|
updateData(this.form).then(() => {
|
||||||
|
this.$store.dispatch('dict/removeDict', this.queryParams.dictType)
|
||||||
|
this.$modal.msgSuccess("修改成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
addData(this.form).then(() => {
|
||||||
|
this.$store.dispatch('dict/removeDict', this.queryParams.dictType)
|
||||||
|
this.$modal.msgSuccess("新增成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
handleDelete(row) {
|
||||||
|
const dictCodes = row.dictCode || this.ids
|
||||||
|
this.$modal.confirm('是否确认删除字典编码为"' + dictCodes + '"的数据项?').then(function() {
|
||||||
|
return delData(dictCodes)
|
||||||
|
}).then(() => {
|
||||||
|
this.getList()
|
||||||
|
this.$modal.msgSuccess("删除成功")
|
||||||
|
this.$store.dispatch('dict/removeDict', this.queryParams.dictType)
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
handleExport() {
|
||||||
|
this.download('system/dict/data/export', {
|
||||||
|
...this.queryParams
|
||||||
|
}, `data_${new Date().getTime()}.xlsx`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.system-dict-data ::v-deep .el-table ::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.system-dict-data ::v-deep .el-table {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
.system-dict-data ::v-deep .el-table__body-wrapper::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.system-dict-data ::v-deep .el-table__body-wrapper {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,403 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container system-dict">
|
||||||
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||||
|
<el-form-item label="字典名称" prop="dictName">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.dictName"
|
||||||
|
placeholder="请输入字典名称"
|
||||||
|
clearable
|
||||||
|
style="width: 240px"
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="字典类型" prop="dictType">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.dictType"
|
||||||
|
placeholder="请输入字典类型"
|
||||||
|
clearable
|
||||||
|
style="width: 240px"
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="停用" prop="status">
|
||||||
|
<el-radio-group v-model="queryParams.status">
|
||||||
|
<el-radio label="0">否</el-radio>
|
||||||
|
<el-radio label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="创建时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="dateRange"
|
||||||
|
style="width: 240px"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="-"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
></el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="el-icon-plus"
|
||||||
|
size="mini"
|
||||||
|
@click="handleAdd"
|
||||||
|
v-hasPermi="['system:dict:add']"
|
||||||
|
>新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
plain
|
||||||
|
icon="el-icon-edit"
|
||||||
|
size="mini"
|
||||||
|
:disabled="single"
|
||||||
|
@click="handleUpdate"
|
||||||
|
v-hasPermi="['system:dict:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
plain
|
||||||
|
icon="el-icon-delete"
|
||||||
|
size="mini"
|
||||||
|
:disabled="multiple"
|
||||||
|
@click="handleDelete"
|
||||||
|
v-hasPermi="['system:dict:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="warning"
|
||||||
|
plain
|
||||||
|
icon="el-icon-download"
|
||||||
|
size="mini"
|
||||||
|
@click="handleExport"
|
||||||
|
v-hasPermi="['system:dict:export']"
|
||||||
|
>导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
plain
|
||||||
|
icon="el-icon-refresh"
|
||||||
|
size="mini"
|
||||||
|
@click="handleRefreshCache"
|
||||||
|
v-hasPermi="['system:dict:remove']"
|
||||||
|
>刷新缓存</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="typeList" :height="tableHeight" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="字典编号" align="center" prop="dictId" />
|
||||||
|
<el-table-column label="字典名称" align="center" prop="dictName" :show-overflow-tooltip="true" />
|
||||||
|
<el-table-column label="字典类型" align="center" :show-overflow-tooltip="true">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<a class="link-type" style="cursor:pointer" @click="handleViewData(scope.row)">{{ scope.row.dictType }}</a>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="状态" align="center" prop="status">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
|
||||||
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-edit"
|
||||||
|
@click="handleUpdate(scope.row)"
|
||||||
|
v-hasPermi="['system:dict:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-s-operation"
|
||||||
|
@click="handleDataList(scope.row)"
|
||||||
|
v-hasPermi="['system:dict:edit']"
|
||||||
|
>列表</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
@click="handleDelete(scope.row)"
|
||||||
|
v-hasPermi="['system:dict:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination
|
||||||
|
v-show="total>0"
|
||||||
|
:total="total"
|
||||||
|
:page.sync="queryParams.pageNum"
|
||||||
|
:limit.sync="queryParams.pageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 添加或修改参数配置对话框 -->
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||||
|
<el-form-item label="字典名称" prop="dictName">
|
||||||
|
<el-input v-model="form.dictName" placeholder="请输入字典名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="dictType">
|
||||||
|
<el-input v-model="form.dictType" placeholder="请输入字典类型" maxlength="100" />
|
||||||
|
<span slot="label">
|
||||||
|
<el-tooltip content="数据存储中的Key值,如:sys_user_sex" placement="top">
|
||||||
|
<i class="el-icon-question"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
字典类型
|
||||||
|
</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态" prop="status">
|
||||||
|
<el-radio-group v-model="form.status">
|
||||||
|
<el-radio
|
||||||
|
v-for="dict in dict.type.sys_normal_disable"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.value"
|
||||||
|
>{{dict.label}}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<dict-data-drawer :visible.sync="drawerVisible" :row="drawerRow" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import DictDataDrawer from './detail'
|
||||||
|
import { listType, getType, delType, addType, updateType, refreshCache } from "@/api/system/dict/type"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Dict",
|
||||||
|
components: { DictDataDrawer },
|
||||||
|
dicts: ['sys_normal_disable'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 遮罩层
|
||||||
|
loading: true,
|
||||||
|
// 选中数组
|
||||||
|
ids: [],
|
||||||
|
// 非单个禁用
|
||||||
|
single: true,
|
||||||
|
// 非多个禁用
|
||||||
|
multiple: true,
|
||||||
|
// 显示搜索条件
|
||||||
|
showSearch: true,
|
||||||
|
// 表格高度
|
||||||
|
tableHeight: window.innerHeight - 240,
|
||||||
|
// 总条数
|
||||||
|
total: 0,
|
||||||
|
// 字典表格数据
|
||||||
|
typeList: [],
|
||||||
|
// 弹出层标题
|
||||||
|
title: "",
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
// 字典数据抽屉状态
|
||||||
|
drawerVisible: false,
|
||||||
|
// 字典数据信息
|
||||||
|
drawerRow: {},
|
||||||
|
// 日期范围
|
||||||
|
dateRange: [],
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
dictName: undefined,
|
||||||
|
dictType: undefined,
|
||||||
|
status: '0'
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
// 表单校验
|
||||||
|
rules: {
|
||||||
|
dictName: [
|
||||||
|
{ required: true, message: "字典名称不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
dictType: [
|
||||||
|
{ required: true, message: "字典类型不能为空", trigger: "blur" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getTableHeight()
|
||||||
|
window.addEventListener('resize', this.getTableHeight)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
window.removeEventListener('resize', this.getTableHeight)
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
showSearch() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.getTableHeight()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getTableHeight() {
|
||||||
|
const offset = this.showSearch ? 240 : 190
|
||||||
|
this.tableHeight = window.innerHeight - offset
|
||||||
|
},
|
||||||
|
/** 查询字典类型列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
listType(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
|
||||||
|
this.typeList = response.rows
|
||||||
|
this.total = response.total
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
// 取消按钮
|
||||||
|
cancel() {
|
||||||
|
this.open = false
|
||||||
|
this.reset()
|
||||||
|
},
|
||||||
|
// 表单重置
|
||||||
|
reset() {
|
||||||
|
this.form = {
|
||||||
|
dictId: undefined,
|
||||||
|
dictName: undefined,
|
||||||
|
dictType: undefined,
|
||||||
|
status: "0",
|
||||||
|
remark: undefined
|
||||||
|
}
|
||||||
|
this.resetForm("form")
|
||||||
|
},
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
resetQuery() {
|
||||||
|
this.dateRange = []
|
||||||
|
this.resetForm("queryForm")
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
handleAdd() {
|
||||||
|
this.reset()
|
||||||
|
this.open = true
|
||||||
|
this.title = "添加字典类型"
|
||||||
|
},
|
||||||
|
// 多选框选中数据
|
||||||
|
handleSelectionChange(selection) {
|
||||||
|
this.ids = selection.map(item => item.dictId)
|
||||||
|
this.single = selection.length != 1
|
||||||
|
this.multiple = !selection.length
|
||||||
|
},
|
||||||
|
/** 字典数据抽屉显示信息 */
|
||||||
|
handleViewData(row) {
|
||||||
|
this.drawerRow = row
|
||||||
|
this.drawerVisible = true
|
||||||
|
},
|
||||||
|
/** 字典数据列表页面 */
|
||||||
|
handleDataList(row) {
|
||||||
|
this.$tab.openPage("字典数据", '/system/dict-data/index/' + row.dictId)
|
||||||
|
},
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
handleUpdate(row) {
|
||||||
|
this.reset()
|
||||||
|
const dictId = row.dictId || this.ids
|
||||||
|
getType(dictId).then(response => {
|
||||||
|
this.form = response.data
|
||||||
|
this.open = true
|
||||||
|
this.title = "修改字典类型"
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 提交按钮 */
|
||||||
|
submitForm() {
|
||||||
|
this.$refs["form"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
if (this.form.dictId != undefined) {
|
||||||
|
updateType(this.form).then(() => {
|
||||||
|
this.$modal.msgSuccess("修改成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
addType(this.form).then(() => {
|
||||||
|
this.$modal.msgSuccess("新增成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
handleDelete(row) {
|
||||||
|
const dictIds = row.dictId || this.ids
|
||||||
|
this.$modal.confirm('是否确认删除字典编号为"' + dictIds + '"的数据项?').then(function() {
|
||||||
|
return delType(dictIds)
|
||||||
|
}).then(() => {
|
||||||
|
this.getList()
|
||||||
|
this.$modal.msgSuccess("删除成功")
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
handleExport() {
|
||||||
|
this.download('system/dict/type/export', {
|
||||||
|
...this.queryParams
|
||||||
|
}, `type_${new Date().getTime()}.xlsx`)
|
||||||
|
},
|
||||||
|
/** 刷新缓存按钮操作 */
|
||||||
|
handleRefreshCache() {
|
||||||
|
refreshCache().then(() => {
|
||||||
|
this.$modal.msgSuccess("刷新成功")
|
||||||
|
this.$store.dispatch('dict/cleanDict')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.system-dict ::v-deep .el-table ::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.system-dict ::v-deep .el-table {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
.system-dict ::v-deep .el-table__body-wrapper::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.system-dict ::v-deep .el-table__body-wrapper {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,568 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container system-menu">
|
||||||
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
|
||||||
|
<el-form-item label="菜单名称" prop="menuName">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.menuName"
|
||||||
|
placeholder="请输入菜单名称"
|
||||||
|
clearable
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="停用" prop="status">
|
||||||
|
<el-radio-group v-model="queryParams.status">
|
||||||
|
<el-radio label="0">否</el-radio>
|
||||||
|
<el-radio label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="el-icon-plus"
|
||||||
|
size="mini"
|
||||||
|
@click="handleAdd"
|
||||||
|
v-hasPermi="['system:menu:add']"
|
||||||
|
>新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="warning"
|
||||||
|
plain
|
||||||
|
icon="el-icon-check"
|
||||||
|
size="mini"
|
||||||
|
@click="handleSaveSort"
|
||||||
|
v-hasPermi="['system:menu:edit']"
|
||||||
|
>保存排序</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="info"
|
||||||
|
plain
|
||||||
|
icon="el-icon-sort"
|
||||||
|
size="mini"
|
||||||
|
@click="toggleExpandAll"
|
||||||
|
>展开/折叠</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table
|
||||||
|
v-if="refreshTable"
|
||||||
|
v-loading="loading"
|
||||||
|
:data="menuList"
|
||||||
|
:height="tableHeight"
|
||||||
|
row-key="menuId"
|
||||||
|
:default-expand-all="isExpandAll"
|
||||||
|
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
|
||||||
|
>
|
||||||
|
<el-table-column prop="menuName" label="菜单名称" :show-overflow-tooltip="true" width="220">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<svg-icon :icon-class="scope.row.icon" />
|
||||||
|
<span class="ml5">{{ scope.row.menuName }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="menuName" label="类型" :show-overflow-tooltip="true" width="100">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag v-if="scope.row.menuType === 'M' && scope.row.isFrame === '0'" type="danger" size="small">外链</el-tag>
|
||||||
|
<el-tag v-else-if="scope.row.menuType === 'M'" type="primary" size="small">目录</el-tag>
|
||||||
|
<el-tag v-else-if="scope.row.menuType === 'C' && scope.row.isFrame === '0'" type="danger" size="small">外链</el-tag>
|
||||||
|
<el-tag v-else-if="scope.row.menuType === 'C'" type="success" size="small">菜单</el-tag>
|
||||||
|
<el-tag v-else-if="scope.row.menuType === 'F'" type="warning" size="small">按钮</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="orderNum" label="排序" width="200">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-input-number v-model="scope.row.orderNum" controls-position="right" :min="0" size="mini" style="width: 88px" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="perms" label="权限标识" :show-overflow-tooltip="true" />
|
||||||
|
<el-table-column prop="component" label="组件路径" :show-overflow-tooltip="true" />
|
||||||
|
<el-table-column prop="status" label="状态" width="80">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-edit"
|
||||||
|
@click="handleUpdate(scope.row)"
|
||||||
|
v-hasPermi="['system:menu:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-plus"
|
||||||
|
@click="handleAdd(scope.row)"
|
||||||
|
v-hasPermi="['system:menu:add']"
|
||||||
|
>新增</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
@click="handleDelete(scope.row)"
|
||||||
|
v-hasPermi="['system:menu:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 添加或修改菜单对话框 -->
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="680px" append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="上级菜单" prop="parentId">
|
||||||
|
<treeselect
|
||||||
|
v-model="form.parentId"
|
||||||
|
:options="menuOptions"
|
||||||
|
:normalizer="normalizer"
|
||||||
|
:show-count="true"
|
||||||
|
placeholder="选择上级菜单"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="菜单类型" prop="menuType">
|
||||||
|
<el-radio-group v-model="form.menuType">
|
||||||
|
<el-radio label="M">目录</el-radio>
|
||||||
|
<el-radio label="C">菜单</el-radio>
|
||||||
|
<el-radio label="F">按钮</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12" v-if="form.menuType != 'F'">
|
||||||
|
<el-form-item label="菜单图标" prop="icon">
|
||||||
|
<el-popover
|
||||||
|
placement="bottom-start"
|
||||||
|
width="460"
|
||||||
|
trigger="click"
|
||||||
|
@show="$refs['iconSelect'].reset()"
|
||||||
|
>
|
||||||
|
<IconSelect ref="iconSelect" @selected="selected" :active-icon="form.icon" />
|
||||||
|
<el-input slot="reference" v-model="form.icon" placeholder="点击选择图标" readonly>
|
||||||
|
<svg-icon
|
||||||
|
v-if="form.icon"
|
||||||
|
slot="prefix"
|
||||||
|
:icon-class="form.icon"
|
||||||
|
style="width: 25px;"
|
||||||
|
/>
|
||||||
|
<i v-else slot="prefix" class="el-icon-search el-input__icon" />
|
||||||
|
</el-input>
|
||||||
|
</el-popover>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="显示排序" prop="orderNum">
|
||||||
|
<el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="菜单名称" prop="menuName">
|
||||||
|
<el-input v-model="form.menuName" placeholder="请输入菜单名称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12" v-if="form.menuType == 'C'">
|
||||||
|
<el-form-item prop="routeName">
|
||||||
|
<el-input v-model="form.routeName" placeholder="请输入路由名称" />
|
||||||
|
<span slot="label">
|
||||||
|
<el-tooltip content="默认不填则和路由地址相同:如地址为:`user`,则名称为`User`(注意:为避免名字的冲突,特殊情况下请自定义,保证唯一性)" placement="top">
|
||||||
|
<i class="el-icon-question"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
路由名称
|
||||||
|
</span>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12" v-if="form.menuType != 'F'">
|
||||||
|
<el-form-item prop="isFrame">
|
||||||
|
<span slot="label">
|
||||||
|
<el-tooltip content="选择是外链则路由地址需要以`http(s)://`开头" placement="top">
|
||||||
|
<i class="el-icon-question"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
是否外链
|
||||||
|
</span>
|
||||||
|
<el-radio-group v-model="form.isFrame">
|
||||||
|
<el-radio label="0">是</el-radio>
|
||||||
|
<el-radio label="1">否</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12" v-if="form.menuType != 'F'">
|
||||||
|
<el-form-item prop="path">
|
||||||
|
<span slot="label">
|
||||||
|
<el-tooltip content="访问的路由地址,如:`user`,如外网地址需内链访问则以`http(s)://`开头" placement="top">
|
||||||
|
<i class="el-icon-question"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
路由地址
|
||||||
|
</span>
|
||||||
|
<el-input v-model="form.path" placeholder="请输入路由地址" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12" v-if="form.menuType == 'C'">
|
||||||
|
<el-form-item prop="component">
|
||||||
|
<span slot="label">
|
||||||
|
<el-tooltip content="访问的组件路径,如:`system/user/index`,默认在`views`目录下" placement="top">
|
||||||
|
<i class="el-icon-question"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
组件路径
|
||||||
|
</span>
|
||||||
|
<el-input v-model="form.component" placeholder="请输入组件路径" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12" v-if="form.menuType != 'M'">
|
||||||
|
<el-form-item prop="perms">
|
||||||
|
<el-input v-model="form.perms" placeholder="请输入权限标识" maxlength="100" />
|
||||||
|
<span slot="label">
|
||||||
|
<el-tooltip content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasPermi('system:user:list')`)" placement="top">
|
||||||
|
<i class="el-icon-question"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
权限字符
|
||||||
|
</span>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12" v-if="form.menuType == 'C'">
|
||||||
|
<el-form-item prop="query">
|
||||||
|
<el-input v-model="form.query" placeholder="请输入路由参数" maxlength="255" />
|
||||||
|
<span slot="label">
|
||||||
|
<el-tooltip content='访问路由的默认传递参数,如:`{"id": 1, "name": "ry"}`' placement="top">
|
||||||
|
<i class="el-icon-question"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
路由参数
|
||||||
|
</span>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12" v-if="form.menuType == 'C'">
|
||||||
|
<el-form-item prop="isCache">
|
||||||
|
<span slot="label">
|
||||||
|
<el-tooltip content="选择是则会被`keep-alive`缓存,需要匹配组件的`name`和地址保持一致" placement="top">
|
||||||
|
<i class="el-icon-question"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
是否缓存
|
||||||
|
</span>
|
||||||
|
<el-radio-group v-model="form.isCache">
|
||||||
|
<el-radio label="0">缓存</el-radio>
|
||||||
|
<el-radio label="1">不缓存</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12" v-if="form.menuType != 'F'">
|
||||||
|
<el-form-item prop="visible">
|
||||||
|
<span slot="label">
|
||||||
|
<el-tooltip content="选择隐藏则路由将不会出现在侧边栏,但仍然可以访问" placement="top">
|
||||||
|
<i class="el-icon-question"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
显示状态
|
||||||
|
</span>
|
||||||
|
<el-radio-group v-model="form.visible">
|
||||||
|
<el-radio
|
||||||
|
v-for="dict in dict.type.sys_show_hide"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.value"
|
||||||
|
>{{dict.label}}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item prop="status">
|
||||||
|
<span slot="label">
|
||||||
|
<el-tooltip content="选择停用则路由将不会出现在侧边栏,也不能被访问" placement="top">
|
||||||
|
<i class="el-icon-question"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
菜单状态
|
||||||
|
</span>
|
||||||
|
<el-radio-group v-model="form.status">
|
||||||
|
<el-radio
|
||||||
|
v-for="dict in dict.type.sys_normal_disable"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.value"
|
||||||
|
>{{dict.label}}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listMenu, getMenu, delMenu, addMenu, updateMenu, updateMenuSort } from "@/api/system/menu"
|
||||||
|
import Treeselect from "@riophae/vue-treeselect"
|
||||||
|
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
|
||||||
|
import IconSelect from "@/components/IconSelect"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Menu",
|
||||||
|
dicts: ['sys_show_hide', 'sys_normal_disable'],
|
||||||
|
components: { Treeselect, IconSelect },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 遮罩层
|
||||||
|
loading: true,
|
||||||
|
// 显示搜索条件
|
||||||
|
showSearch: true,
|
||||||
|
// 表格高度
|
||||||
|
tableHeight: window.innerHeight - 240,
|
||||||
|
// 菜单表格树数据
|
||||||
|
menuList: [],
|
||||||
|
// 菜单树选项
|
||||||
|
menuOptions: [],
|
||||||
|
// 弹出层标题
|
||||||
|
title: "",
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
// 是否展开,默认全部折叠
|
||||||
|
isExpandAll: false,
|
||||||
|
// 重新渲染表格状态
|
||||||
|
refreshTable: true,
|
||||||
|
// 记录原始排序,用于对比变更
|
||||||
|
originalOrders: {},
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
menuName: undefined,
|
||||||
|
visible: undefined,
|
||||||
|
status: '0'
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
// 表单校验
|
||||||
|
rules: {
|
||||||
|
menuName: [
|
||||||
|
{ required: true, message: "菜单名称不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
orderNum: [
|
||||||
|
{ required: true, message: "菜单顺序不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
path: [
|
||||||
|
{ required: true, message: "路由地址不能为空", trigger: "blur" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getTableHeight()
|
||||||
|
window.addEventListener('resize', this.getTableHeight)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
window.removeEventListener('resize', this.getTableHeight)
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
showSearch() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.getTableHeight()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getTableHeight() {
|
||||||
|
const offset = this.showSearch ? 240 : 190
|
||||||
|
this.tableHeight = window.innerHeight - offset
|
||||||
|
},
|
||||||
|
// 选择图标
|
||||||
|
selected(name) {
|
||||||
|
this.form.icon = name
|
||||||
|
},
|
||||||
|
/** 查询菜单列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
listMenu(this.queryParams).then(response => {
|
||||||
|
this.menuList = this.handleTree(response.data, "menuId")
|
||||||
|
// 记录原始排序值
|
||||||
|
this.recordOriginalOrders(this.menuList)
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 转换菜单数据结构 */
|
||||||
|
normalizer(node) {
|
||||||
|
if (node.children && !node.children.length) {
|
||||||
|
delete node.children
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
id: node.menuId,
|
||||||
|
label: node.menuName,
|
||||||
|
children: node.children
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 查询菜单下拉树结构 */
|
||||||
|
getTreeselect() {
|
||||||
|
listMenu().then(response => {
|
||||||
|
this.menuOptions = []
|
||||||
|
const menu = { menuId: 0, menuName: '主类目', children: [] }
|
||||||
|
menu.children = this.handleTree(response.data, "menuId")
|
||||||
|
this.menuOptions.push(menu)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 取消按钮
|
||||||
|
cancel() {
|
||||||
|
this.open = false
|
||||||
|
this.reset()
|
||||||
|
},
|
||||||
|
// 表单重置
|
||||||
|
reset() {
|
||||||
|
this.form = {
|
||||||
|
menuId: undefined,
|
||||||
|
parentId: 0,
|
||||||
|
menuName: undefined,
|
||||||
|
icon: undefined,
|
||||||
|
menuType: "M",
|
||||||
|
orderNum: undefined,
|
||||||
|
isFrame: "1",
|
||||||
|
isCache: "0",
|
||||||
|
visible: "0",
|
||||||
|
status: "0"
|
||||||
|
}
|
||||||
|
this.resetForm("form")
|
||||||
|
},
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery() {
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
resetQuery() {
|
||||||
|
this.resetForm("queryForm")
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
handleAdd(row) {
|
||||||
|
this.reset()
|
||||||
|
this.getTreeselect()
|
||||||
|
if (row != null && row.menuId) {
|
||||||
|
this.form.parentId = row.menuId
|
||||||
|
} else {
|
||||||
|
this.form.parentId = 0
|
||||||
|
}
|
||||||
|
this.open = true
|
||||||
|
this.title = "添加菜单"
|
||||||
|
},
|
||||||
|
/** 展开/折叠操作 */
|
||||||
|
toggleExpandAll() {
|
||||||
|
this.refreshTable = false
|
||||||
|
this.isExpandAll = !this.isExpandAll
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.refreshTable = true
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
handleUpdate(row) {
|
||||||
|
this.reset()
|
||||||
|
this.getTreeselect()
|
||||||
|
getMenu(row.menuId).then(response => {
|
||||||
|
this.form = response.data
|
||||||
|
this.open = true
|
||||||
|
this.title = "修改菜单"
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 提交按钮 */
|
||||||
|
submitForm() {
|
||||||
|
this.$refs["form"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
if (this.form.menuId != undefined) {
|
||||||
|
updateMenu(this.form).then(() => {
|
||||||
|
this.$modal.msgSuccess("修改成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
addMenu(this.form).then(() => {
|
||||||
|
this.$modal.msgSuccess("新增成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 递归记录原始排序 */
|
||||||
|
recordOriginalOrders(list) {
|
||||||
|
list.forEach(item => {
|
||||||
|
this.originalOrders[item.menuId] = item.orderNum
|
||||||
|
if (item.children && item.children.length) {
|
||||||
|
this.recordOriginalOrders(item.children)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 保存排序 */
|
||||||
|
handleSaveSort() {
|
||||||
|
const changedMenuIds = []
|
||||||
|
const changedOrderNums = []
|
||||||
|
const collectChanged = (list) => {
|
||||||
|
list.forEach(item => {
|
||||||
|
if (String(this.originalOrders[item.menuId]) !== String(item.orderNum)) {
|
||||||
|
changedMenuIds.push(item.menuId)
|
||||||
|
changedOrderNums.push(item.orderNum)
|
||||||
|
}
|
||||||
|
if (item.children && item.children.length) {
|
||||||
|
collectChanged(item.children)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
collectChanged(this.menuList)
|
||||||
|
if (changedMenuIds.length === 0) {
|
||||||
|
this.$modal.msgWarning("未检测到排序修改")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
updateMenuSort({ menuIds: changedMenuIds.join(","), orderNums: changedOrderNums.join(",") }).then(() => {
|
||||||
|
this.$modal.msgSuccess("排序保存成功")
|
||||||
|
this.recordOriginalOrders(this.menuList)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
handleDelete(row) {
|
||||||
|
this.$modal.confirm('是否确认删除名称为"' + row.menuName + '"的数据项?').then(function() {
|
||||||
|
return delMenu(row.menuId)
|
||||||
|
}).then(() => {
|
||||||
|
this.getList()
|
||||||
|
this.$modal.msgSuccess("删除成功")
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.system-menu ::v-deep .el-table ::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.system-menu ::v-deep .el-table {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
.system-menu ::v-deep .el-table__body-wrapper::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.system-menu ::v-deep .el-table__body-wrapper {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,342 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container system-post">
|
||||||
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||||
|
<el-form-item label="岗位编码" prop="postCode">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.postCode"
|
||||||
|
placeholder="请输入岗位编码"
|
||||||
|
clearable
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="岗位名称" prop="postName">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.postName"
|
||||||
|
placeholder="请输入岗位名称"
|
||||||
|
clearable
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="停用" prop="status">
|
||||||
|
<el-radio-group v-model="queryParams.status">
|
||||||
|
<el-radio label="0">否</el-radio>
|
||||||
|
<el-radio label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="el-icon-plus"
|
||||||
|
size="mini"
|
||||||
|
@click="handleAdd"
|
||||||
|
v-hasPermi="['system:post:add']"
|
||||||
|
>新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
plain
|
||||||
|
icon="el-icon-edit"
|
||||||
|
size="mini"
|
||||||
|
:disabled="single"
|
||||||
|
@click="handleUpdate"
|
||||||
|
v-hasPermi="['system:post:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
plain
|
||||||
|
icon="el-icon-delete"
|
||||||
|
size="mini"
|
||||||
|
:disabled="multiple"
|
||||||
|
@click="handleDelete"
|
||||||
|
v-hasPermi="['system:post:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="warning"
|
||||||
|
plain
|
||||||
|
icon="el-icon-download"
|
||||||
|
size="mini"
|
||||||
|
@click="handleExport"
|
||||||
|
v-hasPermi="['system:post:export']"
|
||||||
|
>导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="postList" @selection-change="handleSelectionChange" :height="tableHeight">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="岗位编号" align="center" prop="postId" />
|
||||||
|
<el-table-column label="岗位编码" align="center" prop="postCode" />
|
||||||
|
<el-table-column label="岗位名称" align="center" prop="postName" />
|
||||||
|
<el-table-column label="岗位排序" align="center" prop="postSort" />
|
||||||
|
<el-table-column label="状态" align="center" prop="status">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-edit"
|
||||||
|
@click="handleUpdate(scope.row)"
|
||||||
|
v-hasPermi="['system:post:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
@click="handleDelete(scope.row)"
|
||||||
|
v-hasPermi="['system:post:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination
|
||||||
|
v-show="total>0"
|
||||||
|
:total="total"
|
||||||
|
:page.sync="queryParams.pageNum"
|
||||||
|
:limit.sync="queryParams.pageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 添加或修改岗位对话框 -->
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="岗位名称" prop="postName">
|
||||||
|
<el-input v-model="form.postName" placeholder="请输入岗位名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="岗位编码" prop="postCode">
|
||||||
|
<el-input v-model="form.postCode" placeholder="请输入编码名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="岗位顺序" prop="postSort">
|
||||||
|
<el-input-number v-model="form.postSort" controls-position="right" :min="0" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="岗位状态" prop="status">
|
||||||
|
<el-radio-group v-model="form.status">
|
||||||
|
<el-radio
|
||||||
|
v-for="dict in dict.type.sys_normal_disable"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.value"
|
||||||
|
>{{dict.label}}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listPost, getPost, delPost, addPost, updatePost } from "@/api/system/post"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Post",
|
||||||
|
dicts: ['sys_normal_disable'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 遮罩层
|
||||||
|
loading: true,
|
||||||
|
// 表格高度
|
||||||
|
tableHeight: window.innerHeight - 240,
|
||||||
|
// 选中数组
|
||||||
|
ids: [],
|
||||||
|
// 非单个禁用
|
||||||
|
single: true,
|
||||||
|
// 非多个禁用
|
||||||
|
multiple: true,
|
||||||
|
// 显示搜索条件
|
||||||
|
showSearch: true,
|
||||||
|
// 总条数
|
||||||
|
total: 0,
|
||||||
|
// 岗位表格数据
|
||||||
|
postList: [],
|
||||||
|
// 弹出层标题
|
||||||
|
title: "",
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
postCode: undefined,
|
||||||
|
postName: undefined,
|
||||||
|
status: '0'
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
// 表单校验
|
||||||
|
rules: {
|
||||||
|
postName: [
|
||||||
|
{ required: true, message: "岗位名称不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
postCode: [
|
||||||
|
{ required: true, message: "岗位编码不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
postSort: [
|
||||||
|
{ required: true, message: "岗位顺序不能为空", trigger: "blur" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getTableHeight()
|
||||||
|
window.addEventListener('resize', this.getTableHeight)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
window.removeEventListener('resize', this.getTableHeight)
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
showSearch() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.getTableHeight()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 获取表格高度 */
|
||||||
|
getTableHeight() {
|
||||||
|
const offset = this.showSearch ? 240 : 190
|
||||||
|
this.tableHeight = window.innerHeight - offset
|
||||||
|
},
|
||||||
|
/** 查询岗位列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
listPost(this.queryParams).then(response => {
|
||||||
|
this.postList = response.rows
|
||||||
|
this.total = response.total
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 取消按钮
|
||||||
|
cancel() {
|
||||||
|
this.open = false
|
||||||
|
this.reset()
|
||||||
|
},
|
||||||
|
// 表单重置
|
||||||
|
reset() {
|
||||||
|
this.form = {
|
||||||
|
postId: undefined,
|
||||||
|
postCode: undefined,
|
||||||
|
postName: undefined,
|
||||||
|
postSort: 0,
|
||||||
|
status: "0",
|
||||||
|
remark: undefined
|
||||||
|
}
|
||||||
|
this.resetForm("form")
|
||||||
|
},
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
resetQuery() {
|
||||||
|
this.resetForm("queryForm")
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
// 多选框选中数据
|
||||||
|
handleSelectionChange(selection) {
|
||||||
|
this.ids = selection.map(item => item.postId)
|
||||||
|
this.single = selection.length != 1
|
||||||
|
this.multiple = !selection.length
|
||||||
|
},
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
handleAdd() {
|
||||||
|
this.reset()
|
||||||
|
this.open = true
|
||||||
|
this.title = "添加岗位"
|
||||||
|
},
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
handleUpdate(row) {
|
||||||
|
this.reset()
|
||||||
|
const postId = row.postId || this.ids
|
||||||
|
getPost(postId).then(response => {
|
||||||
|
this.form = response.data
|
||||||
|
this.open = true
|
||||||
|
this.title = "修改岗位"
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 提交按钮 */
|
||||||
|
submitForm() {
|
||||||
|
this.$refs["form"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
if (this.form.postId != undefined) {
|
||||||
|
updatePost(this.form).then(() => {
|
||||||
|
this.$modal.msgSuccess("修改成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
addPost(this.form).then(() => {
|
||||||
|
this.$modal.msgSuccess("新增成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
handleDelete(row) {
|
||||||
|
const postIds = row.postId || this.ids
|
||||||
|
this.$modal.confirm('是否确认删除岗位编号为"' + postIds + '"的数据项?').then(function() {
|
||||||
|
return delPost(postIds)
|
||||||
|
}).then(() => {
|
||||||
|
this.getList()
|
||||||
|
this.$modal.msgSuccess("删除成功")
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
handleExport() {
|
||||||
|
this.download('system/post/export', {
|
||||||
|
...this.queryParams
|
||||||
|
}, `post_${new Date().getTime()}.xlsx`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.system-post ::v-deep .el-table ::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.system-post ::v-deep .el-table {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
.system-post ::v-deep .el-table__body-wrapper::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.system-post ::v-deep .el-table__body-wrapper {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,633 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container system-role">
|
||||||
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
|
||||||
|
<el-form-item label="角色名称" prop="roleName">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.roleName"
|
||||||
|
placeholder="请输入角色名称"
|
||||||
|
clearable
|
||||||
|
style="width: 240px"
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="权限字符" prop="roleKey">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.roleKey"
|
||||||
|
placeholder="请输入权限字符"
|
||||||
|
clearable
|
||||||
|
style="width: 240px"
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="停用" prop="status">
|
||||||
|
<el-radio-group v-model="queryParams.status">
|
||||||
|
<el-radio label="0">否</el-radio>
|
||||||
|
<el-radio label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="创建时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="dateRange"
|
||||||
|
style="width: 240px"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="-"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
></el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="el-icon-plus"
|
||||||
|
size="mini"
|
||||||
|
@click="handleAdd"
|
||||||
|
v-hasPermi="['system:role:add']"
|
||||||
|
>新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
plain
|
||||||
|
icon="el-icon-edit"
|
||||||
|
size="mini"
|
||||||
|
:disabled="single"
|
||||||
|
@click="handleUpdate"
|
||||||
|
v-hasPermi="['system:role:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
plain
|
||||||
|
icon="el-icon-delete"
|
||||||
|
size="mini"
|
||||||
|
:disabled="multiple"
|
||||||
|
@click="handleDelete"
|
||||||
|
v-hasPermi="['system:role:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="warning"
|
||||||
|
plain
|
||||||
|
icon="el-icon-download"
|
||||||
|
size="mini"
|
||||||
|
@click="handleExport"
|
||||||
|
v-hasPermi="['system:role:export']"
|
||||||
|
>导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="roleList" @selection-change="handleSelectionChange" :height="tableHeight">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="角色编号" prop="roleId" width="120" />
|
||||||
|
<el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" width="150" />
|
||||||
|
<el-table-column label="权限字符" prop="roleKey" :show-overflow-tooltip="true" width="150" />
|
||||||
|
<el-table-column label="显示顺序" prop="roleSort" width="100" />
|
||||||
|
<el-table-column label="状态" align="center" width="100">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-switch
|
||||||
|
v-model="scope.row.status"
|
||||||
|
active-value="0"
|
||||||
|
inactive-value="1"
|
||||||
|
@change="handleStatusChange(scope.row)"
|
||||||
|
></el-switch>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template slot-scope="scope" v-if="scope.row.roleId !== 1">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-edit"
|
||||||
|
@click="handleUpdate(scope.row)"
|
||||||
|
v-hasPermi="['system:role:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
@click="handleDelete(scope.row)"
|
||||||
|
v-hasPermi="['system:role:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
<el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['system:role:edit']">
|
||||||
|
<el-button size="mini" type="text" icon="el-icon-d-arrow-right">更多</el-button>
|
||||||
|
<el-dropdown-menu slot="dropdown">
|
||||||
|
<el-dropdown-item command="handleDataScope" icon="el-icon-circle-check"
|
||||||
|
v-hasPermi="['system:role:edit']">数据权限</el-dropdown-item>
|
||||||
|
<el-dropdown-item command="handleAuthUser" icon="el-icon-user"
|
||||||
|
v-hasPermi="['system:role:edit']">分配用户</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</el-dropdown>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination
|
||||||
|
v-show="total>0"
|
||||||
|
:total="total"
|
||||||
|
:page.sync="queryParams.pageNum"
|
||||||
|
:limit.sync="queryParams.pageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 添加或修改角色配置对话框 -->
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||||
|
<el-form-item label="角色名称" prop="roleName">
|
||||||
|
<el-input v-model="form.roleName" placeholder="请输入角色名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="roleKey">
|
||||||
|
<span slot="label">
|
||||||
|
<el-tooltip content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasRole('admin')`)" placement="top">
|
||||||
|
<i class="el-icon-question"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
权限字符
|
||||||
|
</span>
|
||||||
|
<el-input v-model="form.roleKey" placeholder="请输入权限字符" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="角色顺序" prop="roleSort">
|
||||||
|
<el-input-number v-model="form.roleSort" controls-position="right" :min="0" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态">
|
||||||
|
<el-radio-group v-model="form.status">
|
||||||
|
<el-radio
|
||||||
|
v-for="dict in dict.type.sys_normal_disable"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.value"
|
||||||
|
>{{dict.label}}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="菜单权限">
|
||||||
|
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
|
||||||
|
<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
|
||||||
|
<el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
|
||||||
|
<el-tree
|
||||||
|
class="tree-border"
|
||||||
|
:data="menuOptions"
|
||||||
|
show-checkbox
|
||||||
|
ref="menu"
|
||||||
|
node-key="id"
|
||||||
|
:check-strictly="!form.menuCheckStrictly"
|
||||||
|
empty-text="加载中,请稍候"
|
||||||
|
:props="defaultProps"
|
||||||
|
></el-tree>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注">
|
||||||
|
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 分配角色数据权限对话框 -->
|
||||||
|
<el-dialog :title="title" :visible.sync="openDataScope" width="500px" append-to-body>
|
||||||
|
<el-form :model="form" label-width="80px">
|
||||||
|
<el-form-item label="角色名称">
|
||||||
|
<el-input v-model="form.roleName" :disabled="true" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="权限字符">
|
||||||
|
<el-input v-model="form.roleKey" :disabled="true" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="权限范围">
|
||||||
|
<el-select v-model="form.dataScope" @change="dataScopeSelectChange">
|
||||||
|
<el-option
|
||||||
|
v-for="item in dataScopeOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="数据权限" v-show="form.dataScope == 2">
|
||||||
|
<el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
|
||||||
|
<el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
|
||||||
|
<el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
|
||||||
|
<el-tree
|
||||||
|
class="tree-border"
|
||||||
|
:data="deptOptions"
|
||||||
|
show-checkbox
|
||||||
|
default-expand-all
|
||||||
|
ref="dept"
|
||||||
|
node-key="id"
|
||||||
|
:check-strictly="!form.deptCheckStrictly"
|
||||||
|
empty-text="加载中,请稍候"
|
||||||
|
:props="defaultProps"
|
||||||
|
></el-tree>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitDataScope">确 定</el-button>
|
||||||
|
<el-button @click="cancelDataScope">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listRole, getRole, delRole, addRole, updateRole, dataScope, changeRoleStatus, deptTreeSelect } from "@/api/system/role"
|
||||||
|
import { treeselect as menuTreeselect, roleMenuTreeselect } from "@/api/system/menu"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Role",
|
||||||
|
dicts: ['sys_normal_disable'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 遮罩层
|
||||||
|
loading: true,
|
||||||
|
// 表格高度
|
||||||
|
tableHeight: window.innerHeight - 240,
|
||||||
|
// 选中数组
|
||||||
|
ids: [],
|
||||||
|
// 非单个禁用
|
||||||
|
single: true,
|
||||||
|
// 非多个禁用
|
||||||
|
multiple: true,
|
||||||
|
// 显示搜索条件
|
||||||
|
showSearch: true,
|
||||||
|
// 总条数
|
||||||
|
total: 0,
|
||||||
|
// 角色表格数据
|
||||||
|
roleList: [],
|
||||||
|
// 弹出层标题
|
||||||
|
title: "",
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
// 是否显示弹出层(数据权限)
|
||||||
|
openDataScope: false,
|
||||||
|
menuExpand: false,
|
||||||
|
menuNodeAll: false,
|
||||||
|
deptExpand: true,
|
||||||
|
deptNodeAll: false,
|
||||||
|
// 日期范围
|
||||||
|
dateRange: [],
|
||||||
|
// 数据范围选项
|
||||||
|
dataScopeOptions: [
|
||||||
|
{
|
||||||
|
value: "1",
|
||||||
|
label: "全部数据权限"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "2",
|
||||||
|
label: "自定数据权限"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "3",
|
||||||
|
label: "本部门数据权限"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "4",
|
||||||
|
label: "本部门及以下数据权限"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "5",
|
||||||
|
label: "仅本人数据权限"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 菜单列表
|
||||||
|
menuOptions: [],
|
||||||
|
// 部门列表
|
||||||
|
deptOptions: [],
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
roleName: undefined,
|
||||||
|
roleKey: undefined,
|
||||||
|
status: '0'
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
defaultProps: {
|
||||||
|
children: "children",
|
||||||
|
label: "label"
|
||||||
|
},
|
||||||
|
// 表单校验
|
||||||
|
rules: {
|
||||||
|
roleName: [
|
||||||
|
{ required: true, message: "角色名称不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
roleKey: [
|
||||||
|
{ required: true, message: "权限字符不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
roleSort: [
|
||||||
|
{ required: true, message: "角色顺序不能为空", trigger: "blur" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getTableHeight()
|
||||||
|
window.addEventListener('resize', this.getTableHeight)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
window.removeEventListener('resize', this.getTableHeight)
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
showSearch() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.getTableHeight()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 获取表格高度 */
|
||||||
|
getTableHeight() {
|
||||||
|
const offset = this.showSearch ? 240 : 190
|
||||||
|
this.tableHeight = window.innerHeight - offset
|
||||||
|
},
|
||||||
|
/** 查询角色列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
listRole(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
|
||||||
|
this.roleList = response.rows
|
||||||
|
this.total = response.total
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
/** 查询菜单树结构 */
|
||||||
|
getMenuTreeselect() {
|
||||||
|
menuTreeselect().then(response => {
|
||||||
|
this.menuOptions = response.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 所有菜单节点数据
|
||||||
|
getMenuAllCheckedKeys() {
|
||||||
|
// 目前被选中的菜单节点
|
||||||
|
let checkedKeys = this.$refs.menu.getCheckedKeys()
|
||||||
|
// 半选中的菜单节点
|
||||||
|
let halfCheckedKeys = this.$refs.menu.getHalfCheckedKeys()
|
||||||
|
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
|
||||||
|
return checkedKeys
|
||||||
|
},
|
||||||
|
// 所有部门节点数据
|
||||||
|
getDeptAllCheckedKeys() {
|
||||||
|
// 目前被选中的部门节点
|
||||||
|
let checkedKeys = this.$refs.dept.getCheckedKeys()
|
||||||
|
// 半选中的部门节点
|
||||||
|
let halfCheckedKeys = this.$refs.dept.getHalfCheckedKeys()
|
||||||
|
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
|
||||||
|
return checkedKeys
|
||||||
|
},
|
||||||
|
/** 根据角色ID查询菜单树结构 */
|
||||||
|
getRoleMenuTreeselect(roleId) {
|
||||||
|
return roleMenuTreeselect(roleId).then(response => {
|
||||||
|
this.menuOptions = response.menus
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 根据角色ID查询部门树结构 */
|
||||||
|
getDeptTree(roleId) {
|
||||||
|
return deptTreeSelect(roleId).then(response => {
|
||||||
|
this.deptOptions = response.depts
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 角色状态修改
|
||||||
|
handleStatusChange(row) {
|
||||||
|
let text = row.status === "0" ? "启用" : "停用"
|
||||||
|
this.$modal.confirm('确认要"' + text + '""' + row.roleName + '"角色吗?').then(function() {
|
||||||
|
return changeRoleStatus(row.roleId, row.status)
|
||||||
|
}).then(() => {
|
||||||
|
this.$modal.msgSuccess(text + "成功")
|
||||||
|
}).catch(function() {
|
||||||
|
row.status = row.status === "0" ? "1" : "0"
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 取消按钮
|
||||||
|
cancel() {
|
||||||
|
this.open = false
|
||||||
|
this.reset()
|
||||||
|
},
|
||||||
|
// 取消按钮(数据权限)
|
||||||
|
cancelDataScope() {
|
||||||
|
this.openDataScope = false
|
||||||
|
this.reset()
|
||||||
|
},
|
||||||
|
// 表单重置
|
||||||
|
reset() {
|
||||||
|
if (this.$refs.menu != undefined) {
|
||||||
|
this.$refs.menu.setCheckedKeys([])
|
||||||
|
}
|
||||||
|
this.menuExpand = false,
|
||||||
|
this.menuNodeAll = false,
|
||||||
|
this.deptExpand = true,
|
||||||
|
this.deptNodeAll = false,
|
||||||
|
this.form = {
|
||||||
|
roleId: undefined,
|
||||||
|
roleName: undefined,
|
||||||
|
roleKey: undefined,
|
||||||
|
roleSort: 0,
|
||||||
|
status: "0",
|
||||||
|
menuIds: [],
|
||||||
|
deptIds: [],
|
||||||
|
menuCheckStrictly: true,
|
||||||
|
deptCheckStrictly: true,
|
||||||
|
remark: undefined
|
||||||
|
}
|
||||||
|
this.resetForm("form")
|
||||||
|
},
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
resetQuery() {
|
||||||
|
this.dateRange = []
|
||||||
|
this.resetForm("queryForm")
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
// 多选框选中数据
|
||||||
|
handleSelectionChange(selection) {
|
||||||
|
this.ids = selection.map(item => item.roleId)
|
||||||
|
this.single = selection.length != 1
|
||||||
|
this.multiple = !selection.length
|
||||||
|
},
|
||||||
|
// 更多操作触发
|
||||||
|
handleCommand(command, row) {
|
||||||
|
switch (command) {
|
||||||
|
case "handleDataScope":
|
||||||
|
this.handleDataScope(row)
|
||||||
|
break
|
||||||
|
case "handleAuthUser":
|
||||||
|
this.handleAuthUser(row)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 树权限(展开/折叠)
|
||||||
|
handleCheckedTreeExpand(value, type) {
|
||||||
|
if (type == 'menu') {
|
||||||
|
let treeList = this.menuOptions
|
||||||
|
for (let i = 0; i < treeList.length; i++) {
|
||||||
|
this.$refs.menu.store.nodesMap[treeList[i].id].expanded = value
|
||||||
|
}
|
||||||
|
} else if (type == 'dept') {
|
||||||
|
let treeList = this.deptOptions
|
||||||
|
for (let i = 0; i < treeList.length; i++) {
|
||||||
|
this.$refs.dept.store.nodesMap[treeList[i].id].expanded = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 树权限(全选/全不选)
|
||||||
|
handleCheckedTreeNodeAll(value, type) {
|
||||||
|
if (type == 'menu') {
|
||||||
|
this.$refs.menu.setCheckedNodes(value ? this.menuOptions: [])
|
||||||
|
} else if (type == 'dept') {
|
||||||
|
this.$refs.dept.setCheckedNodes(value ? this.deptOptions: [])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 树权限(父子联动)
|
||||||
|
handleCheckedTreeConnect(value, type) {
|
||||||
|
if (type == 'menu') {
|
||||||
|
this.form.menuCheckStrictly = value ? true: false
|
||||||
|
} else if (type == 'dept') {
|
||||||
|
this.form.deptCheckStrictly = value ? true: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
handleAdd() {
|
||||||
|
this.reset()
|
||||||
|
this.getMenuTreeselect()
|
||||||
|
this.open = true
|
||||||
|
this.title = "添加角色"
|
||||||
|
},
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
handleUpdate(row) {
|
||||||
|
this.reset()
|
||||||
|
const roleId = row.roleId || this.ids
|
||||||
|
const roleMenu = this.getRoleMenuTreeselect(roleId)
|
||||||
|
getRole(roleId).then(response => {
|
||||||
|
this.form = response.data
|
||||||
|
this.open = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
roleMenu.then(res => {
|
||||||
|
let checkedKeys = res.checkedKeys
|
||||||
|
checkedKeys.forEach((v) => {
|
||||||
|
this.$nextTick(()=>{
|
||||||
|
this.$refs.menu.setChecked(v, true ,false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
this.title = "修改角色"
|
||||||
|
},
|
||||||
|
/** 选择角色权限范围触发 */
|
||||||
|
dataScopeSelectChange(value) {
|
||||||
|
if (value !== '2') {
|
||||||
|
this.$refs.dept.setCheckedKeys([])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 分配数据权限操作 */
|
||||||
|
handleDataScope(row) {
|
||||||
|
this.reset()
|
||||||
|
const deptTreeSelect = this.getDeptTree(row.roleId)
|
||||||
|
getRole(row.roleId).then(response => {
|
||||||
|
this.form = response.data
|
||||||
|
this.openDataScope = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
deptTreeSelect.then(res => {
|
||||||
|
this.$refs.dept.setCheckedKeys(res.checkedKeys)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
this.title = "分配数据权限"
|
||||||
|
},
|
||||||
|
/** 分配用户操作 */
|
||||||
|
handleAuthUser(row) {
|
||||||
|
const roleId = row.roleId
|
||||||
|
this.$router.push("/system/role-auth/user/" + roleId)
|
||||||
|
},
|
||||||
|
/** 提交按钮 */
|
||||||
|
submitForm() {
|
||||||
|
this.$refs["form"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
if (this.form.roleId != undefined) {
|
||||||
|
this.form.menuIds = this.getMenuAllCheckedKeys()
|
||||||
|
updateRole(this.form).then(() => {
|
||||||
|
this.$modal.msgSuccess("修改成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.form.menuIds = this.getMenuAllCheckedKeys()
|
||||||
|
addRole(this.form).then(() => {
|
||||||
|
this.$modal.msgSuccess("新增成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 提交按钮(数据权限) */
|
||||||
|
submitDataScope() {
|
||||||
|
if (this.form.roleId != undefined) {
|
||||||
|
this.form.deptIds = this.getDeptAllCheckedKeys()
|
||||||
|
dataScope(this.form).then(() => {
|
||||||
|
this.$modal.msgSuccess("修改成功")
|
||||||
|
this.openDataScope = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
handleDelete(row) {
|
||||||
|
const roleIds = row.roleId || this.ids
|
||||||
|
this.$modal.confirm('是否确认删除角色编号为"' + roleIds + '"的数据项?').then(function() {
|
||||||
|
return delRole(roleIds)
|
||||||
|
}).then(() => {
|
||||||
|
this.getList()
|
||||||
|
this.$modal.msgSuccess("删除成功")
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
handleExport() {
|
||||||
|
this.download('system/role/export', {
|
||||||
|
...this.queryParams
|
||||||
|
}, `role_${new Date().getTime()}.xlsx`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.system-role ::v-deep .el-table ::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.system-role ::v-deep .el-table {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
.system-role ::v-deep .el-table__body-wrapper::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.system-role ::v-deep .el-table__body-wrapper {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,510 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container tree-sidebar-manage-wrap system-user">
|
||||||
|
<tree-panel title="组织机构" :tree-data="deptOptions" search-placeholder="请输入部门名称" storage-key="dept-sidebar-width" :defaultExpandAll="true" @node-click="handleNodeClick" @refresh="getDeptTree" ref="deptTreeRef" />
|
||||||
|
<div class="tree-sidebar-content">
|
||||||
|
<div class="content-inner">
|
||||||
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||||
|
<el-form-item label="用户名称" prop="userName">
|
||||||
|
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="手机号码" prop="phonenumber">
|
||||||
|
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="停用" prop="status">
|
||||||
|
<el-radio-group v-model="queryParams.status">
|
||||||
|
<el-radio label="0">否</el-radio>
|
||||||
|
<el-radio label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="创建时间">
|
||||||
|
<el-date-picker v-model="dateRange" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['system:user:add']">新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['system:user:edit']">修改</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['system:user:remove']">删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="info" plain icon="el-icon-upload2" size="mini" @click="handleImport" v-hasPermi="['system:user:import']">导入</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['system:user:export']">导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange" :height="tableHeight">
|
||||||
|
<el-table-column type="selection" width="50" align="center" />
|
||||||
|
<el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns.userId.visible" />
|
||||||
|
<el-table-column label="用户名称" align="center" key="userName" v-if="columns.userName.visible" :show-overflow-tooltip="true">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<a class="link-type" style="cursor:pointer" @click="handleViewData(scope.row)">{{ scope.row.userName }}</a>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="用户昵称" align="center" key="nickName" prop="nickName" v-if="columns.nickName.visible" :show-overflow-tooltip="true" />
|
||||||
|
<el-table-column label="部门" align="center" key="deptName" prop="dept.deptName" v-if="columns.deptName.visible" :show-overflow-tooltip="true" />
|
||||||
|
<el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" v-if="columns.phonenumber.visible" width="120" />
|
||||||
|
<el-table-column label="状态" align="center" key="status" v-if="columns.status.visible">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="创建时间" align="center" prop="createTime" v-if="columns.createTime.visible" width="160">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
|
||||||
|
<template slot-scope="scope" v-if="scope.row.userId !== 1">
|
||||||
|
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:user:edit']">修改</el-button>
|
||||||
|
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['system:user:remove']">删除</el-button>
|
||||||
|
<el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['system:user:resetPwd', 'system:user:edit']">
|
||||||
|
<el-button size="mini" type="text" icon="el-icon-d-arrow-right">更多</el-button>
|
||||||
|
<el-dropdown-menu slot="dropdown">
|
||||||
|
<el-dropdown-item command="handleResetPwd" icon="el-icon-key" v-hasPermi="['system:user:resetPwd']">重置密码</el-dropdown-item>
|
||||||
|
<el-dropdown-item command="handleAuthRole" icon="el-icon-circle-check" v-hasPermi="['system:user:edit']">分配角色</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</el-dropdown>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 添加或修改用户配置对话框 -->
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="用户昵称" prop="nickName">
|
||||||
|
<el-input v-model="form.nickName" placeholder="请输入用户昵称" maxlength="30" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="归属部门" prop="deptId">
|
||||||
|
<treeselect v-model="form.deptId" :options="enabledDeptOptions" :show-count="true" placeholder="请选择归属部门" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="手机号码" prop="phonenumber">
|
||||||
|
<el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="邮箱" prop="email">
|
||||||
|
<el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item v-if="form.userId == undefined" label="用户名称" prop="userName">
|
||||||
|
<el-input v-model="form.userName" placeholder="请输入用户名称" maxlength="30" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item v-if="form.userId == undefined" label="用户密码" prop="password" :rules="pwdValidator">
|
||||||
|
<el-input v-model="form.password" placeholder="请输入用户密码" type="password" maxlength="20" show-password />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="用户性别">
|
||||||
|
<el-select v-model="form.sex" placeholder="请选择性别">
|
||||||
|
<el-option v-for="dict in dict.type.sys_user_sex" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="状态">
|
||||||
|
<el-radio-group v-model="form.status">
|
||||||
|
<el-radio v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="岗位">
|
||||||
|
<el-select v-model="form.postIds" multiple placeholder="请选择岗位">
|
||||||
|
<el-option v-for="item in postOptions" :key="item.postId" :label="item.postName" :value="item.postId" :disabled="item.status == 1" ></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="角色">
|
||||||
|
<el-select v-model="form.roleIds" multiple placeholder="请选择角色">
|
||||||
|
<el-option v-for="item in roleOptions" :key="item.roleId" :label="item.roleName" :value="item.roleId" :disabled="item.status == 1"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="备注">
|
||||||
|
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 用户详情抽屉 -->
|
||||||
|
<user-view-drawer ref="userViewRef" />
|
||||||
|
<!-- 用户导入对话框 -->
|
||||||
|
<excel-import-dialog ref="importUserRef" title="用户导入" action="/system/user/importData" template-action="/system/user/importTemplate" template-file-name="user_template" update-support-label="是否更新已经存在的用户数据" @success="getList" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus, deptTreeSelect } from "@/api/system/user"
|
||||||
|
import Treeselect from "@riophae/vue-treeselect"
|
||||||
|
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
|
||||||
|
import TreePanel from "@/components/TreePanel"
|
||||||
|
import ExcelImportDialog from "@/components/ExcelImportDialog"
|
||||||
|
import UserViewDrawer from "./view"
|
||||||
|
import passwordRule from "@/utils/passwordRule"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "User",
|
||||||
|
mixins: [passwordRule],
|
||||||
|
dicts: ['sys_normal_disable', 'sys_user_sex'],
|
||||||
|
components: { Treeselect, TreePanel, ExcelImportDialog, UserViewDrawer },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 遮罩层
|
||||||
|
loading: true,
|
||||||
|
// 表格高度
|
||||||
|
tableHeight: window.innerHeight - 240,
|
||||||
|
// 选中数组
|
||||||
|
ids: [],
|
||||||
|
// 非单个禁用
|
||||||
|
single: true,
|
||||||
|
// 非多个禁用
|
||||||
|
multiple: true,
|
||||||
|
// 显示搜索条件
|
||||||
|
showSearch: true,
|
||||||
|
// 总条数
|
||||||
|
total: 0,
|
||||||
|
// 用户表格数据
|
||||||
|
userList: null,
|
||||||
|
// 弹出层标题
|
||||||
|
title: "",
|
||||||
|
// 所有部门树选项
|
||||||
|
deptOptions: undefined,
|
||||||
|
// 过滤掉已禁用部门树选项
|
||||||
|
enabledDeptOptions: undefined,
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
// 默认密码
|
||||||
|
initPassword: undefined,
|
||||||
|
// 日期范围
|
||||||
|
dateRange: [],
|
||||||
|
// 岗位选项
|
||||||
|
postOptions: [],
|
||||||
|
// 角色选项
|
||||||
|
roleOptions: [],
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
userName: undefined,
|
||||||
|
phonenumber: undefined,
|
||||||
|
status: '0',
|
||||||
|
deptId: undefined
|
||||||
|
},
|
||||||
|
// 列信息
|
||||||
|
columns: {
|
||||||
|
userId: { label: '用户编号', visible: true },
|
||||||
|
userName: { label: '用户名称', visible: true },
|
||||||
|
nickName: { label: '用户昵称', visible: true },
|
||||||
|
deptName: { label: '部门', visible: true },
|
||||||
|
phonenumber: { label: '手机号码', visible: true },
|
||||||
|
status: { label: '状态', visible: true },
|
||||||
|
createTime: { label: '创建时间', visible: true }
|
||||||
|
},
|
||||||
|
// 表单校验
|
||||||
|
rules: {
|
||||||
|
userName: [
|
||||||
|
{ required: true, message: "用户名称不能为空", trigger: "blur" },
|
||||||
|
{ min: 2, max: 20, message: '用户名称长度必须介于 2 和 20 之间', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
nickName: [
|
||||||
|
{ required: true, message: "用户昵称不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
email: [
|
||||||
|
{
|
||||||
|
type: "email",
|
||||||
|
message: "请输入正确的邮箱地址",
|
||||||
|
trigger: ["blur", "change"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
phonenumber: [
|
||||||
|
{
|
||||||
|
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
|
||||||
|
message: "请输入正确的手机号码",
|
||||||
|
trigger: "blur"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList()
|
||||||
|
this.getDeptTree()
|
||||||
|
this.getConfigKey("sys.user.initPassword").then(response => {
|
||||||
|
this.initPassword = response.msg
|
||||||
|
})
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getTableHeight()
|
||||||
|
window.addEventListener('resize', this.getTableHeight)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
window.removeEventListener('resize', this.getTableHeight)
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
showSearch() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.getTableHeight()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 获取表格高度 */
|
||||||
|
getTableHeight() {
|
||||||
|
const offset = this.showSearch ? 240 : 190
|
||||||
|
this.tableHeight = window.innerHeight - offset
|
||||||
|
},
|
||||||
|
/** 查询用户列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
|
||||||
|
this.userList = response.rows
|
||||||
|
this.total = response.total
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 查询部门下拉树结构 */
|
||||||
|
getDeptTree() {
|
||||||
|
deptTreeSelect().then(response => {
|
||||||
|
this.deptOptions = response.data
|
||||||
|
this.enabledDeptOptions = this.filterDisabledDept(JSON.parse(JSON.stringify(response.data)))
|
||||||
|
}).catch(() => {
|
||||||
|
this.deptOptions = []
|
||||||
|
this.enabledDeptOptions = []
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 过滤禁用的部门
|
||||||
|
filterDisabledDept(deptList) {
|
||||||
|
return deptList.filter(dept => {
|
||||||
|
if (dept.disabled) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (dept.children && dept.children.length) {
|
||||||
|
dept.children = this.filterDisabledDept(dept.children)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 节点单击事件
|
||||||
|
handleNodeClick(data) {
|
||||||
|
this.queryParams.deptId = data.id
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
// 用户状态修改
|
||||||
|
handleStatusChange(row) {
|
||||||
|
let text = row.status === "0" ? "启用" : "停用"
|
||||||
|
this.$modal.confirm('确认要"' + text + '""' + row.userName + '"用户吗?').then(function() {
|
||||||
|
return changeUserStatus(row.userId, row.status)
|
||||||
|
}).then(() => {
|
||||||
|
this.$modal.msgSuccess(text + "成功")
|
||||||
|
}).catch(function() {
|
||||||
|
row.status = row.status === "0" ? "1" : "0"
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 取消按钮
|
||||||
|
cancel() {
|
||||||
|
this.open = false
|
||||||
|
this.reset()
|
||||||
|
},
|
||||||
|
// 表单重置
|
||||||
|
reset() {
|
||||||
|
this.form = {
|
||||||
|
userId: undefined,
|
||||||
|
deptId: undefined,
|
||||||
|
userName: undefined,
|
||||||
|
nickName: undefined,
|
||||||
|
password: undefined,
|
||||||
|
phonenumber: undefined,
|
||||||
|
email: undefined,
|
||||||
|
sex: undefined,
|
||||||
|
status: "0",
|
||||||
|
remark: undefined,
|
||||||
|
postIds: [],
|
||||||
|
roleIds: []
|
||||||
|
}
|
||||||
|
this.resetForm("form")
|
||||||
|
},
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
resetQuery() {
|
||||||
|
this.dateRange = []
|
||||||
|
this.resetForm("queryForm")
|
||||||
|
this.queryParams.deptId = undefined
|
||||||
|
this.$refs.deptTreeRef.setCurrentKey(null)
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
// 多选框选中数据
|
||||||
|
handleSelectionChange(selection) {
|
||||||
|
this.ids = selection.map(item => item.userId)
|
||||||
|
this.single = selection.length != 1
|
||||||
|
this.multiple = !selection.length
|
||||||
|
},
|
||||||
|
// 更多操作触发
|
||||||
|
handleCommand(command, row) {
|
||||||
|
switch (command) {
|
||||||
|
case "handleResetPwd":
|
||||||
|
this.handleResetPwd(row)
|
||||||
|
break
|
||||||
|
case "handleAuthRole":
|
||||||
|
this.handleAuthRole(row)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
handleAdd() {
|
||||||
|
this.reset()
|
||||||
|
getUser().then(response => {
|
||||||
|
this.postOptions = response.posts
|
||||||
|
this.roleOptions = response.roles
|
||||||
|
this.open = true
|
||||||
|
this.title = "添加用户"
|
||||||
|
this.form.password = this.initPassword
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
handleUpdate(row) {
|
||||||
|
this.reset()
|
||||||
|
const userId = row.userId || this.ids
|
||||||
|
getUser(userId).then(response => {
|
||||||
|
this.form = response.data
|
||||||
|
this.postOptions = response.posts
|
||||||
|
this.roleOptions = response.roles
|
||||||
|
this.$set(this.form, "postIds", response.postIds)
|
||||||
|
this.$set(this.form, "roleIds", response.roleIds)
|
||||||
|
this.open = true
|
||||||
|
this.title = "修改用户"
|
||||||
|
this.form.password = ""
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 重置密码按钮操作 */
|
||||||
|
handleResetPwd(row) {
|
||||||
|
this.$prompt(`请输入「${row.userName}」的新密码`, "重置密码", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
closeOnClickModal: false,
|
||||||
|
inputValidator: this.pwdPromptValidator
|
||||||
|
}).then(({ value }) => {
|
||||||
|
resetUserPwd(row.userId, value).then(() => {
|
||||||
|
this.$modal.msgSuccess("修改成功,新密码是:" + value)
|
||||||
|
})
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
/** 分配角色操作 */
|
||||||
|
handleAuthRole(row) {
|
||||||
|
const userId = row.userId
|
||||||
|
this.$router.push("/system/user-auth/role/" + userId)
|
||||||
|
},
|
||||||
|
/** 提交按钮 */
|
||||||
|
submitForm() {
|
||||||
|
this.$refs["form"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
if (this.form.userId != undefined) {
|
||||||
|
updateUser(this.form).then(() => {
|
||||||
|
this.$modal.msgSuccess("修改成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
addUser(this.form).then(() => {
|
||||||
|
this.$modal.msgSuccess("新增成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
handleDelete(row) {
|
||||||
|
const userIds = row.userId || this.ids
|
||||||
|
this.$modal.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?').then(function() {
|
||||||
|
return delUser(userIds)
|
||||||
|
}).then(() => {
|
||||||
|
this.getList()
|
||||||
|
this.$modal.msgSuccess("删除成功")
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
handleExport() {
|
||||||
|
this.download('system/user/export', {
|
||||||
|
...this.queryParams
|
||||||
|
}, `user_${new Date().getTime()}.xlsx`)
|
||||||
|
},
|
||||||
|
/** 详情按钮操作 */
|
||||||
|
handleViewData(row) {
|
||||||
|
this.$refs.userViewRef.open(row.userId)
|
||||||
|
},
|
||||||
|
/** 导入按钮操作 */
|
||||||
|
handleImport() {
|
||||||
|
this.$refs.importUserRef.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.system-user ::v-deep .el-table ::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.system-user ::v-deep .el-table {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
.system-user ::v-deep .el-table__body-wrapper::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.system-user ::v-deep .el-table__body-wrapper {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,589 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container syllabus-page">
|
||||||
|
<!-- 查询条件 -->
|
||||||
|
<el-card shadow="never" class="search-card">
|
||||||
|
<el-form :model="searchForm" label-width="100px" class="search-form" @submit.native.prevent>
|
||||||
|
<el-row :gutter="32">
|
||||||
|
<el-col :xs="24" :md="8">
|
||||||
|
<el-form-item label="专业代号">
|
||||||
|
<el-input v-model="searchForm.zydh" placeholder="请输入专业代号" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :md="8">
|
||||||
|
<el-form-item label="停用">
|
||||||
|
<el-radio-group v-model="searchForm.ty">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :md="8">
|
||||||
|
<div class="search-actions">
|
||||||
|
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 数据列表 -->
|
||||||
|
<el-card shadow="never" class="table-card">
|
||||||
|
<div class="list-header">
|
||||||
|
<div class="list-title">教学大纲列表</div>
|
||||||
|
<div class="list-actions">
|
||||||
|
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新增</el-button>
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
plain
|
||||||
|
icon="el-icon-delete"
|
||||||
|
:disabled="!selection.length"
|
||||||
|
@click="handleBatchDelete"
|
||||||
|
>删除所选</el-button>
|
||||||
|
<el-button icon="el-icon-download" @click="handleDownload">下载</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-table v-loading="loading" :data="pagedData" border stripe highlight-current-row
|
||||||
|
@selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="50" align="center" />
|
||||||
|
<el-table-column prop="bh" label="编号" width="170" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="zydh" label="专业代号" width="150" align="center" />
|
||||||
|
<el-table-column prop="kbh" label="课编号" width="110" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="jc" label="简称" width="100" show-overflow-tooltip align="center" />
|
||||||
|
<el-table-column prop="klx" label="课类型" width="80" align="center" />
|
||||||
|
<el-table-column prop="xqdc" label="学期第次" width="80" align="center" />
|
||||||
|
<el-table-column prop="xs" label="学时" width="70" align="center" />
|
||||||
|
<el-table-column prop="xf" label="学分" width="70" align="center" />
|
||||||
|
<el-table-column prop="llxs" label="理论学时" width="80" align="center" />
|
||||||
|
<el-table-column prop="sjxs" label="实践学时" width="80" align="center" />
|
||||||
|
<el-table-column prop="zks" label="周课时" width="70" align="center" />
|
||||||
|
<el-table-column prop="ksks" label="考试课时" width="80" align="center" />
|
||||||
|
<el-table-column label="大纲课程" width="90" align="center">
|
||||||
|
<template slot-scope="scope">{{ fmtYesNo(scope.row.dgkc) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="停用" width="80" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag :type="Number(scope.row.ty) === 1 ? 'danger' : 'success'" size="mini">
|
||||||
|
{{ Number(scope.row.ty) === 1 ? '停用' : '正常' }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="启用时间" width="150" align="center">
|
||||||
|
<template slot-scope="scope">{{ fmtDateTime(scope.row.qysj) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="停用时间" width="150" align="center">
|
||||||
|
<template slot-scope="scope">{{ fmtDateTime(scope.row.tysj) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="160" align="center" fixed="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button type="text" size="mini" icon="el-icon-edit" @click="handleEdit(scope.row)">编辑</el-button>
|
||||||
|
<el-button type="text" size="mini" icon="el-icon-delete" class="danger-text-btn" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<el-pagination
|
||||||
|
class="pagination"
|
||||||
|
background
|
||||||
|
layout="total, sizes, prev, pager, next"
|
||||||
|
:current-page="pageNum"
|
||||||
|
:page-size="pageSize"
|
||||||
|
:total="total"
|
||||||
|
:page-sizes="[10, 20, 50, 100]"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handlePageChange"
|
||||||
|
/>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 新增/编辑弹窗 -->
|
||||||
|
<el-dialog :title="dialog.title" :visible.sync="dialog.visible" width="720px" append-to-body
|
||||||
|
:close-on-click-modal="false">
|
||||||
|
<el-form ref="syllabusForm" :model="dialog.form" :rules="rules" label-width="130px">
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="专业" prop="zydh">
|
||||||
|
<el-select
|
||||||
|
v-model="dialog.form.zydh"
|
||||||
|
filterable
|
||||||
|
clearable
|
||||||
|
placeholder="请选择专业"
|
||||||
|
class="w-full"
|
||||||
|
:loading="referenceDataLoading"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in majorOptions"
|
||||||
|
:key="item.zydh"
|
||||||
|
:label="item.zymc"
|
||||||
|
:value="item.zydh"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="课程" prop="kbh">
|
||||||
|
<el-select
|
||||||
|
v-model="dialog.form.kbh"
|
||||||
|
filterable
|
||||||
|
clearable
|
||||||
|
placeholder="请选择课程"
|
||||||
|
class="w-full"
|
||||||
|
:loading="referenceDataLoading"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in subjectOptions"
|
||||||
|
:key="item.kbh"
|
||||||
|
:label="item.kmc"
|
||||||
|
:value="item.kbh"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="学期第次" prop="xqdc">
|
||||||
|
<el-input-number v-model="dialog.form.xqdc" :min="1" :max="20" controls-position="right" class="w-full" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="课类型" prop="klx">
|
||||||
|
<el-select
|
||||||
|
v-model="dialog.form.klx"
|
||||||
|
filterable
|
||||||
|
clearable
|
||||||
|
placeholder="请选择课类型"
|
||||||
|
class="w-full"
|
||||||
|
:loading="referenceDataLoading"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in courseTypeOptions"
|
||||||
|
:key="item.dictValue"
|
||||||
|
:label="item.dictLabel"
|
||||||
|
:value="item.dictValue"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="学时" prop="xs">
|
||||||
|
<el-input-number v-model="dialog.form.xs" :min="0" controls-position="right" class="w-full" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="停用" prop="ty">
|
||||||
|
<el-radio-group v-model="dialog.form.ty">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="简称">
|
||||||
|
<el-input v-model="dialog.form.jc" placeholder="请输入课程简称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="学分">
|
||||||
|
<el-input-number v-model="dialog.form.xf" :min="0" :step="0.5" :precision="1" controls-position="right" class="w-full" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="课程定位">
|
||||||
|
<el-input v-model="dialog.form.kcdw" placeholder="请输入课程定位" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="模块">
|
||||||
|
<el-input v-model="dialog.form.mk" placeholder="请输入模块" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="成绩分制">
|
||||||
|
<el-input v-model="dialog.form.cjfz" placeholder="请输入成绩分制" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="教研室">
|
||||||
|
<el-select
|
||||||
|
v-model="dialog.form.jysdh"
|
||||||
|
filterable
|
||||||
|
clearable
|
||||||
|
placeholder="请选择教研室"
|
||||||
|
class="w-full"
|
||||||
|
:loading="referenceDataLoading"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in officeOptions"
|
||||||
|
:key="item.jysdh"
|
||||||
|
:label="item.jysmc"
|
||||||
|
:value="item.jysdh"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="考试课时">
|
||||||
|
<el-input-number v-model="dialog.form.ksks" :min="0" controls-position="right" class="w-full" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="理论学时">
|
||||||
|
<el-input-number v-model="dialog.form.llxs" :min="0" controls-position="right" class="w-full" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="实践学时">
|
||||||
|
<el-input-number v-model="dialog.form.sjxs" :min="0" controls-position="right" class="w-full" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="周课时">
|
||||||
|
<el-input-number v-model="dialog.form.zks" :min="0" controls-position="right" class="w-full" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="不计入平均分">
|
||||||
|
<el-radio-group v-model="dialog.form.bjrxypjf">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="考试课时不显示">
|
||||||
|
<el-radio-group v-model="dialog.form.ksksbxs">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="大纲课程">
|
||||||
|
<el-radio-group v-model="dialog.form.dgkc">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="dialog.visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" :loading="dialog.submitting" @click="submitDialog">确 定</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
addSyllabus,
|
||||||
|
deleteSyllabus,
|
||||||
|
batchDeleteSyllabus,
|
||||||
|
updateSyllabus,
|
||||||
|
listSyllabus,
|
||||||
|
listSyllabusByZydhAndTy
|
||||||
|
} from '@/api/teachBusiness/syllabus'
|
||||||
|
import { listMajor } from '@/api/subjectMajor/major'
|
||||||
|
import { listKb } from '@/api/teachOffice/kb'
|
||||||
|
import { listOffice } from '@/api/teachOffice/office'
|
||||||
|
import { getDicts } from '@/api/system/dict/data'
|
||||||
|
|
||||||
|
const REFERENCE_DATA_PAGE_SIZE = 10000
|
||||||
|
const COURSE_TYPE_DICT_CODE = 'course_type'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SyllabusIndex',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
searchForm: {
|
||||||
|
zydh: '',
|
||||||
|
ty: 0
|
||||||
|
},
|
||||||
|
tableData: [],
|
||||||
|
total: 0,
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
selection: [],
|
||||||
|
referenceDataLoading: false,
|
||||||
|
majorOptions: [],
|
||||||
|
subjectOptions: [],
|
||||||
|
courseTypeOptions: [],
|
||||||
|
officeOptions: [],
|
||||||
|
dialog: {
|
||||||
|
visible: false,
|
||||||
|
title: '',
|
||||||
|
submitting: false,
|
||||||
|
form: this.createEmptyForm()
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
zydh: [{ required: true, message: '请选择专业', trigger: 'change' }],
|
||||||
|
kbh: [{ required: true, message: '请选择课程', trigger: 'change' }],
|
||||||
|
xqdc: [{ required: true, message: '请输入学期第次', trigger: 'blur' }],
|
||||||
|
klx: [{ required: true, message: '请选择课类型', trigger: 'change' }],
|
||||||
|
xs: [{ required: true, message: '请输入学时', trigger: 'blur' }],
|
||||||
|
ty: [{ required: true, message: '请选择停用标识', trigger: 'change' }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
pagedData() {
|
||||||
|
const start = (this.pageNum - 1) * this.pageSize
|
||||||
|
return this.tableData.slice(start, start + this.pageSize)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.fetchList()
|
||||||
|
this.loadReferenceData()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
loadReferenceData() {
|
||||||
|
this.referenceDataLoading = true
|
||||||
|
const query = { pageNum: 1, pageSize: REFERENCE_DATA_PAGE_SIZE }
|
||||||
|
const requests = [
|
||||||
|
listMajor(query),
|
||||||
|
listKb(query),
|
||||||
|
listOffice(query),
|
||||||
|
getDicts(COURSE_TYPE_DICT_CODE)
|
||||||
|
].map(request => {
|
||||||
|
return request
|
||||||
|
.then(response => this.getResponseRecords(response))
|
||||||
|
.catch(() => [])
|
||||||
|
})
|
||||||
|
|
||||||
|
Promise.all(requests).then(([majors, subjects, offices, courseTypes]) => {
|
||||||
|
this.majorOptions = this.getUniqueOptions(majors, 'zydh', 'zymc')
|
||||||
|
this.subjectOptions = this.getUniqueOptions(subjects, 'kbh', 'kmc')
|
||||||
|
this.officeOptions = this.getUniqueOptions(offices, 'jysdh', 'jysmc')
|
||||||
|
this.courseTypeOptions = this.getUniqueOptions(courseTypes, 'dictValue', 'dictLabel')
|
||||||
|
}).finally(() => {
|
||||||
|
this.referenceDataLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getResponseRecords(response) {
|
||||||
|
const data = response.data || {}
|
||||||
|
|
||||||
|
return Array.isArray(data) ? data : data.records || []
|
||||||
|
},
|
||||||
|
getUniqueOptions(items, valueKey, labelKey) {
|
||||||
|
const values = new Set()
|
||||||
|
|
||||||
|
return items.filter(item => {
|
||||||
|
const value = item[valueKey]
|
||||||
|
const label = item[labelKey]
|
||||||
|
if (!value || !label || values.has(value)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
values.add(value)
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/* ---------- 列表加载 ---------- */
|
||||||
|
fetchList() {
|
||||||
|
this.loading = true
|
||||||
|
const { zydh, ty } = this.searchForm
|
||||||
|
// 专业代号存在时走后端组合查询;否则查全部后按停用标识过滤
|
||||||
|
const useApiQuery = Boolean(zydh)
|
||||||
|
const req = useApiQuery
|
||||||
|
? listSyllabusByZydhAndTy(zydh, ty)
|
||||||
|
: listSyllabus()
|
||||||
|
req.then(response => {
|
||||||
|
let list = response.data || []
|
||||||
|
if (!useApiQuery) {
|
||||||
|
if (zydh) list = list.filter(i => i.zydh && i.zydh.indexOf(zydh) !== -1)
|
||||||
|
list = list.filter(i => Number(i.ty) === Number(ty))
|
||||||
|
}
|
||||||
|
this.tableData = list
|
||||||
|
this.total = list.length
|
||||||
|
this.pageNum = 1
|
||||||
|
}).catch(() => {
|
||||||
|
this.tableData = []
|
||||||
|
this.total = 0
|
||||||
|
}).finally(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleQuery() {
|
||||||
|
this.fetchList()
|
||||||
|
},
|
||||||
|
handleReset() {
|
||||||
|
this.searchForm = { zydh: '', ty: 0 }
|
||||||
|
this.fetchList()
|
||||||
|
},
|
||||||
|
handleSelectionChange(val) {
|
||||||
|
this.selection = val
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 新增 / 编辑 ---------- */
|
||||||
|
handleAdd() {
|
||||||
|
this.dialog.title = '新增教学大纲'
|
||||||
|
this.dialog.form = this.createEmptyForm()
|
||||||
|
this.dialog.visible = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.syllabusForm) this.$refs.syllabusForm.clearValidate()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleEdit(row) {
|
||||||
|
this.dialog.title = '编辑教学大纲'
|
||||||
|
this.dialog.form = Object.assign({}, this.createEmptyForm(), row)
|
||||||
|
this.dialog.visible = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.syllabusForm) this.$refs.syllabusForm.clearValidate()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
submitDialog() {
|
||||||
|
this.$refs.syllabusForm.validate(valid => {
|
||||||
|
if (!valid) return
|
||||||
|
this.dialog.submitting = true
|
||||||
|
const payload = this.cleanPayload(this.dialog.form)
|
||||||
|
const isEdit = !!payload.bh
|
||||||
|
const req = isEdit ? updateSyllabus(payload) : addSyllabus(payload)
|
||||||
|
req.then(() => {
|
||||||
|
this.$message.success(isEdit ? '修改成功' : '新增成功')
|
||||||
|
this.dialog.visible = false
|
||||||
|
this.fetchList()
|
||||||
|
}).finally(() => {
|
||||||
|
this.dialog.submitting = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 删除 / 批量删除 ---------- */
|
||||||
|
handleDelete(row) {
|
||||||
|
this.$confirm('删除后该条记录将置为「停用」,是否继续?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
return deleteSyllabus(row.bh)
|
||||||
|
}).then(() => {
|
||||||
|
this.$message.success('删除成功')
|
||||||
|
this.fetchList()
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
handleBatchDelete() {
|
||||||
|
if (!this.selection.length) {
|
||||||
|
this.$message.warning('请先勾选要删除的记录')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const bhList = this.selection.map(row => row.bh)
|
||||||
|
this.$confirm('确定删除所选 ' + bhList.length + ' 条记录吗?(将置为「停用」)', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
return batchDeleteSyllabus(bhList)
|
||||||
|
}).then(() => {
|
||||||
|
this.$message.success('批量删除成功')
|
||||||
|
this.fetchList()
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 下载(无后端接口) ---------- */
|
||||||
|
handleDownload() {
|
||||||
|
this.$message.warning('后端暂未提供该接口')
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 分页 ---------- */
|
||||||
|
handleSizeChange(size) {
|
||||||
|
this.pageSize = size
|
||||||
|
this.pageNum = 1
|
||||||
|
},
|
||||||
|
handlePageChange(page) {
|
||||||
|
this.pageNum = page
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 工具 ---------- */
|
||||||
|
createEmptyForm() {
|
||||||
|
return {
|
||||||
|
bh: '',
|
||||||
|
zydh: '',
|
||||||
|
kbh: '',
|
||||||
|
xqdc: 1,
|
||||||
|
klx: '',
|
||||||
|
xs: 0,
|
||||||
|
ty: 0,
|
||||||
|
jc: '',
|
||||||
|
xf: null,
|
||||||
|
kcdw: '',
|
||||||
|
ksks: 0,
|
||||||
|
mk: '',
|
||||||
|
cjfz: '',
|
||||||
|
bjrxypjf: 0,
|
||||||
|
llxs: 0,
|
||||||
|
sjxs: 0,
|
||||||
|
zks: 0,
|
||||||
|
ksksbxs: 0,
|
||||||
|
dgkc: 0,
|
||||||
|
jysdh: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 移除空值(''/null/undefined),保留 0 等有效值 */
|
||||||
|
cleanPayload(obj) {
|
||||||
|
const payload = {}
|
||||||
|
Object.keys(obj).forEach(key => {
|
||||||
|
const value = obj[key]
|
||||||
|
if (value !== '' && value !== null && value !== undefined) {
|
||||||
|
payload[key] = value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return payload
|
||||||
|
},
|
||||||
|
fmtYesNo(val) {
|
||||||
|
return Number(val) === 1 ? '是' : '否'
|
||||||
|
},
|
||||||
|
fmtDateTime(val) {
|
||||||
|
return (val || '').substring(0, 16) || '-'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.app-container {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.syllabus-page {
|
||||||
|
.search-card {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
.w-full {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-actions {
|
||||||
|
padding-top: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-card {
|
||||||
|
.list-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.list-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
margin-top: 16px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.danger-text-btn {
|
||||||
|
color: #f56c6c;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #f78989;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,466 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container timetable-page">
|
||||||
|
<el-tabs v-model="activeTab" class="timetable-tabs">
|
||||||
|
<!-- ==================== 今日教学实施计划 ==================== -->
|
||||||
|
<el-tab-pane label="今日教学实施计划" name="today">
|
||||||
|
<div class="tab-body">
|
||||||
|
<div class="date-header">
|
||||||
|
<el-link type="primary" :underline="false" class="nav-link" @click="handlePrevDay">前一天</el-link>
|
||||||
|
<div class="date-title">{{ dateTitle }}</div>
|
||||||
|
<el-link type="primary" :underline="false" class="nav-link" @click="handleNextDay">后一天</el-link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-card">
|
||||||
|
<el-table :data="todayData" row-key="bh" v-loading="loading" stripe border>
|
||||||
|
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||||
|
<el-table-column label="上课时间" width="130" align="center">
|
||||||
|
<template #default="{ row }">{{ row.sjsj || '-' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="kcmc" label="课程" min-width="140" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="zrdw" label="责任单位" width="110" align="center" />
|
||||||
|
<el-table-column prop="bc" label="班次" width="120" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="skjy" label="教员" width="90" align="center" />
|
||||||
|
<el-table-column label="场地" width="140" align="center" show-overflow-tooltip>
|
||||||
|
<template #default="{ row }">{{ row.jxcd || '-' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="教学内容方法" min-width="160" show-overflow-tooltip header-align="center">
|
||||||
|
<template #default="{ row }">{{ row.jxnrff || '-' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="jybz" label="备注" width="100" show-overflow-tooltip header-align="center">
|
||||||
|
<template #default="{ row }">{{ row.jybz || '-' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<el-empty v-show="!loading && !todayData.length" description="暂无教学计划数据" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- ==================== 本周教学实施计划 ==================== -->
|
||||||
|
<el-tab-pane label="本周教学实施计划" name="week">
|
||||||
|
<div class="tab-body">
|
||||||
|
<div class="week-header">
|
||||||
|
<el-link type="primary" :underline="false" class="nav-link" @click="handlePrevWeek">上一周</el-link>
|
||||||
|
<div class="week-title">{{ weekRangeText }}</div>
|
||||||
|
<el-link type="primary" :underline="false" class="nav-link" @click="handleNextWeek">下一周</el-link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-card">
|
||||||
|
<el-table :data="weekData" row-key="bh" v-loading="loading" stripe border>
|
||||||
|
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||||
|
<el-table-column label="上课时间" width="170" align="center" show-overflow-tooltip>
|
||||||
|
<template #default="{ row }">{{ row.sjsj || '-' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="kcmc" label="课程" min-width="130" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="zrdw" label="责任单位" width="100" align="center" />
|
||||||
|
<el-table-column prop="bc" label="班次" width="130" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="skjy" label="教员" width="90" align="center" />
|
||||||
|
<el-table-column label="场地" width="140" align="center" show-overflow-tooltip>
|
||||||
|
<template #default="{ row }">{{ row.jxcd || '-' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="教学内容方法" min-width="150" show-overflow-tooltip header-align="center">
|
||||||
|
<template #default="{ row }">{{ row.jxnrff || '-' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="jybz" label="备注" width="100" show-overflow-tooltip header-align="center">
|
||||||
|
<template #default="{ row }">{{ row.jybz || '-' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<el-empty v-show="!loading && !weekData.length" description="本周暂无教学计划数据" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- ==================== 教学班次教学实施计划 ==================== -->
|
||||||
|
<el-tab-pane label="教学班次教学实施计划" name="shift">
|
||||||
|
<div class="tab-body">
|
||||||
|
<!-- 选择条件 -->
|
||||||
|
<div class="search-card">
|
||||||
|
<el-form :model="searchForm" inline class="search-form">
|
||||||
|
<el-form-item label="队别班次">
|
||||||
|
<el-select v-model="searchForm.teamClass" placeholder="请选择队别班次" clearable filterable class="shift-select">
|
||||||
|
<el-option v-for="item in teamClassOptions" :key="item" :label="item" :value="item" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">查询</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 标题 -->
|
||||||
|
<div class="page-title">{{ pageTitle }}</div>
|
||||||
|
|
||||||
|
<!-- 下载操作按钮 -->
|
||||||
|
<el-card shadow="never" class="action-card">
|
||||||
|
<div class="button-row">
|
||||||
|
<el-button type="primary" plain size="mini" @click="handleExportPlan">学期教学实施计划</el-button>
|
||||||
|
<el-button type="primary" plain size="mini" @click="handleExportGrades">学期成绩表</el-button>
|
||||||
|
<el-button type="primary" plain size="mini" @click="handleExportCourses">课程列表另存Excel</el-button>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<div class="table-card">
|
||||||
|
<el-table :data="shiftData" v-loading="loading" border stripe style="width: 100%">
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column label="课程名称/课时系数" min-width="220" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<div>{{ row.kcmc || '-' }}</div>
|
||||||
|
<div class="sub-text">{{ row.kssk || '-' }}</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="zrjs" label="责任教员/课次" min-width="150" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="bc" label="班次" min-width="120" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="nj" label="年级" width="80" align="center" />
|
||||||
|
<el-table-column prop="zy" label="专业" min-width="120" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="jhxs" label="计划学时" width="90" align="center" />
|
||||||
|
<el-table-column prop="yxxs" label="运行学时" width="90" align="center" />
|
||||||
|
<el-table-column prop="khlxfs" label="考核类型方式" min-width="140" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="ssjs" label="实施教员" min-width="120" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="rscd" label="人数/场地" min-width="140" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="kcjd" label="课程进度" width="120" align="center" />
|
||||||
|
<el-table-column prop="ssjhbg" label="实施计划变更" min-width="120" align="center" show-overflow-tooltip />
|
||||||
|
</el-table>
|
||||||
|
<el-empty v-show="!loading && !shiftData.length" description="请选择队别班次后查询" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listToday, listWeek, listClass, exportClassPlan, exportClassGrades, exportClassCourses } from '@/api/teachBusiness/timetable'
|
||||||
|
import { listTeam } from '@/api/studentRecords/team'
|
||||||
|
|
||||||
|
const WEEK_DAY_NAMES = ['日', '一', '二', '三', '四', '五', '六']
|
||||||
|
|
||||||
|
function pad2(n) {
|
||||||
|
return n < 10 ? '0' + n : '' + n
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDate(d) {
|
||||||
|
return d.getFullYear() + '-' + pad2(d.getMonth() + 1) + '-' + pad2(d.getDate())
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMonday(d) {
|
||||||
|
const day = d.getDay() || 7
|
||||||
|
const monday = new Date(d)
|
||||||
|
monday.setDate(d.getDate() - day + 1)
|
||||||
|
return monday
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Timetable',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeTab: 'today',
|
||||||
|
loading: false,
|
||||||
|
// 今日
|
||||||
|
todayDate: new Date(),
|
||||||
|
dayOffset: 0,
|
||||||
|
todayData: [],
|
||||||
|
// 本周
|
||||||
|
weekStart: getMonday(new Date()),
|
||||||
|
weekOffset: 0,
|
||||||
|
weekData: [],
|
||||||
|
// 班次
|
||||||
|
searchForm: { teamClass: '' },
|
||||||
|
teamClassOptions: [],
|
||||||
|
teamMap: {},
|
||||||
|
shiftData: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
selectedTodayDate() {
|
||||||
|
const date = new Date(this.todayDate)
|
||||||
|
date.setDate(date.getDate() + this.dayOffset)
|
||||||
|
return date
|
||||||
|
},
|
||||||
|
selectedWeekStart() {
|
||||||
|
const date = new Date(this.weekStart)
|
||||||
|
date.setDate(date.getDate() + this.weekOffset * 7)
|
||||||
|
return date
|
||||||
|
},
|
||||||
|
dateTitle() {
|
||||||
|
return formatDate(this.selectedTodayDate) + ' 今日教学实施计划'
|
||||||
|
},
|
||||||
|
weekRangeText() {
|
||||||
|
const end = new Date(this.selectedWeekStart)
|
||||||
|
end.setDate(end.getDate() + 6)
|
||||||
|
return formatDate(this.selectedWeekStart) + '(' + this.weekDayName(this.selectedWeekStart) + ') 至 ' +
|
||||||
|
formatDate(end) + '(' + this.weekDayName(end) + ') 本周教学实施计划'
|
||||||
|
},
|
||||||
|
pageTitle() {
|
||||||
|
const name = this.searchForm.teamClass || ''
|
||||||
|
return (name ? name + ' ' : '') + '教学班次教学实施计划'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.loadTeamOptions()
|
||||||
|
this.getTodayList()
|
||||||
|
this.getWeekList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
weekDayName(d) {
|
||||||
|
return WEEK_DAY_NAMES[d.getDay()]
|
||||||
|
},
|
||||||
|
/* ---------- 今日:日期导航 ---------- */
|
||||||
|
handlePrevDay() {
|
||||||
|
this.dayOffset -= 1
|
||||||
|
this.getTodayList()
|
||||||
|
},
|
||||||
|
handleNextDay() {
|
||||||
|
this.dayOffset += 1
|
||||||
|
this.getTodayList()
|
||||||
|
},
|
||||||
|
/* ---------- 本周:周次导航 ---------- */
|
||||||
|
handlePrevWeek() {
|
||||||
|
this.weekOffset -= 1
|
||||||
|
this.getWeekList()
|
||||||
|
},
|
||||||
|
handleNextWeek() {
|
||||||
|
this.weekOffset += 1
|
||||||
|
this.getWeekList()
|
||||||
|
},
|
||||||
|
/* ---------- 队别班次下拉(真实接口) ---------- */
|
||||||
|
loadTeamOptions() {
|
||||||
|
listTeam({ pageNum: 1, pageSize: 1000 }).then(response => {
|
||||||
|
const data = response.data || {}
|
||||||
|
const list = data.records || []
|
||||||
|
const map = {}
|
||||||
|
;(list || []).forEach(item => {
|
||||||
|
if (item.xydmc) map[item.xydmc] = item.xydbh
|
||||||
|
})
|
||||||
|
this.teamMap = map
|
||||||
|
this.teamClassOptions = list.map(item => item.xydmc).filter(Boolean)
|
||||||
|
}).catch(() => {
|
||||||
|
this.teamMap = {}
|
||||||
|
this.teamClassOptions = []
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/* ---------- 数据字段映射(接口字段 -> 页面字段) ---------- */
|
||||||
|
mapLessonRow(apiRow) {
|
||||||
|
// 接口今日/本周实体:bh sksj kc zrdw bc jy cd jxnrxff bz
|
||||||
|
const row = Object.assign({}, apiRow)
|
||||||
|
row.kcmc = apiRow.kc
|
||||||
|
row.skjy = apiRow.jy
|
||||||
|
row.jxcd = apiRow.cd
|
||||||
|
row.jxnrff = apiRow.jxnrxff
|
||||||
|
row.jybz = apiRow.bz
|
||||||
|
row.sjsj = apiRow.sksj
|
||||||
|
return row
|
||||||
|
},
|
||||||
|
extractLessonRows(response) {
|
||||||
|
const data = response && response.data
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
if (!data) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新接口返回 DailyWeeklyTimetableRangeVO,列表位于 data.list;
|
||||||
|
// records 分支用于兼容旧分页结构,避免后端版本切换时页面再次无数据。
|
||||||
|
if (Array.isArray(data.list)) {
|
||||||
|
return data.list
|
||||||
|
}
|
||||||
|
if (Array.isArray(data.records)) {
|
||||||
|
return data.records
|
||||||
|
}
|
||||||
|
|
||||||
|
return []
|
||||||
|
},
|
||||||
|
mapClassRow(apiRow) {
|
||||||
|
// 接口班次实体:sskcbh kcmcksxs zrjykc jhxs yxxs khlxfs ssjy rscd ssjhbg
|
||||||
|
const row = Object.assign({}, apiRow)
|
||||||
|
const parts = String(apiRow.kcmcksxs || '').split(' / ')
|
||||||
|
row.kcmc = parts[0] || '-'
|
||||||
|
row.kssk = parts[1] || '-'
|
||||||
|
row.zrjs = apiRow.zrjykc
|
||||||
|
row.ssjs = apiRow.ssjy
|
||||||
|
return row
|
||||||
|
},
|
||||||
|
/* ---------- 今日:拉取数据 ---------- */
|
||||||
|
getTodayList() {
|
||||||
|
const params = {
|
||||||
|
offset: this.dayOffset,
|
||||||
|
rq: formatDate(this.todayDate)
|
||||||
|
}
|
||||||
|
this.loading = true
|
||||||
|
listToday(params).then(response => {
|
||||||
|
this.todayData = this.extractLessonRows(response).map(item => this.mapLessonRow(item))
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.todayData = []
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/* ---------- 本周:拉取数据 ---------- */
|
||||||
|
getWeekList() {
|
||||||
|
const params = {
|
||||||
|
offset: this.weekOffset,
|
||||||
|
rq: formatDate(this.weekStart)
|
||||||
|
}
|
||||||
|
this.loading = true
|
||||||
|
listWeek(params).then(response => {
|
||||||
|
this.weekData = this.extractLessonRows(response).map(item => this.mapLessonRow(item))
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.weekData = []
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/* ---------- 班次:拉取数据 ---------- */
|
||||||
|
getShiftList() {
|
||||||
|
if (!this.searchForm.teamClass) return
|
||||||
|
const xydbh = this.teamMap[this.searchForm.teamClass] || this.searchForm.teamClass
|
||||||
|
const params = { xydbh: xydbh, pageNum: 1, pageSize: 1000 }
|
||||||
|
this.loading = true
|
||||||
|
listClass(params).then(response => {
|
||||||
|
const data = response.data || {}
|
||||||
|
this.shiftData = (data.records || []).map(item => this.mapClassRow(item))
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.shiftData = []
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/* ---------- 班次:查询 ---------- */
|
||||||
|
handleQuery() {
|
||||||
|
if (!this.searchForm.teamClass) {
|
||||||
|
this.$message.warning('请先选择队别班次')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.getShiftList()
|
||||||
|
},
|
||||||
|
/* ---------- 下载 ---------- */
|
||||||
|
downloadBlob(blob, filename) {
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = window.URL.createObjectURL(blob)
|
||||||
|
link.download = filename
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link)
|
||||||
|
window.URL.revokeObjectURL(link.href)
|
||||||
|
},
|
||||||
|
shiftQueryParams() {
|
||||||
|
if (!this.searchForm.teamClass) return null
|
||||||
|
const xydbh = this.teamMap[this.searchForm.teamClass] || this.searchForm.teamClass
|
||||||
|
return { xydbh: xydbh }
|
||||||
|
},
|
||||||
|
/** 下载学期教学实施计划 Excel(GET /kcb/class/export-plan) */
|
||||||
|
handleExportPlan() {
|
||||||
|
const params = this.shiftQueryParams()
|
||||||
|
if (!params) {
|
||||||
|
this.$message.warning('请先选择队别班次')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
exportClassPlan(params).then(blob => {
|
||||||
|
this.downloadBlob(blob, '学期教学实施计划.xlsx')
|
||||||
|
this.$message.success('学期教学实施计划导出成功')
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
/** 下载学期成绩表 Excel(GET /kcb/class/export-grades) */
|
||||||
|
handleExportGrades() {
|
||||||
|
const params = this.shiftQueryParams()
|
||||||
|
if (!params) {
|
||||||
|
this.$message.warning('请先选择队别班次')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
exportClassGrades(params).then(blob => {
|
||||||
|
this.downloadBlob(blob, '学期成绩表.xlsx')
|
||||||
|
this.$message.success('学期成绩表导出成功')
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
/** 班次课程列表另存 Excel(GET /kcb/class/export-courses) */
|
||||||
|
handleExportCourses() {
|
||||||
|
const params = this.shiftQueryParams()
|
||||||
|
if (!params) {
|
||||||
|
this.$message.warning('请先选择队别班次')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
exportClassCourses(params).then(blob => {
|
||||||
|
this.downloadBlob(blob, '班次课程列表.xlsx')
|
||||||
|
this.$message.success('班次课程列表导出成功')
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.timetable-page {
|
||||||
|
.timetable-tabs {
|
||||||
|
background: #fff;
|
||||||
|
padding: 0 16px;
|
||||||
|
border: 1px solid #ebeef5;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-body {
|
||||||
|
padding-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-text {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 日期/周次导航 */
|
||||||
|
.date-header,
|
||||||
|
.week-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 24px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
padding: 14px 16px;
|
||||||
|
background: #fafafa;
|
||||||
|
border: 1px solid #ebeef5;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
.nav-link {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-title,
|
||||||
|
.week-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 班次 */
|
||||||
|
.search-card {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shift-select {
|
||||||
|
width: 240px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
font-size: 17px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #303133;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-card {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
.button-row {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,892 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page-container">
|
||||||
|
<!-- 统计卡片 -->
|
||||||
|
<div class="section-card">
|
||||||
|
<div class="stat-grid">
|
||||||
|
<div
|
||||||
|
v-for="card in statCards"
|
||||||
|
:key="card.title"
|
||||||
|
class="stat-card"
|
||||||
|
:style="{ background: card.gradient }"
|
||||||
|
tabindex="0"
|
||||||
|
role="button"
|
||||||
|
@click="handleStatClick(card)"
|
||||||
|
@keydown.enter="handleStatClick(card)"
|
||||||
|
>
|
||||||
|
<span class="stat-text">{{ card.title }}</span>
|
||||||
|
<span class="stat-value">{{ card.value }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 查询条件 -->
|
||||||
|
<div class="section-card">
|
||||||
|
<el-form :model="queryParams" :inline="true" size="small" class="search-form" @submit.native.prevent>
|
||||||
|
<el-form-item label="年度">
|
||||||
|
<el-select v-model="queryParams.nd" placeholder="请选择年度" clearable style="width: 140px">
|
||||||
|
<el-option v-for="y in yearOptions" :key="y" :label="y" :value="y" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="申请教员编号">
|
||||||
|
<el-input v-model="queryParams.sqjybh" placeholder="请输入申请教员编号" clearable style="width: 180px" @keyup.enter.native="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="教研室审批状态">
|
||||||
|
<el-select v-model="queryParams.jyspzzt" placeholder="请选择" clearable style="width: 150px">
|
||||||
|
<el-option v-for="item in auditStatusOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 调课调整申请列表 -->
|
||||||
|
<div class="section-card">
|
||||||
|
<div class="section-header">
|
||||||
|
<div class="section-title">调停补课申请列表</div>
|
||||||
|
<div class="header-actions">
|
||||||
|
<el-button type="primary" plain icon="el-icon-plus" size="small" @click="openAdd">新增申请</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-table :data="tableData" v-loading="loading" size="small" border stripe class="compact-table" max-height="520">
|
||||||
|
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||||
|
<el-table-column prop="kcmc" label="课程名称" width="200" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column label="申请教员" width="150" align="center" show-overflow-tooltip>
|
||||||
|
<template slot-scope="scope">{{ scope.row.sqjyxm || scope.row.sqjybh || '-' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="sy" label="调课事由" width="230" show-overflow-tooltip header-align="center" />
|
||||||
|
<el-table-column label="拟调整时间" width="200" align="center" show-overflow-tooltip>
|
||||||
|
<template slot-scope="scope">{{ fmtRqJc(scope.row.rq, scope.row.jc) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="nd" label="年度" width="150" align="center" />
|
||||||
|
<el-table-column label="教研室审批状态" width="150" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag :type="auditStatusTag(scope.row.jyspzzt).type" size="mini">{{ auditStatusTag(scope.row.jyspzzt).label }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="教研室查收状态" width="150" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag :type="receiveStatusTag(scope.row.jyscszt).type" size="mini">{{ receiveStatusTag(scope.row.jyscszt).label }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="创建时间" width="150" align="center">
|
||||||
|
<template slot-scope="scope">{{ fmtDateTime(scope.row.cjsj) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="180" align="center" fixed="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<div class="ops-cell">
|
||||||
|
<el-button type="text" size="mini" icon="el-icon-view" @click="openDetail(scope.row)">详情</el-button>
|
||||||
|
<el-button v-if="showAuditMenu(scope.row)" type="text" size="mini" @click="openAudit(scope.row)">审批</el-button>
|
||||||
|
<el-button v-if="scope.row.sczt === 0 && scope.row.jyspzzt !== 1" type="text" size="mini" class="danger-btn" @click="handleCancel(scope.row)">撤销</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<el-empty v-show="!loading && tableData.length === 0" description="暂无调整申请" />
|
||||||
|
<pagination
|
||||||
|
v-show="total > 0"
|
||||||
|
:total="total"
|
||||||
|
:page.sync="queryParams.pageNum"
|
||||||
|
:limit.sync="queryParams.pageSize"
|
||||||
|
@pagination="loadList"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新增申请弹窗 -->
|
||||||
|
<el-dialog title="新增课表调整申请" :visible.sync="addVisible" width="640px" append-to-body>
|
||||||
|
<el-form ref="addForm" :model="addForm" :rules="addRules" label-width="110px">
|
||||||
|
<el-form-item label="年度" prop="nd">
|
||||||
|
<el-select v-model="addForm.nd" placeholder="请选择年度" style="width: 100%" @change="handleAddYearChange">
|
||||||
|
<el-option v-for="y in yearOptions" :key="y" :label="y" :value="y" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="课次编号" prop="sskcbbh">
|
||||||
|
<el-input v-model="addForm.sskcbbh" placeholder="请从可供调课课次中选择" disabled />
|
||||||
|
<el-button type="primary" plain size="mini" class="pick-lesson-btn" :loading="lessonLoading" @click="loadAdjustableLessons">选择可供调课课次</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="调课事由" prop="sy">
|
||||||
|
<el-input
|
||||||
|
v-model="addForm.sy"
|
||||||
|
type="textarea"
|
||||||
|
:rows="2"
|
||||||
|
maxlength="200"
|
||||||
|
show-word-limit
|
||||||
|
placeholder="请输入调课事由"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="拟调整日期" prop="rq">
|
||||||
|
<el-date-picker v-model="addForm.rq" type="date" value-format="yyyy-MM-dd" placeholder="请选择日期" style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="拟调整节次" prop="jc">
|
||||||
|
<el-select v-model="addForm.jc" placeholder="请选择节次" style="width: 100%">
|
||||||
|
<el-option v-for="n in jcOptions" :key="n" :label="jcLabel(n)" :value="n" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="申请教员">
|
||||||
|
<el-input v-model="addForm.sqjybh" placeholder="由服务端根据当前登录人写入" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学员队名称">
|
||||||
|
<el-input v-model="addForm.xydmc" placeholder="选择可供调课课次后自动带出" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="原教室编号">
|
||||||
|
<el-input v-model="addForm.yjsbh" placeholder="选择可供调课课次后自动带出" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="拟调整教室编号">
|
||||||
|
<el-select
|
||||||
|
v-model="addForm.xjsbh"
|
||||||
|
placeholder="请选择拟调整教室"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
:loading="classroomLoading"
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="room in classroomOptions"
|
||||||
|
:key="room.jsbh"
|
||||||
|
:label="classroomOptionLabel(room)"
|
||||||
|
:value="room.jsbh"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="原上课时间">
|
||||||
|
<el-input v-model="addForm.ydsjap" placeholder="选择可供调课课次后自动带出" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" :loading="addLoading" @click="submitAdd">提交申请</el-button>
|
||||||
|
<el-button @click="addVisible = false">取消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 可供调课课次选择弹窗 -->
|
||||||
|
<el-dialog title="选择可供调课课次" :visible.sync="lessonDialogVisible" width="760px" append-to-body>
|
||||||
|
<el-table :data="lessonOptions" v-loading="lessonLoading" size="small" border stripe max-height="420">
|
||||||
|
<el-table-column prop="kcmc" label="课程名称" min-width="140" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column label="原上课时间" width="160" align="center">
|
||||||
|
<template slot-scope="scope">{{ fmtRqJc(scope.row.rq, scope.row.jc) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="xydmc" label="学员队" min-width="120" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="kcxh" label="课次序号" width="90" align="center" />
|
||||||
|
<el-table-column prop="jsbh" label="教室编号" width="110" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column label="操作" width="90" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button type="text" size="mini" @click="pickLesson(scope.row)">选择</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<el-empty v-show="!lessonLoading && lessonOptions.length === 0" description="暂无可供调课课次" />
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 审批弹窗 -->
|
||||||
|
<el-dialog title="教研室审批" :visible.sync="auditVisible" width="520px" append-to-body>
|
||||||
|
<el-form ref="auditForm" :model="auditForm" label-width="100px">
|
||||||
|
<el-form-item label="审批结果" required>
|
||||||
|
<el-radio-group v-model="auditForm.spzt">
|
||||||
|
<el-radio :label="1">同意</el-radio>
|
||||||
|
<el-radio :label="2">发回</el-radio>
|
||||||
|
<el-radio :label="3">拒绝</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
<div class="form-tip">点审批即已查收</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="审批意见">
|
||||||
|
<el-input v-model="auditForm.fhyj" type="textarea" :rows="3" placeholder="请输入审批意见(发回/拒绝时必填)" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="审批人编号">
|
||||||
|
<el-input v-model="auditForm.sprbh" placeholder="不填默认取当前登录人" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" :loading="auditLoading" @click="submitAudit">确定</el-button>
|
||||||
|
<el-button @click="auditVisible = false">取消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 查看详情弹窗 -->
|
||||||
|
<el-dialog title="申请详情" :visible.sync="detailVisible" width="760px" append-to-body>
|
||||||
|
<div v-loading="detailLoading">
|
||||||
|
<el-descriptions v-if="detailData" :column="2" border size="small">
|
||||||
|
<el-descriptions-item label="课程名称">{{ detailData.kcmc || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="申请教员">{{ detailData.sqjyxm || detailData.sqjybh || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="调课事由" :span="2">{{ detailData.sy || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="原上课时间">{{ detailData.ydsjap || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="拟调整时间">{{ fmtRqJc(detailData.rq, detailData.jc) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="年度">{{ detailData.nd || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="创建时间">{{ fmtDateTime(detailData.cjsj) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="教研室审批状态">
|
||||||
|
<el-tag :type="auditStatusTag(detailData.jyspzzt).type" size="mini">{{ auditStatusTag(detailData.jyspzzt).label }}</el-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="教研室查收状态">
|
||||||
|
<el-tag :type="receiveStatusTag(detailData.jyscszt).type" size="mini">{{ receiveStatusTag(detailData.jyscszt).label }}</el-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="教研室审批人">{{ detailData.jyspzrbh || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="教研室审批时间">{{ fmtDateTime(detailData.jyspzsj) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="教研室查收人">{{ detailData.jyscsrbh || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="教研室查收时间">{{ fmtDateTime(detailData.jyscssj) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="教学内容" :span="2">{{ detailData.jxnr || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="教学要点" :span="2">{{ detailData.jxyd || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="教学方法" :span="2">{{ detailData.jxff || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="教学保障备注" :span="2">{{ detailData.jxbzbz || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="用车信息" :span="2">{{ detailData.ycxx || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="备注" :span="2">{{ detailData.bz || '-' }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
|
||||||
|
<!-- 新教室 -->
|
||||||
|
<div v-if="detailData && detailData.roomList && detailData.roomList.length" class="sub-section">
|
||||||
|
<div class="sub-title">新教室</div>
|
||||||
|
<el-table :data="detailData.roomList" size="small" border stripe>
|
||||||
|
<el-table-column prop="jsbh" label="教室编号" min-width="120" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="jsmc" label="教室名称" min-width="140" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="bz" label="备注" min-width="160" show-overflow-tooltip header-align="center" />
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新辅助教员 -->
|
||||||
|
<div v-if="detailData && detailData.teacherList && detailData.teacherList.length" class="sub-section">
|
||||||
|
<div class="sub-title">新辅助教员</div>
|
||||||
|
<el-table :data="detailData.teacherList" size="small" border stripe>
|
||||||
|
<el-table-column prop="fzjybh" label="教员编号" min-width="120" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="fzjyxm" label="教员姓名" min-width="120" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column label="是否主教员" width="100" align="center">
|
||||||
|
<template slot-scope="scope">{{ scope.row.zjy === 1 ? '是' : '否' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="bz" label="备注" min-width="140" show-overflow-tooltip header-align="center" />
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新学员队 -->
|
||||||
|
<div v-if="detailData && detailData.teamList && detailData.teamList.length" class="sub-section">
|
||||||
|
<div class="sub-title">新学员队</div>
|
||||||
|
<el-table :data="detailData.teamList" size="small" border stripe>
|
||||||
|
<el-table-column prop="xydbh" label="学员队编号" min-width="140" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="xydmc" label="学员队名称" min-width="140" align="center" show-overflow-tooltip />
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新保障明细 -->
|
||||||
|
<div v-if="detailData && detailData.supportList && detailData.supportList.length" class="sub-section">
|
||||||
|
<div class="sub-title">新保障明细</div>
|
||||||
|
<el-table :data="detailData.supportList" size="small" border stripe>
|
||||||
|
<el-table-column prop="bztgmxbh" label="保障编号" min-width="140" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="bztgmxmc" label="保障名称" min-width="160" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="sl" label="数量" width="80" align="center" />
|
||||||
|
<el-table-column prop="bz" label="备注" min-width="140" show-overflow-tooltip header-align="center" />
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 机关审批记录 -->
|
||||||
|
<div v-if="detailData && detailData.auditList && detailData.auditList.length" class="sub-section">
|
||||||
|
<div class="sub-title">机关审批记录</div>
|
||||||
|
<el-table :data="detailData.auditList" size="small" border stripe>
|
||||||
|
<el-table-column prop="jgmc" label="机关" min-width="140" align="center" show-overflow-tooltip>
|
||||||
|
<template slot-scope="scope">{{ scope.row.jgmc || scope.row.jgbh || '-' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="审批状态" width="100" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag :type="auditStatusTag(scope.row.spzt).type" size="mini">{{ auditStatusTag(scope.row.spzt).label }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="sprxm" label="审批人" min-width="110" align="center" show-overflow-tooltip>
|
||||||
|
<template slot-scope="scope">{{ scope.row.sprxm || scope.row.sprbh || '-' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="审批时间" width="150" align="center">
|
||||||
|
<template slot-scope="scope">{{ fmtDateTime(scope.row.spsj) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="fhyj" label="发回意见" min-width="140" show-overflow-tooltip header-align="center" />
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="detailVisible = false">关闭</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
listScheduleAdjust,
|
||||||
|
listAdjustableLessons,
|
||||||
|
getScheduleAdjustDetail,
|
||||||
|
submitScheduleAdjust,
|
||||||
|
auditByTeachingOffice,
|
||||||
|
cancelScheduleAdjust
|
||||||
|
} from '@/api/teachBusiness/courseRunning'
|
||||||
|
import { listAllSemester } from '@/api/teachBusiness/semester'
|
||||||
|
import { listAllClassroom } from '@/api/teachBusiness/classroom'
|
||||||
|
|
||||||
|
// 节次 -> 节次区间映射
|
||||||
|
const JC_SECTION = {
|
||||||
|
1: '1-2节', 2: '3-4节', 3: '5-6节', 4: '7-8节', 5: '9-10节', 6: '11-12节'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 审批状态:0-未审批,1-已同意,2-已发回,3-已拒绝
|
||||||
|
const AUDIT_STATUS = {
|
||||||
|
0: { label: '未审批', type: 'info' },
|
||||||
|
1: { label: '已同意', type: 'success' },
|
||||||
|
2: { label: '已发回', type: 'warning' },
|
||||||
|
3: { label: '已拒绝', type: 'danger' }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查收状态:0-未查收,1-已查收
|
||||||
|
const RECEIVE_STATUS = {
|
||||||
|
0: { label: '未查收', type: 'info' },
|
||||||
|
1: { label: '已查收', type: 'success' }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'TimetableAdjust',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
tableData: [],
|
||||||
|
total: 0,
|
||||||
|
queryParams: {
|
||||||
|
nd: undefined,
|
||||||
|
sqjybh: undefined,
|
||||||
|
jyspzzt: undefined,
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20
|
||||||
|
},
|
||||||
|
// 年度下拉数据来自 /semester/all(真实后端数据)
|
||||||
|
yearOptions: [],
|
||||||
|
defaultNd: undefined,
|
||||||
|
jcOptions: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
|
||||||
|
auditStatusOptions: [
|
||||||
|
{ label: '未审批', value: 0 },
|
||||||
|
{ label: '已同意', value: 1 },
|
||||||
|
{ label: '已发回', value: 2 },
|
||||||
|
{ label: '已拒绝', value: 3 }
|
||||||
|
],
|
||||||
|
statCards: [],
|
||||||
|
// 新增申请
|
||||||
|
addVisible: false,
|
||||||
|
addLoading: false,
|
||||||
|
addForm: {},
|
||||||
|
addRules: {
|
||||||
|
nd: [{ required: true, message: '请选择年度', trigger: 'change' }],
|
||||||
|
sskcbbh: [{ required: true, message: '请选择可供调课课次', trigger: 'change' }],
|
||||||
|
sy: [{ required: true, message: '请输入调课事由', trigger: 'blur' }],
|
||||||
|
rq: [{ required: true, message: '请选择拟调整日期', trigger: 'change' }],
|
||||||
|
jc: [{ required: true, message: '请选择拟调整节次', trigger: 'change' }]
|
||||||
|
},
|
||||||
|
// 可供调课课次
|
||||||
|
lessonDialogVisible: false,
|
||||||
|
lessonLoading: false,
|
||||||
|
lessonOptions: [],
|
||||||
|
classroomLoading: false,
|
||||||
|
classroomOptions: [],
|
||||||
|
// 审批
|
||||||
|
auditVisible: false,
|
||||||
|
auditLoading: false,
|
||||||
|
auditForm: { ssdksqbh: '', spzt: 1, fhyj: '', sprbh: '' },
|
||||||
|
// 详情
|
||||||
|
detailVisible: false,
|
||||||
|
detailLoading: false,
|
||||||
|
detailData: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.loadYearOptions().then(() => this.loadList())
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/* ---------- 年度下拉(数据来自 /semester/all) ---------- */
|
||||||
|
loadYearOptions() {
|
||||||
|
return listAllSemester().then(response => {
|
||||||
|
const list = response.data || []
|
||||||
|
// 去重并按年度倒序
|
||||||
|
const map = {}
|
||||||
|
list.forEach(item => {
|
||||||
|
if (item.nd !== null && item.nd !== undefined && item.nd !== '') map[item.nd] = item
|
||||||
|
})
|
||||||
|
const arr = Object.keys(map).sort((a, b) => String(b).localeCompare(String(a)))
|
||||||
|
this.yearOptions = arr
|
||||||
|
// 默认年度:优先当前学期(dqxq=true),否则取最新年度
|
||||||
|
const current = list.find(item => item.dqxq === true)
|
||||||
|
this.defaultNd = (current && current.nd) || arr[0]
|
||||||
|
if (!this.queryParams.nd) this.queryParams.nd = this.defaultNd
|
||||||
|
return arr
|
||||||
|
}).catch(() => {
|
||||||
|
this.yearOptions = []
|
||||||
|
this.defaultNd = undefined
|
||||||
|
return []
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/* ---------- 通用格式化 ---------- */
|
||||||
|
fmtDateTime(v) {
|
||||||
|
if (!v) return '-'
|
||||||
|
return String(v).replace('T', ' ').substring(0, 16)
|
||||||
|
},
|
||||||
|
fmtRqJc(rq, jc) {
|
||||||
|
if (!rq) return '-'
|
||||||
|
const date = String(rq).substring(0, 10)
|
||||||
|
const sec = jc === null || jc === undefined || jc === '' ? '第?节' : (JC_SECTION[jc] || '第' + jc + '节')
|
||||||
|
return date + ' ' + sec
|
||||||
|
},
|
||||||
|
jcLabel(n) {
|
||||||
|
return JC_SECTION[n] || ('第' + n + '节')
|
||||||
|
},
|
||||||
|
auditStatusTag(v) {
|
||||||
|
return AUDIT_STATUS[v] || { label: '-', type: 'info' }
|
||||||
|
},
|
||||||
|
receiveStatusTag(v) {
|
||||||
|
return RECEIVE_STATUS[v] || { label: '-', type: 'info' }
|
||||||
|
},
|
||||||
|
/* ---------- 列表查询 ---------- */
|
||||||
|
loadList() {
|
||||||
|
const params = {
|
||||||
|
pageNum: this.queryParams.pageNum,
|
||||||
|
pageSize: this.queryParams.pageSize
|
||||||
|
}
|
||||||
|
if (this.queryParams.nd) params.nd = this.queryParams.nd
|
||||||
|
if (this.queryParams.sqjybh) params.sqjybh = this.queryParams.sqjybh
|
||||||
|
if (this.queryParams.jyspzzt !== undefined && this.queryParams.jyspzzt !== '') {
|
||||||
|
params.jyspzzt = this.queryParams.jyspzzt
|
||||||
|
}
|
||||||
|
this.loading = true
|
||||||
|
listScheduleAdjust(params).then(response => {
|
||||||
|
const data = response.data || {}
|
||||||
|
this.tableData = data.records || []
|
||||||
|
this.total = data.total || 0
|
||||||
|
this.refreshStatCards()
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.tableData = []
|
||||||
|
this.total = 0
|
||||||
|
this.refreshStatCards()
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.loadList()
|
||||||
|
},
|
||||||
|
resetQuery() {
|
||||||
|
this.queryParams = {
|
||||||
|
nd: this.defaultNd,
|
||||||
|
sqjybh: undefined,
|
||||||
|
jyspzzt: undefined,
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20
|
||||||
|
}
|
||||||
|
this.loadList()
|
||||||
|
},
|
||||||
|
refreshStatCards() {
|
||||||
|
const list = this.tableData
|
||||||
|
this.statCards = [
|
||||||
|
{ title: '本页申请', value: list.length, gradient: 'linear-gradient(135deg, #00875a 0%, #00b877 100%)', filter: undefined },
|
||||||
|
{ title: '教研室待审批', value: list.filter(i => i.jyspzzt === 0).length, gradient: 'linear-gradient(135deg, #e6a23c 0%, #f8b04c 100%)', filter: 0 },
|
||||||
|
{ title: '教研室已同意', value: list.filter(i => i.jyspzzt === 1).length, gradient: 'linear-gradient(135deg, #409eff 0%, #66b1ff 100%)', filter: 1 },
|
||||||
|
{ title: '教研室已拒绝', value: list.filter(i => i.jyspzzt === 3).length, gradient: 'linear-gradient(135deg, #f56c6c 0%, #f78989 100%)', filter: 3 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
handleStatClick(card) {
|
||||||
|
if (card.filter === undefined) return
|
||||||
|
this.queryParams.jyspzzt = this.queryParams.jyspzzt === card.filter ? undefined : card.filter
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
/* ---------- 新增申请 ---------- */
|
||||||
|
openAdd() {
|
||||||
|
this.addForm = {
|
||||||
|
nd: this.defaultNd || this.yearOptions[0],
|
||||||
|
sskcbbh: '',
|
||||||
|
sy: '',
|
||||||
|
rq: '',
|
||||||
|
jc: 1,
|
||||||
|
sqjybh: '',
|
||||||
|
xydrwbh: '',
|
||||||
|
kbh: '',
|
||||||
|
kcbbh: '',
|
||||||
|
xydmc: '',
|
||||||
|
yjsbh: '',
|
||||||
|
xjsbh: '',
|
||||||
|
ydsjap: '',
|
||||||
|
jxnr: '',
|
||||||
|
jxyd: '',
|
||||||
|
jxff: '',
|
||||||
|
jxbzbz: '',
|
||||||
|
ycxx: '',
|
||||||
|
bz: '',
|
||||||
|
roomList: [],
|
||||||
|
teacherList: [],
|
||||||
|
teamList: [],
|
||||||
|
supportList: []
|
||||||
|
}
|
||||||
|
this.lessonOptions = []
|
||||||
|
this.loadClassroomOptions()
|
||||||
|
this.$nextTick(() => this.$refs.addForm && this.$refs.addForm.clearValidate())
|
||||||
|
this.addVisible = true
|
||||||
|
},
|
||||||
|
handleAddYearChange() {
|
||||||
|
Object.assign(this.addForm, {
|
||||||
|
sskcbbh: '',
|
||||||
|
rq: '',
|
||||||
|
jc: 1,
|
||||||
|
sqjybh: '',
|
||||||
|
xydrwbh: '',
|
||||||
|
kbh: '',
|
||||||
|
kcbbh: '',
|
||||||
|
xydmc: '',
|
||||||
|
yjsbh: '',
|
||||||
|
xjsbh: '',
|
||||||
|
ydsjap: '',
|
||||||
|
jxnr: '',
|
||||||
|
jxyd: '',
|
||||||
|
jxff: '',
|
||||||
|
jxbzbz: '',
|
||||||
|
ycxx: '',
|
||||||
|
bz: '',
|
||||||
|
roomList: [],
|
||||||
|
teacherList: [],
|
||||||
|
teamList: [],
|
||||||
|
supportList: []
|
||||||
|
})
|
||||||
|
this.lessonOptions = []
|
||||||
|
},
|
||||||
|
loadClassroomOptions() {
|
||||||
|
this.classroomLoading = true
|
||||||
|
return listAllClassroom().then(response => {
|
||||||
|
const classrooms = Array.isArray(response.data) ? response.data : []
|
||||||
|
this.classroomOptions = classrooms
|
||||||
|
.filter(room => room.jsbh && !this.isDisabledValue(room.ty))
|
||||||
|
.sort((first, second) => String(first.jsbh).localeCompare(String(second.jsbh), 'zh-CN'))
|
||||||
|
}).catch(() => {
|
||||||
|
this.classroomOptions = []
|
||||||
|
this.$message.warning('教室列表加载失败,请稍后重试')
|
||||||
|
}).finally(() => {
|
||||||
|
this.classroomLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
classroomOptionLabel(room) {
|
||||||
|
return room.jsmc ? room.jsbh + ' · ' + room.jsmc : room.jsbh
|
||||||
|
},
|
||||||
|
isDisabledValue(value) {
|
||||||
|
return value === true || value === 1 || value === '1' || value === 'true'
|
||||||
|
},
|
||||||
|
loadAdjustableLessons() {
|
||||||
|
if (!this.addForm.nd) {
|
||||||
|
this.$message.warning('请先选择年度')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.lessonLoading = true
|
||||||
|
listAdjustableLessons({ nd: this.addForm.nd }).then(response => {
|
||||||
|
const data = response.data || []
|
||||||
|
this.lessonOptions = Array.isArray(data) ? data : (data.records || [])
|
||||||
|
this.lessonLoading = false
|
||||||
|
this.lessonDialogVisible = true
|
||||||
|
}).catch(() => {
|
||||||
|
this.lessonLoading = false
|
||||||
|
this.$message.warning('加载可供调课课次失败,请稍后重试')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
pickLesson(row) {
|
||||||
|
const lessonNumber = row.sskcbbh || row.bh || ''
|
||||||
|
if (!lessonNumber) {
|
||||||
|
this.$message.warning('当前课次缺少课次编号,无法选择')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const currentRoomNumber = row.jsbh || row.yjsbh || row.xjsbh || ''
|
||||||
|
const roomList = this.normalizeRoomList(row.roomList, currentRoomNumber)
|
||||||
|
const teamList = this.normalizeTeamList(row.teamList, row.xydbh)
|
||||||
|
Object.assign(this.addForm, {
|
||||||
|
sskcbbh: lessonNumber,
|
||||||
|
rq: row.rq ? String(row.rq).substring(0, 10) : '',
|
||||||
|
jc: row.jc === null || row.jc === undefined ? 1 : Number(row.jc),
|
||||||
|
nd: row.nd || this.addForm.nd,
|
||||||
|
sqjybh: row.sqjybh || '',
|
||||||
|
xydrwbh: row.xydrwbh || '',
|
||||||
|
kbh: row.kbh || '',
|
||||||
|
kcbbh: row.kcbbh || '',
|
||||||
|
xydmc: row.xydmc || '',
|
||||||
|
yjsbh: row.yjsbh || currentRoomNumber,
|
||||||
|
xjsbh: row.xjsbh || currentRoomNumber,
|
||||||
|
ydsjap: row.rq ? this.fmtRqJc(row.rq, row.jc) : (row.ydsjap || ''),
|
||||||
|
jxnr: row.jxnr || '',
|
||||||
|
jxyd: row.jxyd || '',
|
||||||
|
jxff: row.jxff || '',
|
||||||
|
jxbzbz: row.jxbzbz || '',
|
||||||
|
ycxx: row.ycxx || '',
|
||||||
|
bz: row.bz || '',
|
||||||
|
roomList: roomList,
|
||||||
|
teacherList: this.normalizeTeacherList(row.teacherList),
|
||||||
|
teamList: teamList,
|
||||||
|
supportList: this.normalizeSupportList(row.supportList)
|
||||||
|
})
|
||||||
|
;['jysdh', 'kcmc', 'sqjyxm'].forEach(key => {
|
||||||
|
if (row[key] !== undefined && row[key] !== null) this.addForm[key] = row[key]
|
||||||
|
})
|
||||||
|
this.lessonDialogVisible = false
|
||||||
|
this.$nextTick(() => this.$refs.addForm && this.$refs.addForm.validateField('sskcbbh'))
|
||||||
|
this.$message.success('已选择课次:' + (row.kcmc || lessonNumber))
|
||||||
|
},
|
||||||
|
submitAdd() {
|
||||||
|
this.$refs.addForm.validate(valid => {
|
||||||
|
if (!valid) return
|
||||||
|
const payload = {
|
||||||
|
sskcbbh: this.addForm.sskcbbh,
|
||||||
|
sy: this.addForm.sy,
|
||||||
|
rq: this.addForm.rq + 'T00:00:00',
|
||||||
|
jc: this.addForm.jc,
|
||||||
|
nd: this.addForm.nd,
|
||||||
|
roomList: this.buildSubmitRoomList(),
|
||||||
|
teacherList: this.normalizeTeacherList(this.addForm.teacherList),
|
||||||
|
teamList: this.normalizeTeamList(this.addForm.teamList),
|
||||||
|
supportList: this.normalizeSupportList(this.addForm.supportList)
|
||||||
|
}
|
||||||
|
const optionalFields = [
|
||||||
|
'sqjybh', 'xydrwbh', 'kbh', 'kcbbh', 'xjsbh', 'jxnr', 'jxyd',
|
||||||
|
'jxff', 'jxbzbz', 'ycxx', 'bz'
|
||||||
|
]
|
||||||
|
optionalFields.forEach(key => {
|
||||||
|
if (this.addForm[key]) payload[key] = this.addForm[key]
|
||||||
|
})
|
||||||
|
this.addLoading = true
|
||||||
|
submitScheduleAdjust(payload).then(() => {
|
||||||
|
this.addLoading = false
|
||||||
|
this.addVisible = false
|
||||||
|
this.$message.success('申请提交成功')
|
||||||
|
this.loadList()
|
||||||
|
}).catch(() => {
|
||||||
|
this.addLoading = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
normalizeRoomList(roomList, fallbackRoomNumber) {
|
||||||
|
const normalizedList = (Array.isArray(roomList) ? roomList : [])
|
||||||
|
.filter(item => item && item.jsbh)
|
||||||
|
.map(item => ({
|
||||||
|
jsbh: item.jsbh,
|
||||||
|
bz: item.bz || ''
|
||||||
|
}))
|
||||||
|
if (normalizedList.length === 0 && fallbackRoomNumber) {
|
||||||
|
normalizedList.push({ jsbh: fallbackRoomNumber, bz: '' })
|
||||||
|
}
|
||||||
|
return normalizedList
|
||||||
|
},
|
||||||
|
normalizeTeacherList(teacherList) {
|
||||||
|
return (Array.isArray(teacherList) ? teacherList : [])
|
||||||
|
.filter(item => item && item.fzjybh)
|
||||||
|
.map(item => ({ fzjybh: item.fzjybh }))
|
||||||
|
},
|
||||||
|
normalizeTeamList(teamList, fallbackTeamNumber) {
|
||||||
|
const normalizedList = (Array.isArray(teamList) ? teamList : [])
|
||||||
|
.filter(item => item && item.xydbh)
|
||||||
|
.map(item => ({ xydbh: item.xydbh }))
|
||||||
|
if (normalizedList.length === 0 && fallbackTeamNumber) {
|
||||||
|
normalizedList.push({ xydbh: fallbackTeamNumber })
|
||||||
|
}
|
||||||
|
return normalizedList
|
||||||
|
},
|
||||||
|
normalizeSupportList(supportList) {
|
||||||
|
return (Array.isArray(supportList) ? supportList : [])
|
||||||
|
.filter(item => item && item.bztgmxbh)
|
||||||
|
.map(item => ({
|
||||||
|
bztgmxbh: item.bztgmxbh,
|
||||||
|
sl: item.sl === null || item.sl === undefined ? undefined : Number(item.sl)
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
buildSubmitRoomList() {
|
||||||
|
if (!this.addForm.xjsbh) return []
|
||||||
|
const currentRoomList = this.normalizeRoomList(this.addForm.roomList)
|
||||||
|
if (this.addForm.xjsbh === this.addForm.yjsbh && currentRoomList.length > 0) {
|
||||||
|
return currentRoomList
|
||||||
|
}
|
||||||
|
const currentRoom = currentRoomList.find(item => item.jsbh === this.addForm.xjsbh)
|
||||||
|
return [{
|
||||||
|
jsbh: this.addForm.xjsbh,
|
||||||
|
bz: currentRoom ? currentRoom.bz : ''
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
/* ---------- 审批 ---------- */
|
||||||
|
showAuditMenu(row) {
|
||||||
|
return row.sczt === 0 && (row.jyspzzt === 0 || row.jyspzzt === 2 || row.jyspzzt === 3)
|
||||||
|
},
|
||||||
|
openAudit(row) {
|
||||||
|
this.auditForm = {
|
||||||
|
ssdksqbh: row.ssdksqbh,
|
||||||
|
spzt: 1,
|
||||||
|
fhyj: '',
|
||||||
|
sprbh: ''
|
||||||
|
}
|
||||||
|
this.auditVisible = true
|
||||||
|
},
|
||||||
|
submitAudit() {
|
||||||
|
const f = this.auditForm
|
||||||
|
if (f.spzt !== 1 && !f.fhyj) {
|
||||||
|
this.$message.warning('发回/拒绝时请填写审批意见')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const payload = {
|
||||||
|
ssdksqbh: f.ssdksqbh,
|
||||||
|
spzt: f.spzt,
|
||||||
|
fhyj: f.fhyj
|
||||||
|
}
|
||||||
|
if (f.sprbh) payload.sprbh = f.sprbh
|
||||||
|
this.auditLoading = true
|
||||||
|
auditByTeachingOffice(payload).then(() => {
|
||||||
|
this.auditLoading = false
|
||||||
|
this.auditVisible = false
|
||||||
|
this.$message.success('审批成功')
|
||||||
|
this.loadList()
|
||||||
|
}).catch(() => {
|
||||||
|
this.auditLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/* ---------- 撤销 ---------- */
|
||||||
|
handleCancel(row) {
|
||||||
|
this.$confirm('确认撤销该调课申请?', '提示', { type: 'warning' })
|
||||||
|
.then(() => {
|
||||||
|
cancelScheduleAdjust({ ssdksqbh: row.ssdksqbh }).then(() => {
|
||||||
|
this.$message.success('撤销成功')
|
||||||
|
this.loadList()
|
||||||
|
}).catch(() => {})
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
},
|
||||||
|
/* ---------- 详情 ---------- */
|
||||||
|
openDetail(row) {
|
||||||
|
this.detailVisible = true
|
||||||
|
this.detailLoading = true
|
||||||
|
this.detailData = null
|
||||||
|
getScheduleAdjustDetail(row.ssdksqbh).then(response => {
|
||||||
|
this.detailData = response.data || {}
|
||||||
|
this.detailLoading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.detailData = null
|
||||||
|
this.detailLoading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.page-container {
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
|
.section-card {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #ebeef5;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 16px 20px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.header-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 统计卡片 */
|
||||||
|
.stat-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 16px;
|
||||||
|
margin-top: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 16px 20px;
|
||||||
|
border-radius: 6px;
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-text {
|
||||||
|
font-size: 13px;
|
||||||
|
opacity: 0.92;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: 26px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 查询区域 */
|
||||||
|
.search-form {
|
||||||
|
margin-bottom: -16px;
|
||||||
|
|
||||||
|
::v-deep .el-form-item {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.compact-table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.danger-btn {
|
||||||
|
color: #f56c6c;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #f78989;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ops-cell {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-tip {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pick-lesson-btn {
|
||||||
|
margin-top: 6px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-section {
|
||||||
|
margin-top: 16px;
|
||||||
|
|
||||||
|
.sub-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #303133;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 992px) {
|
||||||
|
.page-container .stat-grid {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,484 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container venue-page">
|
||||||
|
<!-- 查询条件 -->
|
||||||
|
<el-card shadow="never" class="search-card">
|
||||||
|
<el-form :model="searchForm" label-width="100px" class="search-form" @submit.native.prevent>
|
||||||
|
<el-row :gutter="24">
|
||||||
|
<el-col :xs="24" :md="8">
|
||||||
|
<el-form-item label="教室编号">
|
||||||
|
<el-input v-model="searchForm.jsbh" placeholder="请输入教室编号" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :md="8">
|
||||||
|
<el-form-item label="教室名称">
|
||||||
|
<el-input v-model="searchForm.jsmc" placeholder="请输入教室名称" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :md="8">
|
||||||
|
<el-form-item label="教学楼代号">
|
||||||
|
<el-input v-model="searchForm.jxldh" placeholder="请输入教学楼代号" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :md="8">
|
||||||
|
<el-form-item label="教学场地类型">
|
||||||
|
<el-select v-model="searchForm.jxcdlx" placeholder="请选择场地类型" clearable filterable allow-create
|
||||||
|
default-first-option class="w-full">
|
||||||
|
<el-option v-for="item in jxcdlxOptions" :key="item" :label="item" :value="item" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :md="8">
|
||||||
|
<el-form-item label="停用">
|
||||||
|
<el-radio-group v-model="searchForm.ty">
|
||||||
|
<el-radio :label="false">否</el-radio>
|
||||||
|
<el-radio :label="true">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :md="8">
|
||||||
|
<div class="search-actions">
|
||||||
|
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 数据列表 -->
|
||||||
|
<el-card shadow="never" class="table-card">
|
||||||
|
<div class="list-header">
|
||||||
|
<div class="list-title">教室列表</div>
|
||||||
|
<div class="list-actions">
|
||||||
|
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新增</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-table v-loading="loading" :data="tableData" border stripe highlight-current-row>
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="jsbh" label="教室编号" width="130" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="jsmc" label="教室名称" width="140" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="jxldh" label="教学楼代号" width="150" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="jxcdlx" label="教学场地类型" width="150" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="jc" label="简称" width="100" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="rnrs" label="容纳人数" width="90" align="center" />
|
||||||
|
<el-table-column prop="mj" label="面积" width="90" align="center" />
|
||||||
|
<el-table-column prop="ksrnrs" label="考试容纳人数" width="110" align="center" />
|
||||||
|
<el-table-column prop="ewyxkbs" label="额外可开班数" width="100" align="center" />
|
||||||
|
<el-table-column label="虚实类型" width="90" align="center">
|
||||||
|
<template slot-scope="scope">{{ fmtXslx(scope.row.xslx) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="停用" width="80" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag :type="isTrue(scope.row.ty) ? 'danger' : 'success'" size="mini">
|
||||||
|
{{ isTrue(scope.row.ty) ? '停用' : '正常' }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="sssb" label="设施设备" width="140" show-overflow-tooltip header-align="center" />
|
||||||
|
<el-table-column label="操作" align="center" fixed="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button type="text" size="mini" icon="el-icon-edit" @click="handleEdit(scope.row)">编辑</el-button>
|
||||||
|
<el-button type="text" size="mini" icon="el-icon-delete" class="danger-text-btn" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<el-pagination
|
||||||
|
class="pagination"
|
||||||
|
background
|
||||||
|
layout="total, sizes, prev, pager, next"
|
||||||
|
:current-page="pageNum"
|
||||||
|
:page-size="pageSize"
|
||||||
|
:total="total"
|
||||||
|
:page-sizes="[10, 20, 50, 100]"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handlePageChange"
|
||||||
|
/>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 新增/编辑弹窗 -->
|
||||||
|
<el-dialog :title="dialog.title" :visible.sync="dialog.visible" width="780px" append-to-body
|
||||||
|
:close-on-click-modal="false">
|
||||||
|
<el-form ref="classroomForm" :model="dialog.form" :rules="rules" label-width="110px">
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="教室名称" prop="jsmc">
|
||||||
|
<el-input v-model="dialog.form.jsmc" placeholder="请输入教室名称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="教学楼代号">
|
||||||
|
<el-input v-model="dialog.form.jxldh" placeholder="请输入教学楼代号" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="教学场地类型">
|
||||||
|
<el-select v-model="dialog.form.jxcdlx" placeholder="请选择场地类型" clearable filterable allow-create
|
||||||
|
default-first-option class="w-full">
|
||||||
|
<el-option v-for="item in jxcdlxOptions" :key="item" :label="item" :value="item" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="简称">
|
||||||
|
<el-input v-model="dialog.form.jc" placeholder="请输入简称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="容纳人数">
|
||||||
|
<el-input-number v-model="dialog.form.rnrs" :min="0" controls-position="right" class="w-full" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="面积">
|
||||||
|
<div class="number-unit-field">
|
||||||
|
<el-input-number
|
||||||
|
v-model="dialog.form.mj"
|
||||||
|
:min="0"
|
||||||
|
:precision="1"
|
||||||
|
controls-position="right"
|
||||||
|
/>
|
||||||
|
<span class="number-unit">㎡</span>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="考试容纳人数">
|
||||||
|
<el-input-number v-model="dialog.form.ksrnrs" :min="0" controls-position="right" class="w-full" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="额外可开班数">
|
||||||
|
<el-input-number v-model="dialog.form.ewyxkbs" :min="0" controls-position="right" class="w-full" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="拼音">
|
||||||
|
<el-input v-model="dialog.form.py" placeholder="请输入拼音" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="虚实类型">
|
||||||
|
<el-radio-group v-model="dialog.form.xslx">
|
||||||
|
<el-radio :label="true">实教</el-radio>
|
||||||
|
<el-radio :label="false">非实教</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="停用">
|
||||||
|
<el-radio-group v-model="dialog.form.ty">
|
||||||
|
<el-radio :label="false">正常</el-radio>
|
||||||
|
<el-radio :label="true">停用</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="设施设备">
|
||||||
|
<el-input v-model="dialog.form.sssb" placeholder="请输入设施设备" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="备注">
|
||||||
|
<el-input v-model="dialog.form.bz" type="textarea" :rows="2" placeholder="请输入备注" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="dialog.visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" :loading="dialog.submitting" @click="submitDialog">确 定</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
addClassroom,
|
||||||
|
deleteClassroom,
|
||||||
|
updateClassroom,
|
||||||
|
listClassroom,
|
||||||
|
listAllClassroom
|
||||||
|
} from '@/api/teachBusiness/classroom'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Venue',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
searchForm: {
|
||||||
|
jsbh: '',
|
||||||
|
jsmc: '',
|
||||||
|
jxldh: '',
|
||||||
|
jxcdlx: '',
|
||||||
|
ty: false
|
||||||
|
},
|
||||||
|
tableData: [],
|
||||||
|
jxcdlxOptions: [],
|
||||||
|
total: 0,
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
dialog: {
|
||||||
|
visible: false,
|
||||||
|
title: '',
|
||||||
|
submitting: false,
|
||||||
|
form: this.createEmptyForm()
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
jsmc: [{ required: true, message: '请输入教室名称', trigger: 'blur' }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.loadVenueTypeOptions()
|
||||||
|
this.fetchList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 独立加载全部场地类型,避免查询结果收窄后下拉候选项同步丢失。
|
||||||
|
*/
|
||||||
|
loadVenueTypeOptions() {
|
||||||
|
return listAllClassroom().then(response => {
|
||||||
|
this.jxcdlxOptions = this.collectVenueTypes(response.data || [])
|
||||||
|
}).catch(() => {
|
||||||
|
// 全量接口异常时保留已收集选项,避免影响列表的基本查询功能。
|
||||||
|
this.mergeVenueTypeOptions(this.tableData)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
collectVenueTypes(classrooms) {
|
||||||
|
const venueTypes = new Set()
|
||||||
|
classrooms.forEach(classroom => {
|
||||||
|
const venueType = classroom.jxcdlx && String(classroom.jxcdlx).trim()
|
||||||
|
if (venueType) {
|
||||||
|
venueTypes.add(venueType)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return Array.from(venueTypes).sort((first, second) => first.localeCompare(second, 'zh-CN'))
|
||||||
|
},
|
||||||
|
|
||||||
|
mergeVenueTypeOptions(classrooms) {
|
||||||
|
const venueTypes = new Set(this.jxcdlxOptions)
|
||||||
|
this.collectVenueTypes(classrooms).forEach(venueType => venueTypes.add(venueType))
|
||||||
|
this.jxcdlxOptions = Array.from(venueTypes)
|
||||||
|
.sort((first, second) => first.localeCompare(second, 'zh-CN'))
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 列表加载 ---------- */
|
||||||
|
fetchList() {
|
||||||
|
this.loading = true
|
||||||
|
const params = {
|
||||||
|
pageNum: this.pageNum,
|
||||||
|
pageSize: this.pageSize
|
||||||
|
}
|
||||||
|
Object.keys(this.searchForm).forEach(key => {
|
||||||
|
const value = this.searchForm[key]
|
||||||
|
if (value !== '' && value !== null && value !== undefined) {
|
||||||
|
params[key] = value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
listClassroom(params).then(response => {
|
||||||
|
const data = response.data || {}
|
||||||
|
this.tableData = data.records || []
|
||||||
|
this.mergeVenueTypeOptions(this.tableData)
|
||||||
|
this.total = data.total || 0
|
||||||
|
}).catch(() => {
|
||||||
|
this.tableData = []
|
||||||
|
this.total = 0
|
||||||
|
}).finally(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 查询 / 重置 ---------- */
|
||||||
|
handleQuery() {
|
||||||
|
this.pageNum = 1
|
||||||
|
this.fetchList()
|
||||||
|
},
|
||||||
|
handleReset() {
|
||||||
|
this.searchForm = {
|
||||||
|
jsbh: '',
|
||||||
|
jsmc: '',
|
||||||
|
jxldh: '',
|
||||||
|
jxcdlx: '',
|
||||||
|
ty: false
|
||||||
|
}
|
||||||
|
this.pageNum = 1
|
||||||
|
this.fetchList()
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 分页 ---------- */
|
||||||
|
handleSizeChange(size) {
|
||||||
|
this.pageSize = size
|
||||||
|
this.pageNum = 1
|
||||||
|
this.fetchList()
|
||||||
|
},
|
||||||
|
handlePageChange(page) {
|
||||||
|
this.pageNum = page
|
||||||
|
this.fetchList()
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 新增 / 编辑 ---------- */
|
||||||
|
handleAdd() {
|
||||||
|
this.dialog.title = '新增教学场地'
|
||||||
|
this.dialog.form = this.createEmptyForm()
|
||||||
|
this.dialog.visible = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.classroomForm) this.$refs.classroomForm.clearValidate()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleEdit(row) {
|
||||||
|
this.dialog.title = '编辑教学场地'
|
||||||
|
this.dialog.form = Object.assign({}, this.createEmptyForm(), row)
|
||||||
|
this.dialog.visible = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.classroomForm) this.$refs.classroomForm.clearValidate()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
submitDialog() {
|
||||||
|
this.$refs.classroomForm.validate(valid => {
|
||||||
|
if (!valid) return
|
||||||
|
this.dialog.submitting = true
|
||||||
|
const payload = this.cleanPayload(this.dialog.form)
|
||||||
|
const isEdit = !!payload.id
|
||||||
|
const req = isEdit ? updateClassroom(payload) : addClassroom(payload)
|
||||||
|
req.then(() => {
|
||||||
|
this.$message.success(isEdit ? '修改成功' : '新增成功')
|
||||||
|
this.dialog.visible = false
|
||||||
|
this.loadVenueTypeOptions()
|
||||||
|
this.fetchList()
|
||||||
|
}).catch(() => {}).finally(() => {
|
||||||
|
this.dialog.submitting = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 删除(后端仅提供单条删除,参数为 id) ---------- */
|
||||||
|
handleDelete(row) {
|
||||||
|
this.$confirm('确定删除教室「' + (row.jsmc || row.jsbh) + '」吗?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
return deleteClassroom(row.id)
|
||||||
|
}).then(() => {
|
||||||
|
this.$message.success('删除成功')
|
||||||
|
this.loadVenueTypeOptions()
|
||||||
|
this.fetchList()
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
|
||||||
|
/* ---------- 工具 ---------- */
|
||||||
|
createEmptyForm() {
|
||||||
|
return {
|
||||||
|
id: '',
|
||||||
|
jsbh: '',
|
||||||
|
jsmc: '',
|
||||||
|
jxldh: '',
|
||||||
|
jxcdlx: '',
|
||||||
|
jc: '',
|
||||||
|
rnrs: null,
|
||||||
|
mj: null,
|
||||||
|
ksrnrs: null,
|
||||||
|
ewyxkbs: null,
|
||||||
|
xh: '',
|
||||||
|
py: '',
|
||||||
|
xslx: false,
|
||||||
|
ty: false,
|
||||||
|
sssb: '',
|
||||||
|
bz: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 移除空值(''/null/undefined),保留 0/false 等有效值 */
|
||||||
|
cleanPayload(obj) {
|
||||||
|
const payload = {}
|
||||||
|
Object.keys(obj).forEach(key => {
|
||||||
|
const value = obj[key]
|
||||||
|
if (value !== '' && value !== null && value !== undefined) {
|
||||||
|
payload[key] = value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return payload
|
||||||
|
},
|
||||||
|
isTrue(val) {
|
||||||
|
return val === true || val === 1 || val === '1' || val === 'true'
|
||||||
|
},
|
||||||
|
fmtXslx(val) {
|
||||||
|
return this.isTrue(val) ? '实教' : '非实教'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.app-container {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.venue-page {
|
||||||
|
.search-card {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
.w-full {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-actions {
|
||||||
|
padding-top: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-card {
|
||||||
|
.list-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.list-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
margin-top: 16px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-unit-field {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.el-input-number {
|
||||||
|
flex: 1;
|
||||||
|
width: auto;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-unit {
|
||||||
|
display: inline-flex;
|
||||||
|
flex: none;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 36px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.danger-text-btn {
|
||||||
|
color: #f56c6c;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #f78989;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,348 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container teach-office">
|
||||||
|
<!-- 查询条件区域 -->
|
||||||
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="88px" v-show="showSearch">
|
||||||
|
<el-form-item label="教研室代号" prop="jysdh">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.jysdh"
|
||||||
|
placeholder="请输入教研室代号"
|
||||||
|
clearable
|
||||||
|
style="width: 160px"
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="教研室名称" prop="jysmc">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.jysmc"
|
||||||
|
placeholder="请输入教研室名称(模糊)"
|
||||||
|
clearable
|
||||||
|
style="width: 180px"
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="部系" prop="bx">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.bx"
|
||||||
|
placeholder="请输入部系"
|
||||||
|
clearable
|
||||||
|
style="width: 160px"
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="停用" prop="ty">
|
||||||
|
<el-radio-group v-model="queryParams.ty">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">查询</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<!-- 操作按钮区域 -->
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="info" plain icon="el-icon-upload2" size="mini" @click="openImport">导入</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 数据列表区域 -->
|
||||||
|
<el-table v-loading="loading" :data="officeList" border :height="tableHeight">
|
||||||
|
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||||
|
<el-table-column label="教研室代号" align="center" prop="jysdh" min-width="110" />
|
||||||
|
<el-table-column label="教研室名称" align="center" prop="jysmc" min-width="160" :show-overflow-tooltip="true" />
|
||||||
|
<el-table-column label="简称" align="center" prop="jc" min-width="90" />
|
||||||
|
<el-table-column label="部系" align="center" prop="bx" min-width="100" />
|
||||||
|
<el-table-column label="机关性质" align="center" min-width="90">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag :type="scope.row.jgxz ? 'primary' : 'info'" size="mini">{{ scope.row.jgxz ? '是' : '否' }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="备注" align="center" prop="bz" min-width="120" :show-overflow-tooltip="true" />
|
||||||
|
<el-table-column label="操作" align="center" min-width="140" class-name="small-padding fixed-width">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">编辑</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-circle-close"
|
||||||
|
style="color: #f56c6c"
|
||||||
|
:disabled="scope.row.ty === 1"
|
||||||
|
@click="handleDisable(scope.row)"
|
||||||
|
>停用</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination
|
||||||
|
v-show="total > 0"
|
||||||
|
:total="total"
|
||||||
|
:page.sync="queryParams.pageNum"
|
||||||
|
:limit.sync="queryParams.pageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 新增/编辑对话框 -->
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="560px" append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||||
|
<el-form-item label="教研室代号" prop="jysdh">
|
||||||
|
<el-input v-model="form.jysdh" placeholder="请输入教研室代号" :disabled="!isAdd" maxlength="20" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="教研室名称" prop="jysmc">
|
||||||
|
<el-input v-model="form.jysmc" placeholder="请输入教研室名称" maxlength="50" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="简称" prop="jc">
|
||||||
|
<el-input v-model="form.jc" placeholder="请输入简称" maxlength="20" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="部系" prop="bx">
|
||||||
|
<el-input v-model="form.bx" placeholder="请输入部系" maxlength="30" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="序号" prop="xh">
|
||||||
|
<el-input v-model="form.xh" placeholder="请输入序号" maxlength="10" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="bz">
|
||||||
|
<el-input v-model="form.bz" type="textarea" placeholder="请输入备注" :rows="3" maxlength="200" show-word-limit />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 导入对话框 -->
|
||||||
|
<el-dialog title="教研室数据导入" :visible.sync="importOpen" width="420px" append-to-body>
|
||||||
|
<el-upload
|
||||||
|
ref="uploadRef"
|
||||||
|
:action="importUrl"
|
||||||
|
:headers="uploadHeaders"
|
||||||
|
:on-success="handleImportSuccess"
|
||||||
|
:on-error="handleImportError"
|
||||||
|
:limit="1"
|
||||||
|
:before-upload="beforeImport"
|
||||||
|
accept=".xls, .xlsx"
|
||||||
|
drag
|
||||||
|
>
|
||||||
|
<i class="el-icon-upload"></i>
|
||||||
|
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||||
|
<div class="el-upload__tip text-center" slot="tip">
|
||||||
|
<span>仅允许导入 xls、xlsx 格式文件。</span>
|
||||||
|
</div>
|
||||||
|
</el-upload>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitImport">确 定</el-button>
|
||||||
|
<el-button @click="importOpen = false">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listOffice, addOffice, updateOffice, disableOffice } from "@/api/teachOffice/office"
|
||||||
|
import { getToken } from '@/utils/auth'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Office",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 遮罩层
|
||||||
|
loading: true,
|
||||||
|
// 显示搜索条件
|
||||||
|
showSearch: true,
|
||||||
|
// 表格高度
|
||||||
|
tableHeight: window.innerHeight - 280,
|
||||||
|
// 总条数
|
||||||
|
total: 0,
|
||||||
|
// 教研室列表数据
|
||||||
|
officeList: [],
|
||||||
|
// 弹出层标题
|
||||||
|
title: "",
|
||||||
|
// 是否显示新增/编辑弹出层
|
||||||
|
open: false,
|
||||||
|
// 是否新增(false 为编辑)
|
||||||
|
isAdd: true,
|
||||||
|
// 是否显示导入弹出层
|
||||||
|
importOpen: false,
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
jysdh: undefined,
|
||||||
|
jysmc: undefined,
|
||||||
|
bx: undefined,
|
||||||
|
ty: 0
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
// 表单校验
|
||||||
|
rules: {
|
||||||
|
jysdh: [
|
||||||
|
{ required: true, message: "教研室代号不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
jysmc: [
|
||||||
|
{ required: true, message: "教研室名称不能为空", trigger: "blur" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
importUrl() {
|
||||||
|
return process.env.VUE_APP_BASE_API + '/jys/office/import'
|
||||||
|
},
|
||||||
|
uploadHeaders() {
|
||||||
|
return { Authorization: 'Bearer ' + getToken() }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 查询教研室列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
listOffice(this.queryParams).then(response => {
|
||||||
|
// 后端返回 MyBatis-Plus 分页结构:data.records / data.total
|
||||||
|
const data = response.data || {}
|
||||||
|
this.officeList = data.records || []
|
||||||
|
this.total = data.total || 0
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.officeList = []
|
||||||
|
this.total = 0
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 查询按钮 */
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
/** 重置按钮 */
|
||||||
|
resetQuery() {
|
||||||
|
this.resetForm("queryForm")
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
/** 新增按钮 */
|
||||||
|
handleAdd() {
|
||||||
|
this.reset()
|
||||||
|
this.isAdd = true
|
||||||
|
this.open = true
|
||||||
|
this.title = "新增教研室"
|
||||||
|
},
|
||||||
|
/** 编辑按钮 */
|
||||||
|
handleUpdate(row) {
|
||||||
|
this.reset()
|
||||||
|
this.isAdd = false
|
||||||
|
// 编辑:jysdh 必传
|
||||||
|
this.form = {
|
||||||
|
jysdh: row.jysdh,
|
||||||
|
jysmc: row.jysmc,
|
||||||
|
jc: row.jc,
|
||||||
|
bx: row.bx,
|
||||||
|
xh: row.xh,
|
||||||
|
bz: row.bz
|
||||||
|
}
|
||||||
|
this.open = true
|
||||||
|
this.title = "编辑教研室"
|
||||||
|
},
|
||||||
|
/** 停用按钮 */
|
||||||
|
handleDisable(row) {
|
||||||
|
const jysdh = row.jysdh
|
||||||
|
this.$modal.confirm('确认停用教研室【' + row.jysmc + '】吗?').then(() => {
|
||||||
|
return disableOffice(jysdh)
|
||||||
|
}).then(() => {
|
||||||
|
this.getList()
|
||||||
|
this.$modal.msgSuccess("停用成功")
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
/** 提交表单 */
|
||||||
|
submitForm() {
|
||||||
|
this.$refs["form"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
if (this.isAdd) {
|
||||||
|
addOffice(this.form).then(response => {
|
||||||
|
this.$modal.msgSuccess("新增成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
}).catch(() => {})
|
||||||
|
} else {
|
||||||
|
updateOffice(this.form).then(response => {
|
||||||
|
this.$modal.msgSuccess("修改成功")
|
||||||
|
this.open = false
|
||||||
|
this.getList()
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 重置表单 */
|
||||||
|
reset() {
|
||||||
|
this.form = {
|
||||||
|
jysdh: undefined,
|
||||||
|
jysmc: undefined,
|
||||||
|
jc: undefined,
|
||||||
|
bx: undefined,
|
||||||
|
xh: undefined,
|
||||||
|
bz: undefined
|
||||||
|
}
|
||||||
|
this.resetForm("form")
|
||||||
|
},
|
||||||
|
/** 取消按钮 */
|
||||||
|
cancel() {
|
||||||
|
this.open = false
|
||||||
|
this.reset()
|
||||||
|
},
|
||||||
|
/** 打开导入对话框 */
|
||||||
|
openImport() {
|
||||||
|
this.importOpen = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.uploadRef) {
|
||||||
|
this.$refs.uploadRef.clearFiles()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 导入前校验文件格式 */
|
||||||
|
beforeImport(file) {
|
||||||
|
const name = file.name.toLowerCase()
|
||||||
|
if (!name.endsWith('.xls') && !name.endsWith('.xlsx')) {
|
||||||
|
this.$modal.msgError('仅支持 xls、xlsx 格式文件')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
/** 提交导入 */
|
||||||
|
submitImport() {
|
||||||
|
const files = this.$refs.uploadRef.uploadFiles
|
||||||
|
if (!files || files.length === 0) {
|
||||||
|
this.$modal.msgError('请选择要导入的文件')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$refs.uploadRef.submit()
|
||||||
|
},
|
||||||
|
/** 导入成功 */
|
||||||
|
handleImportSuccess(response) {
|
||||||
|
this.importOpen = false
|
||||||
|
this.$alert("<div style='overflow:auto;overflow-x:hidden;max-height:70vh;padding:10px 20px 0;'>" + response.msg + '</div>', '导入结果', { dangerouslyUseHTMLString: true })
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
/** 导入失败 */
|
||||||
|
handleImportError() {
|
||||||
|
this.$modal.msgError('导入失败,请稍后重试')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.teach-office {
|
||||||
|
.mb8 {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user