Files
UserclassFront/src/views/classManage/Christianity.vue
T
lijing 542002bb85 fix(render): 修复表格内点击无响应(Vue2 on:{click} → Vue3 onClick)
班级管理「班主任/副班主任/校区」三列、任教管理操作列用的是
h(..., { on: { click: fn } })。Vue3 不再识别 on 对象,事件根本没绑上,
所以点单元格毫无反应。改为顶层 onClick(含带 stopPropagation 的清空按钮),
treeMixin 的树节点点击同步修正。
2026-10-20 15:16:55 +08:00

760 lines
24 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="page-wrapper yh-fill">
<div class="main-container">
<div class="container-full-height">
<div class="layout-flex-row">
<!-- 左侧树形容器 高度撑满、内部滚动 -->
<div class="tree-wrap">
<my-tree :treeData="treeData" :selectId="selectnodeid" @on-tree-click="treeLink"></my-tree>
</div>
<!-- 右侧整体容器 高度撑满 -->
<div class="right-full-wrap">
<!-- 顶部按钮栏 固定高度不滚动 -->
<div class="top-btn-bar">
<Dropdown trigger="click" @on-click="changefieid">
<Button type="primary">
添加班级
<Icon type="ios-arrow-down"></Icon>
</Button>
<template #list><DropdownMenu>
<DropdownItem name="openAddSingleClass">添加单个班级</DropdownItem>
<DropdownItem name="openMultiNumModal">添加多个班级</DropdownItem>
</DropdownMenu></template>
</Dropdown>
<Button type="success" style="margin-left:10px" @click="openImportModal">班级信息导入</Button>
</div>
<!-- 表格容器:填充剩余高度,纵向滚动 -->
<div class="table-auto-scroll">
<Table
stripe
:columns="tableColumns"
:data="tableData"
></Table>
</div>
</div>
</div>
<!-- 弹窗1:添加多个班级 设置数量 -->
<Modal v-model="multiClassModal" title="设置添加班级数量" width="400">
<div style="padding:16px 8px;">
<div style="display:flex;align-items:center;">
<span style="width:80px;">班级数</span>
<Input v-model.number="addClassCount" type="number" min="1" />
</div>
</div>
<template #footer><div align="right">
<Button @click="multiClassModal = false">取消</Button>
<Button type="primary" @click="submitBatchAdd">提交</Button>
</div></template>
</Modal>
<!-- 弹窗2:班级信息导入 -->
<Modal v-model="importModal" title="班级信息导入" width="560">
<!-- <div style="padding:18px 10px;display:flex;align-items:center;gap:20px;">
<Upload action="" :before-upload="beforeUpload">
<Button>选择要上传的文件</Button>
</Upload>
<a href="javascript:;" style="color:#2d7ff9" @click="downloadTemplate">点击链接下载[用户导入模板.xls]</a>
</div>
<div slot="footer" align="right">
<Button @click="importModal = false">取消</Button>
<Button type="primary" @click="confirmImport">确定</Button>
</div> -->
<div class="main-contents">
<Form ref="UpParmas.datapre" :model="UpParmas.datapre" ::label-width="100" inline>
<FormItem label="Excel上传:" style="margin-bottom:10px;width:100%;">
<Input type="text" style="width:90%;" v-model="UpParmas.fileName" class="import-input" placeholder="未选中任何文件.." readonly></Input>
<Upload class="fr btn"
:action="UpParmas.actionUrl"
:data="UpParmas.datapre"
:show-upload-list="false"
:headers="uploadHeader"
accept=".xls,.xlsx"
:before-upload="handleUpload"
:on-success="importFile"
>
<Button icon="md-add"></Button>
</Upload>
</FormItem>
<FormItem v-if="UpParmas.fileName" style="margin-bottom:10px">
<div v-if="UpParmas.listData.code!=0" style="color:red">导入失败,请修改Excel文件中相关数据后再重新上传!</div>
<div v-if="UpParmas.listData.code==0" style="color:green">导入成功!</div>
</FormItem>
</Form>
<Alert show-icon>
操作说明:
<template #icon><Icon type="ios-bulb-outline" size="20"></Icon></template>
<template #desc style="font-size: 12px;">
请先上传EXCEL文件,若成功则显示导入成功数据,否则显示错误的数据及错误原因;<br>
EXCEL文件的格式():工作表(WorkSheet)的名称应设为缺省的[Sheet1];<br>
<a @click="MoBanExceldaochu" style="font-size:12px;">点击链接下载[班级导入模板.xls]</a>
</template>
</Alert>
<Table :columns="UpParmas.columns" :data="UpParmas.listData.data" v-if="UpParmas.listData.data"></Table>
</div>
<Spin fix v-if="spinShow">
<Icon type="ios-loading" size=30 class="demo-spin-icon-load"></Icon>
<div>上传中...</div>
</Spin>
<template #footer><div>
<i-Button @click="UpfileModalcloseclick" style="margin-left: 8px">关闭</i-Button>
</div></template>
</Modal>
<!-- 弹窗3:选择教师 -->
<Modal v-model="selectTeacherModal" title="选择教师" width="420">
<div style="padding:10px 5px;">
<div style="margin-bottom:16px;display:flex;align-items:center;">
<span style="width:75px;">科室</span>
<Select v-model="deptFilter" placeholder="按科室过滤" style="flex:1" @on-change="getteacherSelect" clearable>
<Option v-for="item in groupteacherSelectlist" :key="item.id" :value="item.id">{{ item.name }}</Option>
</Select>
</div>
<div style="display:flex;align-items:center;">
<span style="width:75px;">教师</span>
<Select v-model="selectedTeacher" style="flex:1" filterable>
<Option v-for="item in teacherSelectlist" :key="item.id" :value="item.id">{{ item.name }}</Option>
</Select>
</div>
</div>
<template #footer><div align="right">
<Button @click="selectTeacherModal = false">取消</Button>
<Button type="primary" @click="confirmSelectTeacher">提交</Button>
</div></template>
</Modal>
<!-- 弹窗5:选择校区 -->
<Modal v-model="selectCampusModal" title="选择校区" width="420">
<div style="padding:10px 5px;">
<div style="display:flex;align-items:center;">
<span style="width:75px;">校区</span>
<Select v-model="selectedCampus" style="flex:1" placeholder="请选择">
<Option v-for="item in campusselectlist" :key="item.id" :value="item.id">{{ item.name }}</Option>
</Select>
</div>
</div>
<template #footer><div align="right">
<Button @click="selectCampusModal = false">取消</Button>
<Button type="primary" @click="confirmSelectCampus">提交</Button>
</div></template>
</Modal>
</div>
</div>
</div>
</template>
<script>
import { Button, Input } from "view-ui-plus";
import myTree from "../../components/my_tree";
export default {
components: { myTree},
name: 'ClassHeightFullPage',
data() {
return {
schsystemId:'',
selectnodeid:'',
treeData: [],
selectedTreeNode: null,
selectGrade: '预备',
multiClassModal: false,
addClassCount: 2,
importModal: false,
spinShow:false,
selectTeacherModal: false,
editRowIndex: null,
editField: '',
deptFilter: '',
selectedTeacher: '',
selectCampusModal: false,
campusEditIndex: null,
selectedCampus: '',
tableColumns: [],
tableData: [],
campusselectlist:[],
groupteacherSelectlist:[],
teacherSelectlist:[],
UpParmas:{
fileName:'',
listData:{},
datapre:{},
actionUrl:APIConfig.BschClassSystem.schclassImport,
columns:[
{
title: '行号',
key: 'rows',
align: 'center',
width:'80'
},
{
title: '内容',
key: 'columnValue',
align: 'center',
},
{
title: '错误详情',
key: 'errorMsg',
align: 'center',
}
],
},
}
},
computed: {
uploadHeader() { //附件上传header
let config = {};
if (localStorage.getItem("currentRole")) {
let currentRole = localStorage.getItem("currentRole");
config["currentRole"] = currentRole;
}
return config;
},
},
created() {
this.getGradeTree();
this.getgroupteacherSelect();
this.getteacherSelect();
this.getcampusselect();
this.initTableColumn();
},
mounted() {
},
methods: {
//获取年级树
getGradeTree:function(){
const _this = this;
var item={};
_this.$api.get(APIConfig.BschClassSystem.getGradeTree, item, resp => {
if(resp.code==0)
{
_this.treeData = resp.data;
if(resp.data.children.length>0){
// 起始节点为 data
const pathArr = _this.getFirstPath(resp.data);
_this.selectnodeid=pathArr[pathArr.length-1].id;
_this.schsystemId=pathArr[pathArr.length-1].schsystemId;
_this.getsearcBaseSchClass();
}
}else{
_this.treeData=[];
}
});
},
//获取最后一级的map
getFirstPath(rootNode) {
const path = [];
let cur = rootNode;
while (cur) {
// 存入当前层级关键信息
path.push({
id: cur.id,
name: cur.name,
type: cur.type,
schsystemId:cur.schsystemId,
gradeId:cur.gradeId,
classId:cur.classId,
});
// 有子节点就取第一个,没有就终止
if (cur.children && cur.children.length > 0) {
cur = cur.children[0];
} else {
cur = null;
}
}
return path;
},
//获取班级列表
getsearcBaseSchClass:function(){
const _this = this;
var item={
schsystemId:this.schsystemId,
gradeId:this.selectnodeid
};
_this.$api.get(APIConfig.BschClassSystem.getsearcBaseSchClass, item, resp => {
if(resp.code==0)
{
_this.tableData = resp.data;
}else{
_this.tableData=[];
}
});
},
//教师组下拉
getgroupteacherSelect:function(){
const _this = this;
var item={};
_this.$api.get(APIConfig.BschClassSystem.getgroupteacherSelect, item, resp => {
if(resp.code==0)
{
_this.groupteacherSelectlist= resp.data;
}else{
_this.groupteacherSelectlist=[];
}
});
},
//教师下拉
getteacherSelect:function(){
const _this = this;
var item={
groupId:_this.deptFilter
};
_this.$api.get(APIConfig.BschClassSystem.getteacherSelect, item, resp => {
if(resp.code==0)
{
_this.teacherSelectlist= resp.data;
}else{
_this.teacherSelectlist=[];
}
});
},
//校区下拉
getcampusselect:function(){
const _this = this;
var item={};
_this.$api.get(APIConfig.BschClassSystem.getcampusselect, item, resp => {
if(resp.code==0)
{
_this.campusselectlist= resp.data;
}else{
_this.campusselectlist=[];
}
});
},
//节点点击事件
treeLink(treeNode){
this.schsystemId=treeNode.schsystemId;
this.selectnodeid=treeNode.id;
this.getsearcBaseSchClass();
},
initTableColumn() {
this.tableColumns = [
{ title: '序号', type: 'index', align: 'center', width: 70 },
{ title: '班级名称', key: 'name', align: 'center', width: 100 },
{
title: '班级别名',
align: 'center',
render: (h, params) => {
return h(Input, {modelValue: params.row.cname,
'onUpdate:modelValue': (val) => {
params.row.classAlias = val
this.cellChange(params.index, 'classAlias', val)
},
style: { width: '150px' }})
}
},
{
title: '班主任',
align: 'center',
width: 160,
render: (h, params) => {
return h('div', {
style: {
display: 'flex',
alignItems: 'center',
width: '140px',
height: '34px',
border: '1px solid #dcdcdc',
borderRadius: '4px',
cursor: 'pointer',
margin: '0 auto'
},
onClick: () => this.openTeacherSelect(params.index, 'headTeacher')
}, [
h('span', {
style: {
flex: 1,
textAlign: 'center',
fontSize: '14px',
paddingLeft: '6px',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'
}
}, params.row.firstTeacherName || ''),
params.row.firstTeacherName ? h('span', {
style: {
width: '22px',
height: '22px',
lineHeight: '22px',
textAlign: 'center',
color: 'red',
borderLeft: '1px solid #eee',
flexShrink: 0,
fontSize: '14px'
},
onClick: (e) => {
e.stopPropagation()
var item={
id:params.row.id,
firstTeacherId:null
};
let url=APIConfig.BschClassSystem.editClassFirstTeacher;
this.$api.post(url, item, resp => {
if(resp.code==0)
{
this.$Message.success(`设置教师成功`);
this.getsearcBaseSchClass();
}
});
}
}, '×') : null
])
}
},
{
title: '副班主任',
align: 'center',
width: 160,
render: (h, params) => {
return h('div', {
style: {
display: 'flex',
alignItems: 'center',
width: '140px',
height: '34px',
border: '1px solid #dcdcdc',
borderRadius: '4px',
cursor: 'pointer',
margin: '0 auto'
},
onClick: () => this.openTeacherSelect(params.index, 'secondTeacherName')
}, [
h('span', {
style: {
flex: 1,
textAlign: 'center',
fontSize: '14px',
paddingLeft: '6px',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'
}
}, params.row.secondTeacherName || ''),
params.row.secondTeacherName ? h('span', {
style: {
width: '22px',
height: '22px',
lineHeight: '22px',
textAlign: 'center',
color: 'red',
borderLeft: '1px solid #eee',
flexShrink: 0,
fontSize: '14px'
},
onClick: (e) => {
e.stopPropagation()
var item={
id:params.row.id,
secondTeacherId:null
};
let url=APIConfig.BschClassSystem.editClassSecondTeacher;
this.$api.post(url, item, resp => {
if(resp.code==0)
{
this.$Message.success(`设置教师成功`);
this.getsearcBaseSchClass();
}
});
}
}, '×') : null
])
}
},
{
title: '校区',
align: 'center',
width: 160,
render: (h, params) => {
return h('div', {
style: {
display: 'flex',
alignItems: 'center',
width: '140px',
height: '34px',
border: '1px solid #dcdcdc',
borderRadius: '4px',
cursor: 'pointer',
margin: '0 auto'
},
onClick: () => this.openCampusSelect(params.index)
}, [
h('span', {
style: {
flex: 1,
textAlign: 'center',
fontSize: '14px',
paddingLeft: '6px',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'
}
}, params.row.campusName || ''),
params.row.campusName ? h('span', {
style: {
width: '22px',
height: '22px',
lineHeight: '22px',
textAlign: 'center',
color: 'red',
borderLeft: '1px solid #eee',
flexShrink: 0,
fontSize: '14px'
},
onClick: (e) => {
e.stopPropagation()
var item={
id:params.row.id,
campusId:null
};
let url=APIConfig.BschClassSystem.editClassCampus;
this.$api.post(url, item, resp => {
if(resp.code==0)
{
this.$Message.success(`校区设置成功`);
this.getsearcBaseSchClass();
}
});
}
}, '×') : null
])
}
},
{
title: '操作',
align: 'center',
width: 100,
render: (h, params) => {
return h('div', { style: { display: 'flex', gap: '8px', justifyContent: 'center' } }, [
h(Button, {icon: 'ios-eye-outline', type: 'text', size: 'large',
onClick: () => this.viewDetail(params.row)}),
h(Button, {icon: 'ios-trash-outline', type: 'text', color: 'red', size: 'large',disabled:params.row.disableDel,
onClick: () => this.deleteRow(params.index, params.row)})
])
}
}
]
},
loadTableData() {
console.log('当前筛选年级:', this.selectGrade)
// 替换后端请求
},
cellChange(rowIndex, field, value) {
var item={
id:this.tableData[rowIndex].id,
cname:value
};
this.$api.post(APIConfig.BschClassSystem.editClassName, item, resp => {
if(resp.code==0)
{
// this.$Message.success(`设置班级名称成功`);
this.getsearcBaseSchClass();
}
});
},
//自定义类型添加
changefieid:function(name){
var _this=this;
if(name=="openAddSingleClass")
{
var item={
gradeId:_this.selectnodeid,
number:1
};
_this.$api.post(APIConfig.BschClassSystem.addBaseSchClass, item, resp => {
if(resp.code==0)
{
this.$Message.success(`新增1个班级!`);
this.getsearcBaseSchClass();
}
});
}else if(name=="openMultiNumModal")
{
this.addClassCount = 2
this.multiClassModal = true
}
},
//批量增加班级
submitBatchAdd() {
if (this.addClassCount < 1) return this.$Message.warning('班级数量不能小于1');
var item={
gradeId:this.selectnodeid,
number:this.addClassCount
};
this.$api.post(APIConfig.BschClassSystem.addBaseSchClass, item, resp => {
if(resp.code==0)
{
this.$Message.success(`批量新增${this.addClassCount}个班级`);
this.getsearcBaseSchClass();
this.multiClassModal = false;
}
});
},
openImportModal() {
this.importModal = true
},
//导入成功返回
importFile(response, file, fileList){
const _this=this;
console.log(response);
console.log(file);
_this.spinShow=false;
_this.UpParmas.fileName=file.name;
_this.UpParmas.listData=response;
if(response.code==0)
{
_this.$Message.info('导入成功!');
_this.getsearcBaseSchClass();
}else{
_this.$Message.info(response.Message);
}
},
//附件上传之前的方法
handleUpload:function(file){
const _this=this;
_this.spinShow=true;
},
MoBanExceldaochu() {
var _this = this;
if (localStorage.getItem("currentRole")) {
let currentRole = localStorage.getItem("currentRole");
let { schId, roleId, userId, childId } = JSON.parse(decodeURIComponent(currentRole));
var url=APIConfig.BschClassSystem.schclassdownloadTemplate+'?schId='+schId;
window.location.href=url;
}else{
this.$Message.info('获取不了学校!');
}
},
//附件上传模态框关闭事件
UpfileModalcloseclick:function(){
this.importModal=false;
this.UpParmas={
fileName:'',
listData:{},
datapre:{},
}
},
openTeacherSelect(index, field) {
this.editRowIndex = index
this.editField = field
this.deptFilter = ''
this.selectedTeacher =field=='headTeacher'? this.tableData[index].firstTeacherId:this.tableData[index].secondTeacherId;
this.selectTeacherModal = true
},
confirmSelectTeacher() {
if (!this.selectedTeacher) return this.$Message.warning('请选择教师');
var item={
id:this.tableData[this.editRowIndex].id
};
if(this.editField=='headTeacher'){
item.firstTeacherId=this.selectedTeacher;
}else{
item.secondTeacherId=this.selectedTeacher;
}
let url=this.editField=='headTeacher'?APIConfig.BschClassSystem.editClassFirstTeacher:APIConfig.BschClassSystem.editClassSecondTeacher;
this.$api.post(url, item, resp => {
if(resp.code==0)
{
this.$Message.success(`设置教师成功`);
this.getsearcBaseSchClass();
this.selectTeacherModal = false;
}
});
},
openCampusSelect(index) {
this.campusEditIndex = index
this.selectedCampus = this.tableData[index].campusId;
this.selectCampusModal = true
},
confirmSelectCampus() {
var item={
id:this.tableData[this.campusEditIndex].id,
campusId:this.selectedCampus
};
let url=APIConfig.BschClassSystem.editClassCampus;
this.$api.post(url, item, resp => {
if(resp.code==0)
{
this.$Message.success(`校区设置成功`);
this.getsearcBaseSchClass();
this.selectCampusModal = false;
}
});
},
viewDetail(row) {
this.$router.push('/ChristianityDetail?gradeId='+row.gradeId+'&classId='+row.classId+'&gradeclassName='+row.gradeName+row.name);
},
deleteRow(index, row) {
this.$Modal.confirm({
title: '确认删除',
content: `确定删除班级「${row.name}」吗?`,
onOk: () => {
var url=APIConfig.BschClassSystem.deleteBaseSchClass+this.tableData[index].id;
this.$api.post(url,{},(resp)=>{
this.$Message.success('删除成功!');
this.getsearcBaseSchClass();
});
}
})
}
}
}
</script>
<style scoped>
/* 根容器占满父高度 */
.container-full-height {width: 100%; height: 100%; box-sizing: border-box; display: flex; flex-direction: column}
.layout-flex-row {
display: flex;
flex: 1;
gap: 16px;
min-height: 0;
}
/* 左侧树形 压到底部、内部滚动 */
.tree-wrap {
width: 220px;
border: 1px solid #e8e8e8;
padding: 8px;
overflow-y: auto;
flex-shrink: 0;
}
/* 右侧整体容器 高度填充 */
.right-full-wrap {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0;
min-height: 0;
}
/* 顶部按钮栏 固定不滚动 */
.top-btn-bar {
padding-bottom: 14px;
flex-shrink: 0;
}
/* 表格区域:自动填充剩余高度,纵向滚动 */
.table-auto-scroll {
flex: 1;
overflow: auto;
min-height: 0;
}
</style>
<style>
.ivu-alert-desc{
font-size: 12px;
}
</style>