Merge branch 'developer'
BIN
public/img/bg/003.PNG
Normal file
|
After Width: | Height: | Size: 419 KiB |
BIN
public/img/bg/12345.jpg
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
public/img/bg/bf.jpg
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
public/img/bg/bfnew.jpg
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/img/bg/cglz.jpg
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/img/bg/cgsq.jpg
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
public/img/bg/city.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
public/img/bg/cloud.jpg
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
public/img/bg/czLogin.png
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
public/img/bg/db.jpg
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
public/img/bg/inExam.jpg
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/img/bg/lyys.jpg
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/img/bg/outExam.jpg
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/img/bg/star-squashed.jpg
Normal file
|
After Width: | Height: | Size: 359 KiB |
BIN
public/img/bg/ten_logo.jpg
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
public/img/bg/ten_logo.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/img/bg/userphotobg.jpg
Normal file
|
After Width: | Height: | Size: 125 KiB |
BIN
public/img/bg/ybf.jpg
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
public/img/bg/zss.jpeg
Normal file
|
After Width: | Height: | Size: 131 KiB |
BIN
public/img/chartImg/1.jpeg
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
public/img/chartImg/2.jpeg
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
public/img/chartImg/3.jpeg
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
public/img/chartImg/4.jpeg
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/img/chartImg/5.jpeg
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
public/img/chartImg/6.jpeg
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/img/chartImg/7.jpeg
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
public/img/chartImg/8.jpeg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/img/chartImg/9.jpeg
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
public/img/default/no_pic.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
public/img/dormRoom/6.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
public/img/enroll/app-upload.jpg
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
public/img/enroll/certificate.png
Normal file
|
After Width: | Height: | Size: 516 KiB |
BIN
public/img/enroll/courseimg/anjian-head-bg.jpg
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
public/img/enroll/courseimg/anjian-list-submenu-bg.jpg
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
public/img/enroll/courseimg/list-ico-1.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
public/img/enroll/courseimg/list-ico-2.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
public/img/enroll/courseimg/list-logo.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
public/img/enroll/courseimg/page-ico-a.jpg
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
public/img/enroll/courseimg/page-ico-b.jpg
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
public/img/enroll/courseimg/radia-2.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
public/img/enroll/login-bg.jpg
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
public/img/enroll/login-title.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
public/img/enroll/logo.png
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
public/img/enroll/radia-1.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
public/img/enroll/radia-2.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
public/img/enroll/register-title.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
public/img/homePage/building.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
public/img/homePage/class_leave.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
public/img/homePage/company_change.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
public/img/homePage/dorm_leave.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
public/img/homePage/stu_leave.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
public/img/homePage/trainProjectApply.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
public/img/homePage/trainProjectArrived.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
public/img/login/20150407100539_39849.jpeg
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
public/img/login/logo.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
public/img/login/pkucloud1h100.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
public/img/pdf/more_big.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
public/img/pdf/more_small.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
public/img/pdf/next_icon.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
public/img/pdf/pre_icon.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
public/img/pdf/roate_icon.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
public/img/support/board/.bg.png.icloud
Normal file
BIN
public/img/support/board/samiao.png
Normal file
|
After Width: | Height: | Size: 197 KiB |
BIN
public/img/test/bydkl.jpg
Normal file
|
After Width: | Height: | Size: 284 KiB |
BIN
public/img/test/bylcl.jpg
Normal file
|
After Width: | Height: | Size: 296 KiB |
BIN
public/img/test/gwlx.jpg
Normal file
|
After Width: | Height: | Size: 302 KiB |
BIN
public/img/test/jyxstj.jpg
Normal file
|
After Width: | Height: | Size: 241 KiB |
BIN
public/img/test/qddk.jpg
Normal file
|
After Width: | Height: | Size: 264 KiB |
BIN
public/img/test/shpxrs.jpg
Normal file
|
After Width: | Height: | Size: 294 KiB |
BIN
public/img/test/xszcrs.jpg
Normal file
|
After Width: | Height: | Size: 296 KiB |
BIN
public/img/test/xydsjjc.jpg
Normal file
|
After Width: | Height: | Size: 440 KiB |
BIN
public/img/test/zbtj.jpg
Normal file
|
After Width: | Height: | Size: 383 KiB |
@@ -52,6 +52,18 @@ export const getObj = (id: string | number) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据学号获取学生详细信息(用于详情页面)
|
||||||
|
* @param query
|
||||||
|
*/
|
||||||
|
export const getStudentInfoDetail = (query: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/basic/basicstudentinfo/page',
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据学号获取信息
|
* 根据学号获取信息
|
||||||
* @param stuNo
|
* @param stuNo
|
||||||
@@ -492,11 +504,10 @@ export const exportStudentData = (data: any) => {
|
|||||||
/**
|
/**
|
||||||
* 申请顶岗
|
* 申请顶岗
|
||||||
* @param data
|
* @param data
|
||||||
* TODO: 接口文档中未找到此接口,请提供正确的接口地址
|
|
||||||
*/
|
*/
|
||||||
export const applyInternship = (data: any) => {
|
export const applyInternship = (data: any) => {
|
||||||
return request({
|
return request({
|
||||||
url: '/basic/basicstudent/applyInternship', // TODO: 接口文档中未找到此接口
|
url: '/work/jobfairstu/batchSaveJobFairStu',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data,
|
data: data,
|
||||||
});
|
});
|
||||||
@@ -519,15 +530,13 @@ export const importCertificate = (formData: FormData) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 证书导出
|
* 创建证书导出异步任务
|
||||||
* @param data
|
* @param data 查询参数
|
||||||
* TODO: 接口文档中未找到此接口,请提供正确的接口地址
|
|
||||||
*/
|
*/
|
||||||
export const exportCertificate = (data: any) => {
|
export const makeExportSkillLevelTask = (data?: any) => {
|
||||||
return request({
|
return request({
|
||||||
url: '/basic/basicstudent/exportCertificate', // TODO: 接口文档中未找到此接口
|
url: '/ems/file/makeExportSkillLevelTask',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data,
|
data: data,
|
||||||
responseType: 'blob',
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -115,9 +115,9 @@ export function revokeAgent(applyId: number | string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存实施采购方式(分步骤实施采购-第一步)
|
* 保存实施采购途径(分步骤实施采购-第一步)
|
||||||
* @param id 采购申请ID
|
* @param id 采购申请ID
|
||||||
* @param implementType 实施采购方式:1-自行组织采购,2-委托代理采购
|
* @param implementType 实施采购途径:1-自行组织采购,2-委托代理采购
|
||||||
*/
|
*/
|
||||||
export function saveImplementType(id: number | string, implementType: string) {
|
export function saveImplementType(id: number | string, implementType: string) {
|
||||||
return request({
|
return request({
|
||||||
@@ -179,7 +179,7 @@ export function getContracts(params?: any) {
|
|||||||
* 实施采购:上传招标文件并关联到申请单(可同时保存采购代表人方式与人员)
|
* 实施采购:上传招标文件并关联到申请单(可同时保存采购代表人方式与人员)
|
||||||
* @param id 采购申请ID
|
* @param id 采购申请ID
|
||||||
* @param fileIds 已上传的招标文件ID列表(fileType=130)
|
* @param fileIds 已上传的招标文件ID列表(fileType=130)
|
||||||
* @param implementType 实施采购方式 1:自行组织采购 2:委托代理采购
|
* @param implementType 实施采购途径 1:自行组织采购 2:委托代理采购
|
||||||
* @param representorTeacherNo 需求部门初审-指定采购代表人(单人)
|
* @param representorTeacherNo 需求部门初审-指定采购代表人(单人)
|
||||||
* @param representors 需求部门初审-部门多人逗号分隔
|
* @param representors 需求部门初审-部门多人逗号分隔
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ const loading = ref(false);
|
|||||||
// 提交表单数据
|
// 提交表单数据
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
id: '',
|
id: '',
|
||||||
|
stuNo: '',
|
||||||
realName: '',
|
realName: '',
|
||||||
oldName: '',
|
oldName: '',
|
||||||
idCard: '',
|
idCard: '',
|
||||||
@@ -58,6 +59,7 @@ const openDialog = (rowData: any) => {
|
|||||||
Object.assign(form, {
|
Object.assign(form, {
|
||||||
id: rowData.id || '',
|
id: rowData.id || '',
|
||||||
realName: rowData.realName || '',
|
realName: rowData.realName || '',
|
||||||
|
stuNo: rowData.stuNo || '',
|
||||||
oldName: rowData.oldName || '',
|
oldName: rowData.oldName || '',
|
||||||
idCard: rowData.idCard || '',
|
idCard: rowData.idCard || '',
|
||||||
});
|
});
|
||||||
|
|||||||
333
src/views/basic/basicstudent/components/StudentDetail.vue
Normal file
@@ -0,0 +1,333 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog title="学生详情" v-model="visible" :close-on-click-modal="false" draggable width="1200px" top="5vh">
|
||||||
|
<div v-loading="loading" class="student-detail-container">
|
||||||
|
<!-- 左侧导航 -->
|
||||||
|
<div class="detail-sidebar">
|
||||||
|
<el-menu :default-active="activeTab" @select="handleMenuSelect">
|
||||||
|
<el-menu-item index="basic">
|
||||||
|
<el-icon><User /></el-icon>
|
||||||
|
<span>基本信息</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="education">
|
||||||
|
<el-icon><School /></el-icon>
|
||||||
|
<span>教育经历</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="family">
|
||||||
|
<el-icon><HomeFilled /></el-icon>
|
||||||
|
<span>家庭信息</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="major">
|
||||||
|
<el-icon><Briefcase /></el-icon>
|
||||||
|
<span>专业信息</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="class">
|
||||||
|
<el-icon><Grid /></el-icon>
|
||||||
|
<span>班级信息</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="adult">
|
||||||
|
<el-icon><Document /></el-icon>
|
||||||
|
<span>成教信息</span>
|
||||||
|
</el-menu-item>
|
||||||
|
</el-menu>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 右侧内容 -->
|
||||||
|
<div class="detail-content">
|
||||||
|
<!-- 基本信息 -->
|
||||||
|
<div v-show="activeTab === 'basic'" class="detail-panel">
|
||||||
|
<el-descriptions :column="3" border>
|
||||||
|
<el-descriptions-item label="姓名">{{ detailData.realName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="曾用名">{{ detailData.oldName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="性别">
|
||||||
|
<el-tag v-if="detailData.gender === '1' || detailData.gender === 1" size="small" type="primary">男</el-tag>
|
||||||
|
<el-tag v-else-if="detailData.gender === '0' || detailData.gender === 0" size="small" type="danger">女</el-tag>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="身份证号">{{ detailData.idCard || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="出生日期">{{ basicInfo?.birthday || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="民族">{{ basicInfo?.national || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="政治面貌">{{ basicInfo?.politicsStatus || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="籍贯">{{ detailData.householdAddress || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="本人电话">{{ detailData.phone || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="电子邮箱">{{ basicInfo?.email || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="QQ号/微信号">{{ basicInfo?.qq || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="退伍军人">
|
||||||
|
<el-tag v-if="basicInfo?.veteran === '1' || basicInfo?.veteran === 1" size="small" type="success">是</el-tag>
|
||||||
|
<el-tag v-else-if="basicInfo?.veteran === '0' || basicInfo?.veteran === 0" size="small" type="info">否</el-tag>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="辨色力">{{ basicInfo?.colourSense || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="裸眼视力(左)">{{ basicInfo?.eyeLeft || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="裸眼视力(右)">{{ basicInfo?.eyeRight || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="身高(cm)">{{ basicInfo?.height || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="体重(kg)">{{ basicInfo?.weight || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="既往病史">{{ basicInfo?.seekText || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="本人特长" :span="3">{{ basicInfo?.advantage || '-' }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 教育经历 -->
|
||||||
|
<div v-show="activeTab === 'education'" class="detail-panel">
|
||||||
|
<el-descriptions :column="3" border>
|
||||||
|
<el-descriptions-item label="入学前文化程度">{{ educationInfo?.education || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="中考分数">{{ educationInfo?.examScore || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="中考准考证号">{{ educationInfo?.examNo || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="本校借读学年">{{ educationInfo?.temporaryyeYear || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="入学前毕业学校">{{ educationInfo?.schoolName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="毕业学校省市">{{ educationInfo?.schoolProvince || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="曾任职务" :span="3">{{ educationInfo?.position || '-' }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 家庭信息 -->
|
||||||
|
<div v-show="activeTab === 'family'" class="detail-panel">
|
||||||
|
<el-descriptions :column="3" border class="mb20">
|
||||||
|
<el-descriptions-item label="户口详细地址" :span="3">{{ homeInfo?.detailedHouseholdAddress || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="户口性质">{{ homeInfo?.householdProperties || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="是否租住">
|
||||||
|
<el-tag v-if="homeInfo?.isTemp === '1' || homeInfo?.isTemp === 1" size="small" type="success">是</el-tag>
|
||||||
|
<el-tag v-else-if="homeInfo?.isTemp === '0' || homeInfo?.isTemp === 0" size="small" type="info">否</el-tag>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="居住详细地址">{{ homeInfo?.liveAddress || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="家庭主要收入来源">{{ homeInfo?.incomeSource || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="家庭年收入(万)">{{ homeInfo?.incomeMoney || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="家庭人均收入(万)">{{ homeInfo?.incomePerMoney || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="是否低保">
|
||||||
|
<el-tag v-if="homeInfo?.homeDifficulty === '1' || homeInfo?.homeDifficulty === 1" size="small" type="warning">是</el-tag>
|
||||||
|
<el-tag v-else-if="homeInfo?.homeDifficulty === '0' || homeInfo?.homeDifficulty === 0" size="small" type="info">否</el-tag>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="共同居住人">{{ homeInfo?.livewith || '-' }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
|
||||||
|
<el-divider content-position="left">父母信息</el-divider>
|
||||||
|
<el-descriptions :column="3" border>
|
||||||
|
<el-descriptions-item label="父亲姓名">{{ homeInfo?.fatherName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="父亲手机号">{{ homeInfo?.fatherPhone || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="父亲身份证号">{{ homeInfo?.fatcherIdCard || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="父亲工作单位" :span="3">{{ homeInfo?.fatherWorkAddress || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="母亲姓名">{{ homeInfo?.matherName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="母亲手机号">{{ homeInfo?.matherPhone || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="母亲身份证号">{{ homeInfo?.matherIdCard || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="母亲工作单位" :span="3">{{ homeInfo?.matherWorkAddress || '-' }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
|
||||||
|
<el-divider content-position="left">家庭成员列表</el-divider>
|
||||||
|
<el-table :data="homeDetailList" border style="width: 100%" max-height="300">
|
||||||
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
|
<el-table-column prop="appellation" label="关系" width="100" />
|
||||||
|
<el-table-column prop="realName" label="姓名" width="100" />
|
||||||
|
<el-table-column prop="tel" label="手机号" width="130" />
|
||||||
|
<el-table-column prop="idCard" label="身份证号" width="180" />
|
||||||
|
<el-table-column prop="workAddress" label="工作单位" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="politicsStatus" label="政治面貌" width="100" />
|
||||||
|
<el-table-column prop="health" label="身体状况" width="80" />
|
||||||
|
</el-table>
|
||||||
|
<div v-if="homeDetailList.length === 0" class="empty-tip">暂无家庭成员信息</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 专业信息 -->
|
||||||
|
<div v-show="activeTab === 'major'" class="detail-panel">
|
||||||
|
<el-descriptions :column="3" border>
|
||||||
|
<el-descriptions-item label="入学日期">{{ majorInfo?.enterDate || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="学院">{{ detailData.deptName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="专业名称">{{ detailData.majorName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="学号">{{ detailData.stuNo || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="学籍号">{{ majorInfo?.schoolRollNumber || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="学籍">{{ majorInfo?.schoolRoll || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="状态">{{ majorInfo?.studentStatus || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="培养层次">{{ majorInfo?.majorLevel || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="学制">{{ majorInfo?.majorYears || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="学习形式">{{ majorInfo?.studyType || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="联院学号">{{ majorInfo?.unionStuNo || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="中技证号">{{ majorInfo?.middleNumber || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="中技段结束时间">{{ majorInfo?.middleTime || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="高技证号">{{ majorInfo?.highNumber || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="高技段结束时间">{{ majorInfo?.highTime || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="技师证号">{{ majorInfo?.technicianNumber || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="毕业证号">{{ detailData.graduateNumber || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="毕业时间">{{ majorInfo?.graduateDate || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="结业时间">{{ majorInfo?.pauseDate || '-' }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 班级信息 -->
|
||||||
|
<div v-show="activeTab === 'class'" class="detail-panel">
|
||||||
|
<el-descriptions :column="3" border>
|
||||||
|
<el-descriptions-item label="班级名称">{{ detailData.className || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="班号">{{ majorInfo?.classNo || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="教室位置">{{ majorInfo?.classRoomPosition || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="就读方式">{{ majorInfo?.isRoomNo || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="班主任">{{ detailData.teacherRealName || majorInfo?.teacherRealName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="班主任联系电话">{{ majorInfo?.teacherTel || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="宿舍号">{{ detailData.roomNo || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="宿舍联系电话">{{ majorInfo?.dormBuildingPhone || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="中职卡开户行">{{ majorInfo?.bankName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="中职卡号">{{ majorInfo?.bankCard || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="社保卡开户行">{{ majorInfo?.socialBank || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="社保卡号">{{ majorInfo?.socialBankNo || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="停车证号">{{ detailData.parkingNo || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="班级QQ群号">{{ detailData.classQQ || majorInfo?.classQq || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="年级">{{ majorInfo?.currentGrade || '-' }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 成教信息 -->
|
||||||
|
<div v-show="activeTab === 'adult'" class="detail-panel">
|
||||||
|
<el-descriptions :column="3" border>
|
||||||
|
<el-descriptions-item label="成教学院">{{ adultInfo?.schoolName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="成教学历">{{ adultInfo?.adultEducation || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="成教考试号">{{ adultInfo?.adultExamNo || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="成教入籍日期">{{ adultInfo?.adultEnterDate || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="成教学号">{{ adultInfo?.adultNo || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="成教专业">{{ adultInfo?.adultMajorName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="成教计算机成绩">{{ adultInfo?.computerScore || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="成教英语成绩">{{ adultInfo?.englishScore || '-' }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">关 闭</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="StudentDetailDialog">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { User, School, HomeFilled, Briefcase, Grid, Document } from '@element-plus/icons-vue';
|
||||||
|
import { getStudentInfoDetail } from '/@/api/basic/basicstudent';
|
||||||
|
import { useMessage } from '/@/hooks/message';
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const visible = ref(false);
|
||||||
|
const loading = ref(false);
|
||||||
|
const activeTab = ref('basic');
|
||||||
|
|
||||||
|
// 学生数据
|
||||||
|
const detailData = ref<any>({});
|
||||||
|
const basicInfo = ref<any>(null);
|
||||||
|
const educationInfo = ref<any>(null);
|
||||||
|
const homeInfo = ref<any>(null);
|
||||||
|
const homeDetailList = ref<any[]>([]);
|
||||||
|
const majorInfo = ref<any>(null);
|
||||||
|
const adultInfo = ref<any>(null);
|
||||||
|
|
||||||
|
// 菜单选择
|
||||||
|
const handleMenuSelect = (index: string) => {
|
||||||
|
activeTab.value = index;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
const openDialog = async (rowData: any) => {
|
||||||
|
visible.value = true;
|
||||||
|
activeTab.value = 'basic';
|
||||||
|
detailData.value = rowData || {};
|
||||||
|
|
||||||
|
// 重置数据
|
||||||
|
basicInfo.value = null;
|
||||||
|
educationInfo.value = null;
|
||||||
|
homeInfo.value = null;
|
||||||
|
homeDetailList.value = [];
|
||||||
|
majorInfo.value = null;
|
||||||
|
adultInfo.value = null;
|
||||||
|
|
||||||
|
// 加载详情数据
|
||||||
|
if (rowData?.stuNo) {
|
||||||
|
await loadDetailData(rowData.stuNo);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载详情数据
|
||||||
|
const loadDetailData = async (stuNo: string) => {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const res = await getStudentInfoDetail({ stuNo });
|
||||||
|
if (res.data && res.data.records && res.data.records.length > 0) {
|
||||||
|
const data = res.data.records[0];
|
||||||
|
// 主数据
|
||||||
|
detailData.value = data;
|
||||||
|
// 基本信息
|
||||||
|
basicInfo.value = data.basicStudentInfoDetailVO || data.basicStudentInfo || null;
|
||||||
|
// 教育经历
|
||||||
|
educationInfo.value = data.basicStudentEducation || null;
|
||||||
|
// 家庭信息
|
||||||
|
homeInfo.value = data.basicStudentHome || null;
|
||||||
|
homeDetailList.value = data.homeDetailList || [];
|
||||||
|
// 专业/班级信息
|
||||||
|
majorInfo.value = data.basicStudentMajorClassVO || data.basicStudentMajorClass || null;
|
||||||
|
// 成教信息
|
||||||
|
adultInfo.value = data.basicStudentAdultEducation || null;
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error('获取学生详情失败', err);
|
||||||
|
useMessage().error(err.msg || '获取学生详情失败');
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 暴露方法给父组件
|
||||||
|
defineExpose({
|
||||||
|
openDialog,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.student-detail-container {
|
||||||
|
display: flex;
|
||||||
|
min-height: 500px;
|
||||||
|
max-height: 70vh;
|
||||||
|
|
||||||
|
.detail-sidebar {
|
||||||
|
width: 180px;
|
||||||
|
border-right: 1px solid #e4e7ed;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
.el-menu {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu-item {
|
||||||
|
height: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
background-color: #ecf5ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-content {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0 20px;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.detail-panel {
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb20 {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-tip {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-descriptions__label) {
|
||||||
|
width: 140px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-descriptions__content) {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
274
src/views/basic/basicstudent/components/StudentIdCardPrint.vue
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog title="学生证件照打印" v-model="visible" :close-on-click-modal="false" draggable fullscreen>
|
||||||
|
<div class="print-container" ref="printRef">
|
||||||
|
<div class="print-actions" v-if="!isPrinting">
|
||||||
|
<el-button type="primary" icon="Printer" @click="handlePrint">打印</el-button>
|
||||||
|
<el-button @click="visible = false">关闭</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-loading="loading" class="print-content">
|
||||||
|
<div class="print-page" v-for="(page, pageIndex) in printPages" :key="pageIndex">
|
||||||
|
<div class="card-wrapper" v-for="(item, cardIndex) in page" :key="cardIndex" :style="getBackgroundStyle(item)">
|
||||||
|
<!-- 头像区域 -->
|
||||||
|
<div class="photo-area">
|
||||||
|
<img :src="item.photo || defaultAvatar" class="student-photo" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 二维码和学生信息区域 -->
|
||||||
|
<div class="info-area">
|
||||||
|
<div class="qrcode-wrapper">
|
||||||
|
<img :src="item.ava || item.qrCode" class="qrcode-img" />
|
||||||
|
</div>
|
||||||
|
<div class="student-info">
|
||||||
|
<ul>
|
||||||
|
<li>姓名:{{ item.realName || '-' }}</li>
|
||||||
|
<li>班级:{{ item.className || '-' }}</li>
|
||||||
|
<li>系部:{{ item.deptName || '-' }}</li>
|
||||||
|
<li>学号:{{ item.stuNo || '-' }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="StudentIdCardPrint">
|
||||||
|
import { ref, computed } from 'vue';
|
||||||
|
import { preBatchPrint, prePrint } from '/@/api/basic/basicstudent';
|
||||||
|
import { useMessage } from '/@/hooks/message';
|
||||||
|
|
||||||
|
// 默认头像
|
||||||
|
const defaultAvatar = '/img/avatar-default.png';
|
||||||
|
|
||||||
|
// 定义变量
|
||||||
|
const visible = ref(false);
|
||||||
|
const loading = ref(false);
|
||||||
|
const isPrinting = ref(false);
|
||||||
|
const printRef = ref();
|
||||||
|
const studentList = ref<any[]>([]);
|
||||||
|
|
||||||
|
// 计算打印页面(每页4个学生)
|
||||||
|
const printPages = computed(() => {
|
||||||
|
const pages: any[][] = [];
|
||||||
|
const students = studentList.value;
|
||||||
|
const totalPages = Math.ceil(students.length / 4);
|
||||||
|
|
||||||
|
for (let i = 0; i < totalPages; i++) {
|
||||||
|
const pageStudents = students.slice(i * 4, (i + 1) * 4);
|
||||||
|
pages.push(pageStudents);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pages;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取背景样式
|
||||||
|
const getBackgroundStyle = (item: any) => {
|
||||||
|
if (item.roomNo) {
|
||||||
|
return "background-image: url('/img/bg/zss.jpeg');";
|
||||||
|
}
|
||||||
|
return "background-image: url('/img/bg/userphotobg.jpg');";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 打开弹窗 - 批量打印(传入选中的学生完整JSON数据)
|
||||||
|
const openDialog = async (selectedRows: any[]) => {
|
||||||
|
if (!selectedRows || selectedRows.length === 0) {
|
||||||
|
useMessage().warning('请先选择要打印的学生');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
visible.value = true;
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 调用后端接口,传入选中的学生完整数据
|
||||||
|
const res = await preBatchPrint(selectedRows);
|
||||||
|
if (res.data && Array.isArray(res.data)) {
|
||||||
|
studentList.value = res.data;
|
||||||
|
} else {
|
||||||
|
// 如果后端没有返回数据,直接使用前端数据
|
||||||
|
studentList.value = selectedRows;
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
// 如果接口报错,直接使用前端数据
|
||||||
|
studentList.value = selectedRows;
|
||||||
|
console.warn('获取打印数据失败,使用前端数据', err);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 打开弹窗 - 单个学生打印
|
||||||
|
const openSingleDialog = async (row: any) => {
|
||||||
|
if (!row.stuNo) {
|
||||||
|
useMessage().warning('学号不存在');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
visible.value = true;
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await prePrint(row.stuNo);
|
||||||
|
if (res.data) {
|
||||||
|
studentList.value = [res.data];
|
||||||
|
} else {
|
||||||
|
studentList.value = [row];
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
studentList.value = [row];
|
||||||
|
console.warn('获取打印数据失败,使用前端数据', err);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 执行打印
|
||||||
|
const handlePrint = () => {
|
||||||
|
isPrinting.value = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
window.print();
|
||||||
|
isPrinting.value = false;
|
||||||
|
}, 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 暴露方法
|
||||||
|
defineExpose({
|
||||||
|
openDialog,
|
||||||
|
openSingleDialog,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.print-container {
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.print-actions {
|
||||||
|
position: fixed;
|
||||||
|
top: 80px;
|
||||||
|
right: 80px;
|
||||||
|
z-index: 100;
|
||||||
|
background: #fff;
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.print-content {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.print-page {
|
||||||
|
width: 29.7cm;
|
||||||
|
height: 19.2cm;
|
||||||
|
margin: 0 auto 20px;
|
||||||
|
page-break-after: always;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
page-break-after: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-wrapper {
|
||||||
|
width: 7cm;
|
||||||
|
height: 10cm;
|
||||||
|
border: 1px #0508b8 solid;
|
||||||
|
margin-left: 5cm;
|
||||||
|
margin-top: 0.3cm;
|
||||||
|
margin-bottom: 0.3cm;
|
||||||
|
float: left;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% auto;
|
||||||
|
background-position: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-area {
|
||||||
|
width: 2.5cm;
|
||||||
|
margin: 0 auto;
|
||||||
|
height: 5.8cm;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.student-photo {
|
||||||
|
width: 2.5cm;
|
||||||
|
height: 3cm;
|
||||||
|
object-fit: cover;
|
||||||
|
margin-top: 2cm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-area {
|
||||||
|
width: 6.5cm;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qrcode-wrapper {
|
||||||
|
width: 2.5cm;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qrcode-img {
|
||||||
|
width: 2.5cm;
|
||||||
|
height: 2.5cm;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.student-info {
|
||||||
|
width: 4cm;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
|
||||||
|
li {
|
||||||
|
line-height: 23px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.print-actions {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-dialog__header),
|
||||||
|
:deep(.el-dialog__footer) {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-dialog) {
|
||||||
|
margin: 0 !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-dialog__body) {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.print-content {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.print-page {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
-moz-print-color-adjust: exact;
|
||||||
|
-ms-print-color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -62,8 +62,8 @@
|
|||||||
<el-option label="否" value="0" />
|
<el-option label="否" value="0" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="姓名/学号/身份证号" prop="keyword">
|
<el-form-item label="姓名/学号/身份证号" prop="total">
|
||||||
<el-input v-model="searchForm.keyword" placeholder="请输入姓名/学号/身份证号" clearable style="width: 200px" />
|
<el-input v-model="searchForm.total" placeholder="请输入姓名/学号/身份证号" clearable style="width: 200px" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" plain icon="Search" @click="handleSearch">查询</el-button>
|
<el-button type="primary" plain icon="Search" @click="handleSearch">查询</el-button>
|
||||||
@@ -199,7 +199,16 @@
|
|||||||
取消班干部
|
取消班干部
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button v-else icon="User" text type="success" @click="handleSetLeader(scope.row)"> 设为班干部 </el-button>
|
<el-button v-else icon="User" text type="success" @click="handleSetLeader(scope.row)"> 设为班干部 </el-button>
|
||||||
<el-button icon="Lock" text type="danger" @click="handleForbidInout(scope.row)"> 禁止进出 </el-button>
|
<el-button
|
||||||
|
v-if="scope.row.isInout == 1 || scope.row.isInout === '1'"
|
||||||
|
icon="Lock"
|
||||||
|
text
|
||||||
|
type="danger"
|
||||||
|
@click="handleForbidInout(scope.row)"
|
||||||
|
>
|
||||||
|
禁止进出
|
||||||
|
</el-button>
|
||||||
|
<el-button v-else icon="Unlock" text type="success" @click="handleForbidInout(scope.row)"> 允许进出 </el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -217,6 +226,9 @@
|
|||||||
<!-- 简单信息维护对话框 -->
|
<!-- 简单信息维护对话框 -->
|
||||||
<SimpleEditDialog ref="simpleEditDialogRef" @refresh="getDataList(false)" />
|
<SimpleEditDialog ref="simpleEditDialogRef" @refresh="getDataList(false)" />
|
||||||
|
|
||||||
|
<!-- 学生证件照打印 -->
|
||||||
|
<PrintDialog ref="printDialogRef" />
|
||||||
|
|
||||||
<!-- 段段清证书导入对话框 -->
|
<!-- 段段清证书导入对话框 -->
|
||||||
<el-dialog title="段段清证书导入" v-model="importCertificateDialogVisible" :close-on-click-modal="false" draggable width="500px">
|
<el-dialog title="段段清证书导入" v-model="importCertificateDialogVisible" :close-on-click-modal="false" draggable width="500px">
|
||||||
<el-upload
|
<el-upload
|
||||||
@@ -268,6 +280,25 @@
|
|||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 申请顶岗弹窗 -->
|
||||||
|
<el-dialog title="申请顶岗" v-model="applyInternshipDialogVisible" :close-on-click-modal="false" draggable width="400px">
|
||||||
|
<el-form :model="applyInternshipForm" label-width="80px">
|
||||||
|
<el-form-item label="顶岗年份" required>
|
||||||
|
<el-select v-model="applyInternshipForm.year" placeholder="请选择顶岗年份" style="width: 100%">
|
||||||
|
<el-option v-for="item in workYearList" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="applyInternshipDialogVisible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="handleApplyInternshipConfirm" :loading="applyInternshipLoading" :disabled="!applyInternshipForm.year">
|
||||||
|
确 定
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -291,6 +322,7 @@ import {
|
|||||||
Tickets,
|
Tickets,
|
||||||
Medal,
|
Medal,
|
||||||
Lock,
|
Lock,
|
||||||
|
Unlock,
|
||||||
DataAnalysis,
|
DataAnalysis,
|
||||||
Setting,
|
Setting,
|
||||||
Menu,
|
Menu,
|
||||||
@@ -306,7 +338,7 @@ import {
|
|||||||
preBatchPrint,
|
preBatchPrint,
|
||||||
importCertificate,
|
importCertificate,
|
||||||
exportStuInfoCard,
|
exportStuInfoCard,
|
||||||
exportCertificate,
|
makeExportSkillLevelTask,
|
||||||
resetPassWord,
|
resetPassWord,
|
||||||
editIsleader,
|
editIsleader,
|
||||||
updateInout,
|
updateInout,
|
||||||
@@ -324,14 +356,16 @@ import { makeExportClassRoomHygieneMonthlyTask } from '/@/api/stuwork/file';
|
|||||||
|
|
||||||
// 引入组件
|
// 引入组件
|
||||||
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
|
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
|
||||||
const DetailDialog = defineAsyncComponent(() => import('./detail.vue'));
|
const DetailDialog = defineAsyncComponent(() => import('./components/StudentDetail.vue'));
|
||||||
const SimpleEditDialog = defineAsyncComponent(() => import('./components/SimpleEdit.vue'));
|
const SimpleEditDialog = defineAsyncComponent(() => import('./components/SimpleEdit.vue'));
|
||||||
|
const PrintDialog = defineAsyncComponent(() => import('./components/StudentIdCardPrint.vue'));
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const formDialogRef = ref();
|
const formDialogRef = ref();
|
||||||
const detailDialogRef = ref();
|
const detailDialogRef = ref();
|
||||||
const simpleEditDialogRef = ref();
|
const simpleEditDialogRef = ref();
|
||||||
|
const printDialogRef = ref();
|
||||||
const searchFormRef = ref();
|
const searchFormRef = ref();
|
||||||
const uploadRef = ref();
|
const uploadRef = ref();
|
||||||
const columnControlRef = ref();
|
const columnControlRef = ref();
|
||||||
@@ -351,6 +385,13 @@ const exportFieldLoading = ref(false);
|
|||||||
const selectedExportFields = ref<string[]>([]);
|
const selectedExportFields = ref<string[]>([]);
|
||||||
const exportFieldCheckAll = ref(false);
|
const exportFieldCheckAll = ref(false);
|
||||||
const exportFieldIndeterminate = ref(false);
|
const exportFieldIndeterminate = ref(false);
|
||||||
|
// 申请顶岗相关
|
||||||
|
const applyInternshipDialogVisible = ref(false);
|
||||||
|
const applyInternshipLoading = ref(false);
|
||||||
|
const workYearList = ref<any[]>([]);
|
||||||
|
const applyInternshipForm = reactive({
|
||||||
|
year: '',
|
||||||
|
});
|
||||||
|
|
||||||
// 表格列配置
|
// 表格列配置
|
||||||
const tableColumns = [
|
const tableColumns = [
|
||||||
@@ -504,7 +545,7 @@ const searchForm = reactive({
|
|||||||
parkingCard: '',
|
parkingCard: '',
|
||||||
completion: '',
|
completion: '',
|
||||||
isUnionClass: '',
|
isUnionClass: '',
|
||||||
keyword: '',
|
total: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
// 配置 useTable
|
// 配置 useTable
|
||||||
@@ -546,7 +587,7 @@ const handleReset = () => {
|
|||||||
parkingCard: '',
|
parkingCard: '',
|
||||||
completion: '',
|
completion: '',
|
||||||
isUnionClass: '',
|
isUnionClass: '',
|
||||||
keyword: '',
|
total: '',
|
||||||
});
|
});
|
||||||
getDataList();
|
getDataList();
|
||||||
};
|
};
|
||||||
@@ -622,17 +663,85 @@ const handleExportFieldConfirm = async () => {
|
|||||||
|
|
||||||
// 申请顶岗
|
// 申请顶岗
|
||||||
const handleApplyInternship = async () => {
|
const handleApplyInternship = async () => {
|
||||||
useMessage().warning('功能开发中');
|
if (selectedRows.value.length === 0) {
|
||||||
|
useMessage().warning('请先选择要申请顶岗的学生');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取顶岗年份字典
|
||||||
|
try {
|
||||||
|
const yearRes = await getDicts('work_year');
|
||||||
|
if (yearRes.data && Array.isArray(yearRes.data)) {
|
||||||
|
workYearList.value = yearRes.data.map((item: any) => ({
|
||||||
|
label: item.label || item.dictLabel || item.name,
|
||||||
|
value: item.value || item.dictValue || item.code,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
// 重置表单并打开弹窗
|
||||||
|
applyInternshipForm.year = '';
|
||||||
|
applyInternshipDialogVisible.value = true;
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '获取顶岗年份失败');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 确认申请顶岗
|
||||||
|
const handleApplyInternshipConfirm = async () => {
|
||||||
|
if (!applyInternshipForm.year) {
|
||||||
|
useMessage().warning('请选择顶岗年份');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
applyInternshipLoading.value = true;
|
||||||
|
try {
|
||||||
|
// 构建请求数据
|
||||||
|
const stuList = selectedRows.value.map((row) => ({ stuNo: row.stuNo }));
|
||||||
|
await applyInternship({ stuList, year: applyInternshipForm.year });
|
||||||
|
useMessage().success('申请顶岗成功');
|
||||||
|
applyInternshipDialogVisible.value = false;
|
||||||
|
getDataList();
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '申请顶岗失败');
|
||||||
|
} finally {
|
||||||
|
applyInternshipLoading.value = false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 导出头像
|
// 导出头像
|
||||||
const handleExportAvatar = async () => {
|
const handleExportAvatar = async () => {
|
||||||
useMessage().warning('功能开发中');
|
if (!searchForm.classCode) {
|
||||||
|
useMessage().warning('请先选择班级');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await getDownPic({
|
||||||
|
classCode: searchForm.classCode,
|
||||||
|
stuStatus: searchForm.stuStatus || '1',
|
||||||
|
});
|
||||||
|
// 处理blob下载
|
||||||
|
const blob = new Blob([res], { type: 'application/zip' });
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.download = `学生头像_${searchForm.classCode}.zip`;
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
useMessage().success('导出成功');
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '导出失败');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 批量打印
|
// 批量打印
|
||||||
const handleBatchPrint = async () => {
|
const handleBatchPrint = () => {
|
||||||
useMessage().warning('功能开发中');
|
if (selectedRows.value.length === 0) {
|
||||||
|
useMessage().warning('请先选择要打印的学生');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printDialogRef.value?.openDialog(selectedRows.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 段段清证书导入
|
// 段段清证书导入
|
||||||
@@ -682,47 +791,124 @@ const handleUploadError = (err: any) => {
|
|||||||
|
|
||||||
// 学籍卡导出
|
// 学籍卡导出
|
||||||
const handleExportStudentCard = async () => {
|
const handleExportStudentCard = async () => {
|
||||||
useMessage().warning('功能开发中');
|
if (selectedRows.value.length === 0) {
|
||||||
|
useMessage().warning('请先选择要导出学籍卡的学生');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const stuNoList = selectedRows.value.map((row) => row.stuNo);
|
||||||
|
const res = await exportStuInfoCard({ stuNoList });
|
||||||
|
// 处理blob下载
|
||||||
|
const blob = new Blob([res], { type: 'application/zip' });
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.download = '学籍卡.zip';
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
useMessage().success('学籍卡导出成功');
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '学籍卡导出失败');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 证书导出
|
// 证书导出
|
||||||
const handleExportCertificate = async () => {
|
const handleExportCertificate = async () => {
|
||||||
useMessage().warning('功能开发中');
|
try {
|
||||||
|
await makeExportSkillLevelTask({
|
||||||
|
deptCode: searchForm.deptCode,
|
||||||
|
classCode: searchForm.classCode,
|
||||||
|
});
|
||||||
|
useMessage().success('导出任务已创建,请在文件管理中下载');
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '创建导出任务失败');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 简单信息维护
|
// 简单信息维护
|
||||||
const handleSimpleEdit = (row: any) => {
|
const handleSimpleEdit = (row: any) => {
|
||||||
useMessage().warning('功能开发中');
|
simpleEditDialogRef.value?.openDialog(row);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 查看详情
|
// 查看详情
|
||||||
const handleViewDetail = (row: any) => {
|
const handleViewDetail = (row: any) => {
|
||||||
useMessage().warning('功能开发中');
|
detailDialogRef.value?.openDialog(row);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 打印证件照
|
// 打印证件照
|
||||||
const handlePrintPhoto = async (row: any) => {
|
const handlePrintPhoto = (row: any) => {
|
||||||
useMessage().warning('功能开发中');
|
printDialogRef.value?.openSingleDialog(row);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 重置密码
|
// 重置密码
|
||||||
const handleResetPassword = async (row: any) => {
|
const handleResetPassword = async (row: any) => {
|
||||||
useMessage().warning('功能开发中');
|
try {
|
||||||
|
await useMessageBox().confirm(`确定要重置学生【${row.realName}】的密码吗?重置后密码将变为默认密码。`);
|
||||||
|
await resetPassWord(row);
|
||||||
|
useMessage().success('密码重置成功');
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err !== 'cancel') {
|
||||||
|
useMessage().error(err.msg || '密码重置失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 设为班干部
|
// 设为班干部
|
||||||
const handleSetLeader = async (row: any) => {
|
const handleSetLeader = async (row: any) => {
|
||||||
useMessage().warning('功能开发中');
|
try {
|
||||||
|
await useMessageBox().confirm(`确定要将学生【${row.realName}】设为班干部吗?`);
|
||||||
|
await editIsleader({
|
||||||
|
id: row.id,
|
||||||
|
stuNo: row.stuNo,
|
||||||
|
isClassLeader: 1
|
||||||
|
});
|
||||||
|
useMessage().success('设置成功');
|
||||||
|
getDataList();
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err !== 'cancel') {
|
||||||
|
useMessage().error(err.msg || '设置失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 取消班干部
|
// 取消班干部
|
||||||
const handleCancelLeader = async (row: any) => {
|
const handleCancelLeader = async (row: any) => {
|
||||||
useMessage().warning('功能开发中');
|
try {
|
||||||
|
await useMessageBox().confirm(`确定要取消学生【${row.realName}】的班干部身份吗?`);
|
||||||
|
await editIsleader({
|
||||||
|
id: row.id,
|
||||||
|
stuNo: row.stuNo,
|
||||||
|
isClassLeader: 0
|
||||||
|
});
|
||||||
|
useMessage().success('取消成功');
|
||||||
|
getDataList();
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err !== 'cancel') {
|
||||||
|
useMessage().error(err.msg || '取消失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 禁止进出
|
// 禁止进出/允许进出
|
||||||
const handleForbidInout = async (row: any) => {
|
const handleForbidInout = async (row: any) => {
|
||||||
useMessage().warning('功能开发中');
|
const isForbid = row.isInout === 1 || row.isInout === '1';
|
||||||
|
const action = isForbid ? '禁止' : '允许';
|
||||||
|
try {
|
||||||
|
await useMessageBox().confirm(`确定要${action}学生【${row.realName}】进出吗?`);
|
||||||
|
await updateInout({
|
||||||
|
stuNo: row.stuNo,
|
||||||
|
isInout: isForbid ? 0 : 1
|
||||||
|
});
|
||||||
|
useMessage().success(`${action}进出设置成功`);
|
||||||
|
getDataList();
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err !== 'cancel') {
|
||||||
|
useMessage().error(err.msg || '设置失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取学院列表
|
// 获取学院列表
|
||||||
|
|||||||
@@ -26,18 +26,11 @@
|
|||||||
<el-divider content-position="left">
|
<el-divider content-position="left">
|
||||||
<span class="section-title">基础信息</span>
|
<span class="section-title">基础信息</span>
|
||||||
</el-divider>
|
</el-divider>
|
||||||
<el-text v-if="!isEditMode && !isViewMode" type="info" size="small" class="mb12" style="display: block">
|
<el-text v-if="!isEditMode && !isViewMode" type="info" size="small" class="mb12" style="display: block"> 暂存时,基础信息必填 </el-text>
|
||||||
暂存时,基础信息必填
|
|
||||||
</el-text>
|
|
||||||
<el-row :gutter="16">
|
<el-row :gutter="16">
|
||||||
<el-col :span="8" class="mb12">
|
<el-col :span="8" class="mb12">
|
||||||
<el-form-item label="采购项目名称" prop="projectName">
|
<el-form-item label="采购项目名称" prop="projectName">
|
||||||
<el-input
|
<el-input v-model="dataForm.projectName" placeholder="请输入采购项目名称" clearable :disabled="flowFieldDisabled('projectName')" />
|
||||||
v-model="dataForm.projectName"
|
|
||||||
placeholder="请输入采购项目名称"
|
|
||||||
clearable
|
|
||||||
:disabled="flowFieldDisabled('projectName')"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8" class="mb12">
|
<el-col :span="8" class="mb12">
|
||||||
@@ -130,6 +123,10 @@
|
|||||||
:disabled="flowFieldDisabled('categoryCode')"
|
:disabled="flowFieldDisabled('categoryCode')"
|
||||||
@change="handleCategoryChange"
|
@change="handleCategoryChange"
|
||||||
/>
|
/>
|
||||||
|
<!-- 显示品目编码层级关系 -->
|
||||||
|
<el-text v-if="categoryCodeHierarchy" type="info" size="small" style="margin-top: 4px; display: block">
|
||||||
|
品目编码层级:{{ categoryCodeHierarchy }}
|
||||||
|
</el-text>
|
||||||
<el-text v-if="isSpecialServiceCategory && dataForm.categoryCode" type="warning" size="small" style="margin-top: 4px">
|
<el-text v-if="isSpecialServiceCategory && dataForm.categoryCode" type="warning" size="small" style="margin-top: 4px">
|
||||||
当前选择品目为服务商城品目
|
当前选择品目为服务商城品目
|
||||||
</el-text>
|
</el-text>
|
||||||
@@ -199,7 +196,13 @@
|
|||||||
:disabled="isPurchaseTypeDisabled"
|
:disabled="isPurchaseTypeDisabled"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
>
|
>
|
||||||
<el-option v-for="item in purchaseTypeDeptOptions" :key="item.value" :label="item.label" :value="item.value" :disabled="item.disabled" />
|
<el-option
|
||||||
|
v-for="item in purchaseTypeDeptOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
:disabled="item.disabled"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -395,12 +398,17 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="16">
|
<el-row :gutter="16">
|
||||||
<el-col :span="8" class="mb12">
|
<el-col :span="8" class="mb12">
|
||||||
<el-form-item label="组织采购形式" prop="purchaseSchool" :required="isPurchaseSchoolRequired">
|
<el-form-item label="实施采购途径" prop="implementType" :required="isImplementTypeRequired">
|
||||||
<el-radio-group v-model="dataForm.purchaseSchool" :disabled="schoolUnifiedPurchaseFormDisabled">
|
<el-select
|
||||||
<el-radio v-for="item in purchaseModeSchoolList" :key="item.value" :label="item.value">
|
v-model="dataForm.implementType"
|
||||||
{{ item.label }}
|
placeholder="请选择实施采购途径"
|
||||||
</el-radio>
|
clearable
|
||||||
</el-radio-group>
|
:disabled="schoolUnifiedPurchaseFormDisabled"
|
||||||
|
@change="handleImplementTypeChange"
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
|
<el-option v-for="item in implementTypeList" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8" class="mb12">
|
<el-col :span="8" class="mb12">
|
||||||
@@ -810,15 +818,9 @@
|
|||||||
<el-divider content-position="left">实施采购信息</el-divider>
|
<el-divider content-position="left">实施采购信息</el-divider>
|
||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
<el-col :span="8" class="mb12" v-if="dataForm.implementType">
|
<el-col :span="8" class="mb12" v-if="dataForm.implementType">
|
||||||
<div class="view-label">实施采购方式</div>
|
<div class="view-label">实施采购途径</div>
|
||||||
<div class="view-value">
|
<div class="view-value">
|
||||||
{{
|
|
||||||
dataForm.implementType === '1'
|
|
||||||
? '自行组织采购'
|
|
||||||
: dataForm.implementType === '2'
|
|
||||||
? '委托代理采购'
|
|
||||||
: dataForm.implementType || '—'
|
|
||||||
}}
|
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8" class="mb12" v-if="dataForm.fileFlowInstId">
|
<el-col :span="8" class="mb12" v-if="dataForm.fileFlowInstId">
|
||||||
@@ -978,7 +980,6 @@ const dataForm = reactive({
|
|||||||
isSpecial: '',
|
isSpecial: '',
|
||||||
hasAssets: '0',
|
hasAssets: '0',
|
||||||
purchaseMode: '',
|
purchaseMode: '',
|
||||||
purchaseSchool: '',
|
|
||||||
purchaseType: '',
|
purchaseType: '',
|
||||||
purchaseTypeUnion: '',
|
purchaseTypeUnion: '',
|
||||||
purchaseChannel: '',
|
purchaseChannel: '',
|
||||||
@@ -1049,7 +1050,13 @@ const isSpecialList = ref<any[]>([]);
|
|||||||
const purchaseTypeDeptList = ref<any[]>([]);
|
const purchaseTypeDeptList = ref<any[]>([]);
|
||||||
/** 部门采购方式字典(委托采购中心采购时使用) */
|
/** 部门采购方式字典(委托采购中心采购时使用) */
|
||||||
const purchaseTypeDeptDelegationList = ref<any[]>([]);
|
const purchaseTypeDeptDelegationList = ref<any[]>([]);
|
||||||
const purchaseModeSchoolList = ref<any[]>([]);
|
/** 实施采购途径选项:1:自行组织采购 2:委托代理采购 5:框架协议 8:网上商城 */
|
||||||
|
const implementTypeList = ref<any[]>([
|
||||||
|
{ value: '1', label: '自行组织采购' },
|
||||||
|
{ value: '2', label: '委托代理采购' },
|
||||||
|
{ value: '140', label: '框架协议' },
|
||||||
|
{ value: '170', label: '网上商城' },
|
||||||
|
]);
|
||||||
const purchaseTypeUnionList = ref<any[]>([]);
|
const purchaseTypeUnionList = ref<any[]>([]);
|
||||||
const businessDeptList = ref<any[]>([]);
|
const businessDeptList = ref<any[]>([]);
|
||||||
const schoolLeaderList = ref<any[]>([]);
|
const schoolLeaderList = ref<any[]>([]);
|
||||||
@@ -1215,8 +1222,8 @@ const isPurchaseTypeUnionRequired = computed(() => {
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 学校统一采购 - 组织采购形式是否必填
|
// 学校统一采购 - 实施采购途径是否必填
|
||||||
const isPurchaseSchoolRequired = computed(() => {
|
const isImplementTypeRequired = computed(() => {
|
||||||
// 审核阶段:采购中心必填
|
// 审核阶段:采购中心必填
|
||||||
if (isFlowEmbed.value && isPurchaseCenter.value) {
|
if (isFlowEmbed.value && isPurchaseCenter.value) {
|
||||||
return true;
|
return true;
|
||||||
@@ -1361,6 +1368,14 @@ const isSpecialServiceCategory = computed(() => {
|
|||||||
return Number(category.isMallService) === 1 || Number(category.isProjectService) === 1;
|
return Number(category.isMallService) === 1 || Number(category.isProjectService) === 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 计算品目编码层级路径显示(如:A/A01/A01000000)
|
||||||
|
const categoryCodeHierarchy = computed(() => {
|
||||||
|
if (!categoryCodePath.value || categoryCodePath.value.length === 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return categoryCodePath.value.join('/');
|
||||||
|
});
|
||||||
|
|
||||||
// 部门自行采购 & 采购途径=自行采购 & 特殊服务类目 → 采购方式固定网上商城
|
// 部门自行采购 & 采购途径=自行采购 & 特殊服务类目 → 采购方式固定网上商城
|
||||||
const isDeptSelfMallLocked = computed(() => {
|
const isDeptSelfMallLocked = computed(() => {
|
||||||
return isDeptPurchase.value && !isEntrustCenterChannel.value && isSpecialServiceCategory.value;
|
return isDeptPurchase.value && !isEntrustCenterChannel.value && isSpecialServiceCategory.value;
|
||||||
@@ -1386,6 +1401,26 @@ const calcEntrustCenterType = (): 'service_online' | 'other' | '' => {
|
|||||||
return 'other';
|
return 'other';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 实施采购途径变化时,根据选择自动设置采购方式
|
||||||
|
// 140:框架协议 → 采购方式自动选择"框架协议"
|
||||||
|
// 170:网上商城 → 采购方式自动选择"网上商城"
|
||||||
|
// 1:自行组织采购、2:委托代理采购 → 清空采购方式,由用户手动选择
|
||||||
|
const handleImplementTypeChange = (value: string) => {
|
||||||
|
if (!value) {
|
||||||
|
// 清空实施采购途径时,清空采购方式
|
||||||
|
dataForm.purchaseType = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 仅当选择框架协议(140)或网上商城(170)时,自动设置采购方式
|
||||||
|
if (value === '140' || value === '170') {
|
||||||
|
dataForm.purchaseType = value;
|
||||||
|
} else {
|
||||||
|
// 其他选项清空采购方式,由用户手动选择
|
||||||
|
dataForm.purchaseType = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 监听采购途径变化,清理所有与采购方式相关的材料字段,同时如果已选择品目则重新计算entrustCenterType
|
// 监听采购途径变化,清理所有与采购方式相关的材料字段,同时如果已选择品目则重新计算entrustCenterType
|
||||||
watch(
|
watch(
|
||||||
() => dataForm.purchaseChannel,
|
() => dataForm.purchaseChannel,
|
||||||
@@ -1732,13 +1767,13 @@ const dataRules = reactive({
|
|||||||
trigger: 'change',
|
trigger: 'change',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
// 学校统一采购 + 采购中心审核:采购形式必填
|
// 学校统一采购 + 采购中心审核:实施采购途径必填
|
||||||
purchaseSchool: [
|
implementType: [
|
||||||
{
|
{
|
||||||
validator: (_rule: any, value: string, callback: (e?: Error) => void) => {
|
validator: (_rule: any, value: string, callback: (e?: Error) => void) => {
|
||||||
if (!isDeptPurchase.value && isFlowEmbed.value && isPurchaseCenter.value) {
|
if (!isDeptPurchase.value && isFlowEmbed.value && isPurchaseCenter.value) {
|
||||||
if (!value || String(value).trim() === '') {
|
if (!value || String(value).trim() === '') {
|
||||||
callback(new Error('请选择组织采购形式'));
|
callback(new Error('请选择实施采购途径'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1865,7 +1900,6 @@ async function loadDetail(applyId: string | number) {
|
|||||||
isCentralized: detail.isCentralized != null ? String(detail.isCentralized) : '',
|
isCentralized: detail.isCentralized != null ? String(detail.isCentralized) : '',
|
||||||
isSpecial: detail.isSpecial != null ? String(detail.isSpecial) : '',
|
isSpecial: detail.isSpecial != null ? String(detail.isSpecial) : '',
|
||||||
purchaseMode: detail.purchaseMode != null ? String(detail.purchaseMode) : '',
|
purchaseMode: detail.purchaseMode != null ? String(detail.purchaseMode) : '',
|
||||||
purchaseSchool: detail.purchaseSchool != null ? String(detail.purchaseSchool) : '',
|
|
||||||
purchaseType:
|
purchaseType:
|
||||||
detail.purchaseType === DEPT_PURCHASE_TYPE.ENTRUST_CENTER
|
detail.purchaseType === DEPT_PURCHASE_TYPE.ENTRUST_CENTER
|
||||||
? ''
|
? ''
|
||||||
@@ -2220,23 +2254,6 @@ const purchaseTypeDeptOptions = computed(() => {
|
|||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
// 获取学校采购形式字典
|
|
||||||
const getPurchaseModeSchoolDict = async () => {
|
|
||||||
try {
|
|
||||||
const res = await getDicts('PURCHASE_MODE_SCHOOL');
|
|
||||||
purchaseModeSchoolList.value =
|
|
||||||
res.data && Array.isArray(res.data)
|
|
||||||
? res.data.map((item: any) => ({
|
|
||||||
id: item.id,
|
|
||||||
label: item.label || item.dictLabel || item.name,
|
|
||||||
value: item.value || item.dictValue || item.code,
|
|
||||||
}))
|
|
||||||
: [];
|
|
||||||
} catch (err) {
|
|
||||||
purchaseModeSchoolList.value = [];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取学校统一采购方式字典
|
// 获取学校统一采购方式字典
|
||||||
const getPurchaseTypeUnionDict = async () => {
|
const getPurchaseTypeUnionDict = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -2808,7 +2825,6 @@ onMounted(async () => {
|
|||||||
getIsSpecialDict(),
|
getIsSpecialDict(),
|
||||||
getPurchaseTypeDeptDict(),
|
getPurchaseTypeDeptDict(),
|
||||||
getPurchaseTypeDeptDelegationDict(),
|
getPurchaseTypeDeptDelegationDict(),
|
||||||
getPurchaseModeSchoolDict(),
|
|
||||||
getPurchaseTypeUnionDict(),
|
getPurchaseTypeUnionDict(),
|
||||||
getBusinessDeptListData(),
|
getBusinessDeptListData(),
|
||||||
getSchoolLeaderListData(),
|
getSchoolLeaderListData(),
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="implement-page">
|
<div class="implement-page">
|
||||||
<div class="implement-form">
|
<div class="implement-form">
|
||||||
<!-- 步骤一:选择实施采购方式 -->
|
<!-- 步骤一:选择实施采购途径 -->
|
||||||
<div class="step-section">
|
<div class="step-section">
|
||||||
<div class="step-header">
|
<div class="step-header">
|
||||||
<span class="step-number" :class="{ completed: step1Completed && !isEditingStep1 }">1</span>
|
<span class="step-number" :class="{ completed: step1Completed && !isEditingStep1 }">1</span>
|
||||||
<span class="step-title">选择实施采购方式</span>
|
<span class="step-title">选择实施采购途径</span>
|
||||||
<el-tag v-if="step1Completed && !isEditingStep1" type="success" size="small">已完成</el-tag>
|
<el-tag v-if="step1Completed && !isEditingStep1" type="success" size="small">已完成</el-tag>
|
||||||
</div>
|
</div>
|
||||||
<div class="step-content">
|
<div class="step-content">
|
||||||
<el-form-item label="实施采购方式" required>
|
<el-form-item label="实施采购途径" required>
|
||||||
<el-radio-group v-model="implementType" :disabled="step1Completed && !isEditingStep1">
|
<el-radio-group v-model="implementType" :disabled="step1Completed && !isEditingStep1">
|
||||||
<el-radio :label="IMPLEMENT_TYPE.SELF_ORGANIZED">自行组织采购</el-radio>
|
<el-radio :label="IMPLEMENT_TYPE.SELF_ORGANIZED">自行组织采购</el-radio>
|
||||||
<el-radio :label="IMPLEMENT_TYPE.ENTRUST_AGENT">委托代理采购</el-radio>
|
<el-radio :label="IMPLEMENT_TYPE.ENTRUST_AGENT">委托代理采购</el-radio>
|
||||||
@@ -97,7 +97,7 @@ import { Session } from '/@/utils/storage';
|
|||||||
|
|
||||||
// ==================== 常量定义(与后端枚举保持一致) ====================
|
// ==================== 常量定义(与后端枚举保持一致) ====================
|
||||||
|
|
||||||
/** 实施采购方式(与后端 ImplementTypeEnum 一致) */
|
/** 实施采购途径(与后端 ImplementTypeEnum 一致) */
|
||||||
const IMPLEMENT_TYPE = {
|
const IMPLEMENT_TYPE = {
|
||||||
/** 自行组织采购 */
|
/** 自行组织采购 */
|
||||||
SELF_ORGANIZED: '1',
|
SELF_ORGANIZED: '1',
|
||||||
@@ -328,7 +328,7 @@ const handleRevokeAgent = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 步骤一:保存实施采购方式 */
|
/** 步骤一:保存实施采购途径 */
|
||||||
const handleSaveImplementType = async () => {
|
const handleSaveImplementType = async () => {
|
||||||
const id = applyRow.value?.id ?? applyId.value;
|
const id = applyRow.value?.id ?? applyId.value;
|
||||||
|
|
||||||
@@ -337,7 +337,7 @@ const handleSaveImplementType = async () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!implementType.value) {
|
if (!implementType.value) {
|
||||||
useMessage().warning('请选择实施采购方式');
|
useMessage().warning('请选择实施采购途径');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
saveTypeSubmitting.value = true;
|
saveTypeSubmitting.value = true;
|
||||||
@@ -370,7 +370,7 @@ const cancelEditStep1 = () => {
|
|||||||
isEditingStep1.value = false;
|
isEditingStep1.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 重新保存实施采购方式(修改后确认) */
|
/** 重新保存实施采购途径(修改后确认) */
|
||||||
const handleReSaveImplementType = async () => {
|
const handleReSaveImplementType = async () => {
|
||||||
const id = applyRow.value?.id ?? applyId.value;
|
const id = applyRow.value?.id ?? applyId.value;
|
||||||
if (!id) {
|
if (!id) {
|
||||||
@@ -378,7 +378,7 @@ const handleReSaveImplementType = async () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!implementType.value) {
|
if (!implementType.value) {
|
||||||
useMessage().warning('请选择实施采购方式');
|
useMessage().warning('请选择实施采购途径');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
saveTypeSubmitting.value = true;
|
saveTypeSubmitting.value = true;
|
||||||
@@ -466,7 +466,7 @@ const handleConfirm = async () => {
|
|||||||
// 步骤一未完成时,先保存步骤一
|
// 步骤一未完成时,先保存步骤一
|
||||||
if (!step1Completed.value) {
|
if (!step1Completed.value) {
|
||||||
if (!implementType.value) {
|
if (!implementType.value) {
|
||||||
useMessage().warning('请选择实施采购方式');
|
useMessage().warning('请选择实施采购途径');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
saveTypeSubmitting.value = true;
|
saveTypeSubmitting.value = true;
|
||||||
@@ -475,7 +475,7 @@ const handleConfirm = async () => {
|
|||||||
step1Completed.value = true;
|
step1Completed.value = true;
|
||||||
emit('saved');
|
emit('saved');
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
useMessage().error(e?.msg || '保存实施采购方式失败');
|
useMessage().error(e?.msg || '保存实施采购途径失败');
|
||||||
return;
|
return;
|
||||||
} finally {
|
} finally {
|
||||||
saveTypeSubmitting.value = false;
|
saveTypeSubmitting.value = false;
|
||||||
|
|||||||
@@ -64,9 +64,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<div class="header-actions">
|
<div class="header-actions">
|
||||||
<el-button icon="Plus" type="primary" @click="formDialogRef.openDialog()"> 新增 </el-button>
|
<el-button icon="Plus" type="primary" @click="formDialogRef.openDialog()"> 新增 </el-button>
|
||||||
<el-button icon="Upload" type="success" class="ml10" @click="handleImport"> 导入行为记录 </el-button>
|
<el-button icon="Upload" type="success" class="ml10" @click="handleConductImport"> 导入考核 </el-button>
|
||||||
<el-button icon="Download" type="primary" plain class="ml10" @click="handleDownloadConductTemplate"> 导入考核模板 </el-button>
|
|
||||||
<el-button icon="Upload" type="warning" class="ml10" @click="handleConductImport"> 导入考核 </el-button>
|
|
||||||
<right-toolbar v-model:showSearch="showSearch" class="ml10" @queryTable="getDataList">
|
<right-toolbar v-model:showSearch="showSearch" class="ml10" @queryTable="getDataList">
|
||||||
<TableColumnControl
|
<TableColumnControl
|
||||||
ref="columnControlRef"
|
ref="columnControlRef"
|
||||||
@@ -168,42 +166,14 @@
|
|||||||
<!-- 新增/编辑对话框 -->
|
<!-- 新增/编辑对话框 -->
|
||||||
<form-dialog ref="formDialogRef" @refresh="getDataList" />
|
<form-dialog ref="formDialogRef" @refresh="getDataList" />
|
||||||
|
|
||||||
<!-- 导入对话框 -->
|
|
||||||
<el-dialog title="导入行为记录" v-model="importDialogVisible" :width="500" :close-on-click-modal="false" draggable>
|
|
||||||
<el-upload ref="uploadRef" :auto-upload="false" :on-change="handleFileChange" :limit="1" accept=".xlsx,.xls" drag>
|
|
||||||
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
|
||||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
|
||||||
<template #tip>
|
|
||||||
<div class="el-upload__tip">只能上传 xlsx/xls 文件</div>
|
|
||||||
</template>
|
|
||||||
</el-upload>
|
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button @click="importDialogVisible = false">取消</el-button>
|
|
||||||
<el-button type="primary" @click="handleImportSubmit" :disabled="!importFile || importLoading">确认</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<!-- 导入操行考核弹窗 -->
|
<!-- 导入操行考核弹窗 -->
|
||||||
<el-dialog title="导入操行考核数据" v-model="conductImportDialogVisible" :width="500" :close-on-click-modal="false" draggable>
|
<upload-excel
|
||||||
<div style="margin-bottom: 15px">
|
ref="conductUploadExcelRef"
|
||||||
<el-button icon="Download" type="success" @click="handleDownloadConductTemplate"> 下载模板 </el-button>
|
:title="'导入操行考核'"
|
||||||
</div>
|
:url="'/stuwork/file/importConductAssessment'"
|
||||||
<el-upload :auto-upload="false" :on-change="handleConductFileChange" :limit="1" accept=".xlsx,.xls" drag>
|
:temp-url="'/stuwork/file/exportConductAssessmentTemplate'"
|
||||||
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
@refreshDataList="getDataList"
|
||||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
/>
|
||||||
<template #tip>
|
|
||||||
<div class="el-upload__tip">只能上传 xlsx/xls 文件,请先下载导入模板</div>
|
|
||||||
</template>
|
|
||||||
</el-upload>
|
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button @click="conductImportDialogVisible = false">取消</el-button>
|
|
||||||
<el-button type="primary" @click="handleConductImportSubmit" :disabled="!conductImportFile || conductImportLoading">确认导入</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -211,8 +181,7 @@
|
|||||||
import { reactive, ref, onMounted, computed, nextTick } from 'vue';
|
import { reactive, ref, onMounted, computed, nextTick } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { BasicTableProps, useTable } from '/@/hooks/table';
|
import { BasicTableProps, useTable } from '/@/hooks/table';
|
||||||
import { fetchList, delObj, importExcel } from '/@/api/stuwork/stuconduct';
|
import { fetchList, delObj } from '/@/api/stuwork/stuconduct';
|
||||||
import { exportConductAssessmentTemplate, importConductAssessment, downloadBlobFile } from '/@/api/stuwork/file';
|
|
||||||
import { getDeptList } from '/@/api/basic/basicclass';
|
import { getDeptList } from '/@/api/basic/basicclass';
|
||||||
import { queryAllSchoolYear } from '/@/api/basic/basicyear';
|
import { queryAllSchoolYear } from '/@/api/basic/basicyear';
|
||||||
import { getClassListByRole } from '/@/api/basic/basicclass';
|
import { getClassListByRole } from '/@/api/basic/basicclass';
|
||||||
@@ -220,7 +189,6 @@ import { getDicts } from '/@/api/admin/dict';
|
|||||||
import { useMessage, useMessageBox } from '/@/hooks/message';
|
import { useMessage, useMessageBox } from '/@/hooks/message';
|
||||||
import TableColumnControl from '/@/components/TableColumnControl/index.vue';
|
import TableColumnControl from '/@/components/TableColumnControl/index.vue';
|
||||||
import {
|
import {
|
||||||
UploadFilled,
|
|
||||||
List,
|
List,
|
||||||
CreditCard,
|
CreditCard,
|
||||||
Calendar,
|
Calendar,
|
||||||
@@ -242,7 +210,6 @@ import FormDialog from './form.vue';
|
|||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const formDialogRef = ref();
|
const formDialogRef = ref();
|
||||||
const columnControlRef = ref<any>();
|
const columnControlRef = ref<any>();
|
||||||
const uploadRef = ref();
|
|
||||||
const searchFormRef = ref();
|
const searchFormRef = ref();
|
||||||
const showSearch = ref(true);
|
const showSearch = ref(true);
|
||||||
const schoolYearList = ref<any[]>([]);
|
const schoolYearList = ref<any[]>([]);
|
||||||
@@ -250,12 +217,7 @@ const schoolTermList = ref<any[]>([]);
|
|||||||
const deptList = ref<any[]>([]);
|
const deptList = ref<any[]>([]);
|
||||||
const classList = ref<any[]>([]);
|
const classList = ref<any[]>([]);
|
||||||
const typeList = ref<any[]>([]);
|
const typeList = ref<any[]>([]);
|
||||||
const importDialogVisible = ref(false);
|
const conductUploadExcelRef = ref();
|
||||||
const importFile = ref<File | null>(null);
|
|
||||||
const importLoading = ref(false);
|
|
||||||
const conductImportDialogVisible = ref(false);
|
|
||||||
const conductImportFile = ref<File | null>(null);
|
|
||||||
const conductImportLoading = ref(false);
|
|
||||||
|
|
||||||
// 表格列配置
|
// 表格列配置
|
||||||
const tableColumns = [
|
const tableColumns = [
|
||||||
@@ -357,81 +319,9 @@ const handleViewAttachment = (row: any) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 导入
|
// 导入操行考核
|
||||||
const handleImport = () => {
|
|
||||||
importDialogVisible.value = true;
|
|
||||||
importFile.value = null;
|
|
||||||
uploadRef.value?.clearFiles();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 文件变化
|
|
||||||
const handleFileChange = (file: any) => {
|
|
||||||
importFile.value = file.raw;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 提交导入
|
|
||||||
const handleImportSubmit = async () => {
|
|
||||||
if (!importFile.value) {
|
|
||||||
useMessage().warning('请先选择要上传的文件');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
importLoading.value = true;
|
|
||||||
try {
|
|
||||||
await importExcel(importFile.value);
|
|
||||||
useMessage().success('导入成功');
|
|
||||||
importDialogVisible.value = false;
|
|
||||||
importFile.value = null;
|
|
||||||
uploadRef.value?.clearFiles();
|
|
||||||
getDataList();
|
|
||||||
} catch (err: any) {
|
|
||||||
useMessage().error(err.msg || '导入失败');
|
|
||||||
} finally {
|
|
||||||
importLoading.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 下载操行考核导入模板
|
|
||||||
const handleDownloadConductTemplate = async () => {
|
|
||||||
try {
|
|
||||||
await downloadBlobFile(exportConductAssessmentTemplate(), `操行考核导入模板_${Date.now()}.xlsx`);
|
|
||||||
} catch (err: any) {
|
|
||||||
useMessage().error(err?.msg || '下载模板失败');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 打开操行考核导入弹窗
|
|
||||||
const handleConductImport = () => {
|
const handleConductImport = () => {
|
||||||
conductImportDialogVisible.value = true;
|
conductUploadExcelRef.value?.show();
|
||||||
conductImportFile.value = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 操行考核文件变化
|
|
||||||
const handleConductFileChange = (file: any) => {
|
|
||||||
conductImportFile.value = file.raw;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 提交操行考核导入
|
|
||||||
const handleConductImportSubmit = async () => {
|
|
||||||
if (!conductImportFile.value) {
|
|
||||||
useMessage().warning('请先选择要上传的文件');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
conductImportLoading.value = true;
|
|
||||||
try {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append('file', conductImportFile.value);
|
|
||||||
await importConductAssessment(formData);
|
|
||||||
useMessage().success('导入成功');
|
|
||||||
conductImportDialogVisible.value = false;
|
|
||||||
conductImportFile.value = null;
|
|
||||||
getDataList();
|
|
||||||
} catch (err: any) {
|
|
||||||
useMessage().error(err.msg || '导入失败');
|
|
||||||
} finally {
|
|
||||||
conductImportLoading.value = false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 编辑
|
// 编辑
|
||||||
|
|||||||
@@ -210,37 +210,13 @@
|
|||||||
<form-dialog ref="formDialogRef" @refresh="getDataList" />
|
<form-dialog ref="formDialogRef" @refresh="getDataList" />
|
||||||
|
|
||||||
<!-- 导入对话框 -->
|
<!-- 导入对话框 -->
|
||||||
<el-dialog
|
<upload-excel
|
||||||
title="导入数据"
|
ref="uploadExcelRef"
|
||||||
v-model="importDialogVisible"
|
:title="'导入团员'"
|
||||||
:close-on-click-modal="false"
|
:url="'/stuwork/file/importStuUnionLeague'"
|
||||||
width="500px">
|
:temp-url="'/stuwork/file/exportStuUnionLeagueTemplate'"
|
||||||
<el-upload
|
@refreshDataList="getDataList"
|
||||||
ref="uploadRef"
|
/>
|
||||||
:auto-upload="false"
|
|
||||||
:limit="1"
|
|
||||||
:on-exceed="handleExceed"
|
|
||||||
:on-change="handleFileChange"
|
|
||||||
:file-list="fileList"
|
|
||||||
accept=".xlsx,.xls"
|
|
||||||
drag>
|
|
||||||
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
|
||||||
<div class="el-upload__text">
|
|
||||||
将文件拖到此处,或<em>点击上传</em>
|
|
||||||
</div>
|
|
||||||
<template #tip>
|
|
||||||
<div class="el-upload__tip">
|
|
||||||
只能上传 xlsx/xls 文件
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-upload>
|
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button @click="importDialogVisible = false">取消</el-button>
|
|
||||||
<el-button type="primary" @click="handleImportSubmit" :loading="importLoading">确认</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<!-- 统计对话框 -->
|
<!-- 统计对话框 -->
|
||||||
<el-dialog
|
<el-dialog
|
||||||
@@ -290,16 +266,15 @@ import { reactive, ref, onMounted, computed, nextTick } from 'vue'
|
|||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { BasicTableProps, useTable } from "/@/hooks/table";
|
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||||
import { fetchList, delObj, getStatistics } from "/@/api/stuwork/stuunionleague";
|
import { fetchList, delObj, getStatistics } from "/@/api/stuwork/stuunionleague";
|
||||||
import { exportStuUnionLeagueTemplate, importStuUnionLeague, makeExportStuUnionLeagueTask } from "/@/api/stuwork/file";
|
import { makeExportStuUnionLeagueTask } from "/@/api/stuwork/file";
|
||||||
import { getClassListByRole } from "/@/api/basic/basicclass";
|
import { getClassListByRole } from "/@/api/basic/basicclass";
|
||||||
import { getGradeList } from "/@/api/basic/basicclass";
|
import { getGradeList } from "/@/api/basic/basicclass";
|
||||||
import { useMessage, useMessageBox } from "/@/hooks/message";
|
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||||
import { parseTime } from "/@/utils/formatTime";
|
import { parseTime } from "/@/utils/formatTime";
|
||||||
import TableColumnControl from '/@/components/TableColumnControl/index.vue'
|
import TableColumnControl from '/@/components/TableColumnControl/index.vue'
|
||||||
import { UploadFilled, List, OfficeBuilding, Grid, CreditCard, Avatar, Phone, Calendar, Postcard, Briefcase, Setting, Menu, Search, Document, DataAnalysis } from '@element-plus/icons-vue'
|
import { List, OfficeBuilding, Grid, CreditCard, Avatar, Phone, Calendar, Postcard, Briefcase, Setting, Menu, Search, Document, DataAnalysis } from '@element-plus/icons-vue'
|
||||||
import { useTableColumnControl } from '/@/hooks/tableColumn'
|
import { useTableColumnControl } from '/@/hooks/tableColumn'
|
||||||
|
|
||||||
import type { UploadFile, UploadFiles } from 'element-plus';
|
|
||||||
import FormDialog from './form.vue'
|
import FormDialog from './form.vue'
|
||||||
|
|
||||||
// 定义变量
|
// 定义变量
|
||||||
@@ -307,13 +282,10 @@ const route = useRoute()
|
|||||||
const formDialogRef = ref()
|
const formDialogRef = ref()
|
||||||
const columnControlRef = ref<any>()
|
const columnControlRef = ref<any>()
|
||||||
const searchFormRef = ref()
|
const searchFormRef = ref()
|
||||||
const uploadRef = ref()
|
const uploadExcelRef = ref()
|
||||||
const showSearch = ref(true)
|
const showSearch = ref(true)
|
||||||
const classList = ref<any[]>([])
|
const classList = ref<any[]>([])
|
||||||
const gradeList = ref<any[]>([])
|
const gradeList = ref<any[]>([])
|
||||||
const importDialogVisible = ref(false)
|
|
||||||
const importLoading = ref(false)
|
|
||||||
const fileList = ref<UploadFile[]>([])
|
|
||||||
|
|
||||||
// 统计相关变量
|
// 统计相关变量
|
||||||
const statisticsDialogVisible = ref(false)
|
const statisticsDialogVisible = ref(false)
|
||||||
@@ -420,47 +392,7 @@ const handleDelete = async (row: any) => {
|
|||||||
|
|
||||||
// 导入
|
// 导入
|
||||||
const handleImport = () => {
|
const handleImport = () => {
|
||||||
importDialogVisible.value = true
|
uploadExcelRef.value?.show()
|
||||||
fileList.value = []
|
|
||||||
}
|
|
||||||
|
|
||||||
// 文件变化
|
|
||||||
const handleFileChange = (file: UploadFile, files: UploadFiles) => {
|
|
||||||
fileList.value = [file]
|
|
||||||
}
|
|
||||||
|
|
||||||
// 文件超出限制
|
|
||||||
const handleExceed = () => {
|
|
||||||
useMessage().warning('文件数量超出限制')
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提交导入
|
|
||||||
const handleImportSubmit = async () => {
|
|
||||||
if (fileList.value.length === 0) {
|
|
||||||
useMessage().warning('请先选择要上传的文件')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const file = fileList.value[0].raw
|
|
||||||
if (!file) {
|
|
||||||
useMessage().warning('文件无效')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
importLoading.value = true
|
|
||||||
try {
|
|
||||||
const formData = new FormData()
|
|
||||||
formData.append('file', file as File)
|
|
||||||
await importStuUnionLeague(formData)
|
|
||||||
useMessage().success('导入成功')
|
|
||||||
importDialogVisible.value = false
|
|
||||||
fileList.value = []
|
|
||||||
getDataList()
|
|
||||||
} catch (err: any) {
|
|
||||||
useMessage().error(err.msg || '导入失败')
|
|
||||||
} finally {
|
|
||||||
importLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导出
|
// 导出
|
||||||
|
|||||||