forked from liweijie/education
1 line
25 KiB
JSON
1 line
25 KiB
JSON
{"remainingRequest":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\vue-loader\\lib\\index.js??vue-loader-options!C:\\Users\\Admin\\Desktop\\education\\frontend\\src\\views\\teachOffice\\elective\\index.vue?vue&type=style&index=0&id=2c185304&scoped=true&lang=scss","dependencies":[{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\src\\views\\teachOffice\\elective\\index.vue","mtime":1787567993848},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\css-loader\\dist\\cjs.js","mtime":1787309792478},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\vue-loader\\lib\\loaders\\stylePostLoader.js","mtime":1787309794547},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\postcss-loader\\src\\index.js","mtime":1787309793084},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\sass-loader\\dist\\cjs.js","mtime":1787309791955},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\cache-loader\\dist\\cjs.js","mtime":1787309791955},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\vue-loader\\lib\\index.js","mtime":1787309793790}],"contextDependencies":[],"result":[{"type":"Buffer","data":"base64:CgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKDQovLyA9PT09PT09PT09PT09PT09PT09PSAyLiDmn6Xor6LmnaHku7bljLrln58gPT09PT09PT09PT09PT09PT09PT0NCi5xdWVyeS1jYXJkIHsNCiAgLnF1ZXJ5LWZpZWxkIHsNCiAgICBkaXNwbGF5OiBmbGV4Ow0KICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7DQogICAgbWFyZ2luLWJvdHRvbTogMTRweDsNCiAgICBtaW4taGVpZ2h0OiAzMnB4Ow0KDQogICAgLnEtbGFiZWwgew0KICAgICAgd2lkdGg6IDEyMHB4Ow0KICAgICAgZmxleC1zaHJpbms6IDA7DQogICAgICBmb250LXNpemU6IDEzcHg7DQogICAgICBjb2xvcjogIzMwMzEzMzsNCiAgICAgIHRleHQtYWxpZ246IHJpZ2h0Ow0KICAgICAgbWFyZ2luLXJpZ2h0OiAxMHB4Ow0KICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDsNCiAgICB9DQoNCiAgICAucS1jb250cm9sIHsNCiAgICAgIGZsZXg6IDE7DQogICAgICBtaW4td2lkdGg6IDA7DQogICAgfQ0KICB9DQp9DQoNCi5leHBvcnQtYmFyIHsNCiAgYWxpZ24taXRlbXM6IGNlbnRlcjsNCn0NCg0KLy8gPT09PT09PT09PT09PT09PT09PT0gNC4g5pON5L2c5oyJ6ZKu5Yy65Z+fID09PT09PT09PT09PT09PT09PT09DQouYWN0aW9uLWNhcmQgew0KICAuYWN0aW9uLXJvdyB7DQogICAgZGlzcGxheTogZmxleDsNCiAgICBmbGV4LXdyYXA6IHdyYXA7DQogICAgZ2FwOiAxMnB4Ow0KICAgIG1hcmdpbi1ib3R0b206IDEycHg7DQoNCiAgICAmOmxhc3QtY2hpbGQgew0KICAgICAgbWFyZ2luLWJvdHRvbTogMDsNCiAgICB9DQogIH0NCn0NCg0KLy8gPT09PT09PT09PT09PT09PT09PT0gNS4g5paH5Lu25LiK5Lyg5Yy65Z+fID09PT09PT09PT09PT09PT09PT09DQoudXBsb2FkLWNhcmQgew0KICAudXBsb2FkLXJvdyB7DQogICAgZGlzcGxheTogZmxleDsNCiAgICBhbGlnbi1pdGVtczogY2VudGVyOw0KICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjsNCiAgICBmbGV4LXdyYXA6IHdyYXA7DQogICAgZ2FwOiAxMnB4Ow0KDQogICAgLnVwbG9hZC1sZWZ0IHsNCiAgICAgIGRpc3BsYXk6IGZsZXg7DQogICAgICBhbGlnbi1pdGVtczogY2VudGVyOw0KICAgICAgZ2FwOiAxMnB4Ow0KDQogICAgICAuZmlsZS1uYW1lIHsNCiAgICAgICAgZm9udC1zaXplOiAxMnB4Ow0KICAgICAgICBjb2xvcjogIzk5OTsNCg0KICAgICAgICAmLmhhcy1maWxlIHsNCiAgICAgICAgICBjb2xvcjogIzMwMzEzMzsNCiAgICAgICAgfQ0KICAgICAgfQ0KICAgIH0NCg0KICAgIC51cGxvYWQtcmlnaHQgew0KICAgICAgZGlzcGxheTogZmxleDsNCiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7DQogICAgfQ0KICB9DQp9DQoNCi8vID09PT09PT09PT09PT09PT09PT09IDYuIOaVsOaNruihqOagvOWMuuWfnyA9PT09PT09PT09PT09PT09PT09PQ0KLnRhYmxlLWNhcmQgew0KICAubWFpbi10YWJsZSB7DQogICAgOjp2LWRlZXAgLmNlbGwgew0KICAgICAgZm9udC1zaXplOiAxMnB4Ow0KICAgIH0NCiAgfQ0KDQogIC50cmlwbGUtaGVhZGVyLA0KICAudHJpcGxlLWNlbGwgew0KICAgIGRpc3BsYXk6IGZsZXg7DQogICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsNCiAgICBsaW5lLWhlaWdodDogMS40Ow0KICB9DQoNCiAgLnBhZ2luYXRpb24td3JhcCB7DQogICAgZGlzcGxheTogZmxleDsNCiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGZsZXgtZW5kOw0KICAgIG1hcmdpbi10b3A6IDE2cHg7DQogIH0NCn0NCg=="},{"version":3,"sources":["index.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAscA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA","file":"index.vue","sourceRoot":"src/views/teachOffice/elective","sourcesContent":["<template>\r\n <div class=\"app-container management-page elective-page\">\r\n <!-- ==================== 2. 查询条件区域 ==================== -->\r\n <div class=\"section-card query-card\">\r\n <div class=\"section-heading\">\r\n <div>\r\n <h2 class=\"section-title\">筛选条件</h2>\r\n <p class=\"section-description\">按课程、班次、教员及状态筛选选修课</p>\r\n </div>\r\n <el-button type=\"primary\" icon=\"el-icon-search\" @click=\"handleQuery\">查询</el-button>\r\n </div>\r\n <el-form>\r\n <el-row :gutter=\"32\">\r\n <!-- 左栏 -->\r\n <el-col :xs=\"24\" :md=\"12\">\r\n <div class=\"query-field\">\r\n <span class=\"q-label no-check\">授课教员</span>\r\n <el-input v-model=\"searchForm.js\" placeholder=\"请输入授课教员\" clearable class=\"q-control\" />\r\n </div>\r\n <div class=\"query-field\">\r\n <span class=\"q-label no-check\">可选班次年级</span>\r\n <el-input v-model=\"searchForm.kbcnj\" placeholder=\"请输入可选班次年级\" clearable class=\"q-control\" />\r\n </div>\r\n <div class=\"query-field\">\r\n <span class=\"q-label no-check\">选修课状态</span>\r\n <el-select\r\n v-model=\"searchForm.xxkzt\"\r\n placeholder=\"请选择选修课状态\"\r\n clearable\r\n class=\"q-control\"\r\n >\r\n <el-option v-for=\"item in statusOptions\" :key=\"item\" :label=\"item\" :value=\"item\" />\r\n </el-select>\r\n </div>\r\n </el-col>\r\n\r\n <!-- 右栏 -->\r\n <el-col :xs=\"24\" :md=\"12\">\r\n <div class=\"query-field\">\r\n <span class=\"q-label no-check\">课程科目名称</span>\r\n <el-input v-model=\"searchForm.kckmmc\" placeholder=\"请输入课程科目名称\" clearable class=\"q-control\" />\r\n </div>\r\n <div class=\"query-field\">\r\n <span class=\"q-label no-check\">选修班名称</span>\r\n <el-input v-model=\"searchForm.xxbmc\" placeholder=\"请输入选修班名称\" clearable class=\"q-control\" />\r\n </div>\r\n <div class=\"query-field\">\r\n <span class=\"q-label no-check\">培训层次</span>\r\n <el-select v-model=\"searchForm.pxcc\" placeholder=\"请选择培训层次\" clearable class=\"q-control\">\r\n <el-option v-for=\"item in pxccOptions\" :key=\"item\" :label=\"item\" :value=\"item\" />\r\n </el-select>\r\n </div>\r\n </el-col>\r\n </el-row>\r\n </el-form>\r\n\r\n </div>\r\n\r\n <!-- ==================== 3. 导出按钮区域 ==================== -->\r\n <div class=\"section-card export-card\">\r\n <div class=\"section-heading section-heading--compact\">\r\n <div>\r\n <h2 class=\"section-title\">数据导出</h2>\r\n <p class=\"section-description\">下载选修班及学员名单</p>\r\n </div>\r\n </div>\r\n <div class=\"export-bar\">\r\n <el-button icon=\"el-icon-download\" @click=\"handleDownloadList\">下载选修班列表</el-button>\r\n <el-button icon=\"el-icon-download\" @click=\"handleDownloadWord\">下载选修班学员名单Word</el-button>\r\n <el-button icon=\"el-icon-download\" @click=\"handleDownloadExcel\">下载选修班学员名单Excel</el-button>\r\n </div>\r\n </div>\r\n\r\n <!-- ==================== 4. 操作按钮区域 ==================== -->\r\n <div class=\"section-card action-card\">\r\n <div class=\"section-heading section-heading--compact\">\r\n <div>\r\n <h2 class=\"section-title\">选修课操作</h2>\r\n <p class=\"section-description\">新建选修课,或对已选数据执行批量操作</p>\r\n </div>\r\n </div>\r\n <div class=\"action-row\">\r\n <el-button type=\"primary\" icon=\"el-icon-plus\" @click=\"handleOpenNew\">新建选修课</el-button>\r\n <el-button type=\"primary\" plain icon=\"el-icon-circle-check\" @click=\"handleOpenEarly\">\r\n 所选批量开放报名\r\n </el-button>\r\n <el-button type=\"warning\" plain icon=\"el-icon-remove-outline\" @click=\"handleCancelEarly\">\r\n 所选批量取消开放报名\r\n </el-button>\r\n <el-button type=\"danger\" plain icon=\"el-icon-circle-close\" @click=\"handleStopSignup\">\r\n 批量停止报名\r\n </el-button>\r\n <el-button icon=\"el-icon-refresh\" @click=\"handleReverseRange\">\r\n 所选批量根据学员反向确定班次范围\r\n </el-button>\r\n </div>\r\n <div class=\"action-row\">\r\n <el-button icon=\"el-icon-download\" @click=\"handleDownloadTemplate\">【选修课数据文件模板】下载</el-button>\r\n </div>\r\n </div>\r\n\r\n <!-- ==================== 5. 文件上传区域 ==================== -->\r\n <div class=\"section-card upload-card\">\r\n <div class=\"section-heading section-heading--compact\">\r\n <div>\r\n <h2 class=\"section-title\">数据导入</h2>\r\n <p class=\"section-description\">选择填写完成的模板文件并上传</p>\r\n </div>\r\n </div>\r\n <div class=\"upload-row\">\r\n <div class=\"upload-left\">\r\n <el-button icon=\"el-icon-folder-opened\" @click=\"handleSelectFile\">选择文件</el-button>\r\n <span class=\"file-name\" :class=\"{ 'has-file': selectedFile }\">{{ fileName }}</span>\r\n <input ref=\"fileInputRef\" type=\"file\" style=\"display: none\" @change=\"handleFileChange\" />\r\n </div>\r\n <div class=\"upload-right\">\r\n <el-button type=\"primary\" icon=\"el-icon-upload2\" @click=\"handleUpload\">上传数据</el-button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- ==================== 6. 数据表格区域 ==================== -->\r\n <div class=\"section-card table-card\">\r\n <div class=\"section-heading section-heading--compact table-heading\">\r\n <div>\r\n <h2 class=\"section-title\">选修课列表</h2>\r\n <p class=\"section-description\">共 {{ total }} 条数据</p>\r\n </div>\r\n </div>\r\n <el-table v-loading=\"loading\" :data=\"tableData\" border stripe class=\"main-table\" @selection-change=\"handleSelectionChange\">\r\n <template slot=\"empty\">\r\n <span>无数据!</span>\r\n </template>\r\n <el-table-column type=\"selection\" width=\"40\" align=\"center\" />\r\n <el-table-column type=\"index\" label=\"序号\" width=\"60\" align=\"center\" :index=\"tableIndex\" />\r\n <el-table-column prop=\"kmc\" label=\"课程\" min-width=\"110\" show-overflow-tooltip />\r\n <el-table-column prop=\"jcmc\" label=\"教材\" min-width=\"120\" show-overflow-tooltip />\r\n <el-table-column prop=\"jyxm\" label=\"实施教员\" width=\"90\" align=\"center\" />\r\n <el-table-column prop=\"jsmc\" label=\"教学场地\" width=\"100\" show-overflow-tooltip />\r\n <el-table-column prop=\"kxdlbc\" label=\"显示可选队别班次\" min-width=\"150\" align=\"center\" show-overflow-tooltip />\r\n <el-table-column label=\"计划学时/运行学时/学分\" width=\"130\" align=\"center\">\r\n <template slot=\"header\">\r\n <div class=\"triple-header\">\r\n <span>计划学时</span>\r\n <span>运行学时</span>\r\n <span>学分</span>\r\n </div>\r\n </template>\r\n <template slot-scope=\"{ row }\">\r\n <div class=\"triple-cell\">\r\n <span>{{ row.jhyxxsxf }}</span>\r\n </div>\r\n </template>\r\n </el-table-column>\r\n <el-table-column label=\"开课结课日期\" min-width=\"150\" align=\"center\">\r\n <template slot-scope=\"{ row }\">\r\n {{ row.kkjkrq }}\r\n </template>\r\n </el-table-column>\r\n <el-table-column label=\"报名日期\" min-width=\"140\" align=\"center\">\r\n <template slot-scope=\"{ row }\">\r\n {{ row.bmrq }}\r\n </template>\r\n </el-table-column>\r\n <el-table-column prop=\"jhrs\" label=\"计划人数\" width=\"90\" align=\"center\" />\r\n <el-table-column prop=\"yqsm\" label=\"要求说明\" min-width=\"120\" show-overflow-tooltip />\r\n </el-table>\r\n\r\n <div class=\"pagination-wrap\">\r\n <el-pagination\r\n background\r\n layout=\"total, prev, pager, next, jumper\"\r\n :total=\"total\"\r\n :page-size=\"pageSize\"\r\n :current-page=\"currentPage\"\r\n @current-change=\"handlePageChange\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- 新建选修课弹窗 -->\r\n <el-dialog\r\n :visible=\"dialogVisible\"\r\n title=\"新建选修课\"\r\n width=\"560px\"\r\n @update:visible=\"val => (dialogVisible = val)\"\r\n >\r\n <el-form ref=\"formRef\" :model=\"form\" :rules=\"rules\" label-width=\"110px\">\r\n <el-form-item label=\"课程名称\" prop=\"kcmc\">\r\n <el-input v-model=\"form.kcmc\" placeholder=\"请输入课程名称\" clearable />\r\n </el-form-item>\r\n <el-form-item label=\"实施教员\" prop=\"js\">\r\n <el-input v-model=\"form.js\" placeholder=\"请输入实施教员\" clearable />\r\n </el-form-item>\r\n <el-form-item label=\"教材\">\r\n <el-input v-model=\"form.jc\" placeholder=\"请输入教材\" clearable />\r\n </el-form-item>\r\n <el-form-item label=\"教学场地\">\r\n <el-input v-model=\"form.jxcd\" placeholder=\"请输入教学场地\" clearable />\r\n </el-form-item>\r\n <el-form-item label=\"计划学时\">\r\n <el-input-number v-model=\"form.jhsxs\" :min=\"0\" :precision=\"0\" class=\"w-full\" />\r\n </el-form-item>\r\n <el-form-item label=\"运行学时\">\r\n <el-input-number v-model=\"form.yxsxs\" :min=\"0\" :precision=\"0\" class=\"w-full\" />\r\n </el-form-item>\r\n <el-form-item label=\"学分\">\r\n <el-input-number v-model=\"form.xf\" :min=\"0\" :precision=\"1\" class=\"w-full\" />\r\n </el-form-item>\r\n <el-form-item label=\"计划人数\">\r\n <el-input-number v-model=\"form.jh\" :min=\"0\" :precision=\"0\" class=\"w-full\" />\r\n </el-form-item>\r\n </el-form>\r\n <div slot=\"footer\">\r\n <el-button @click=\"dialogVisible = false\">取消</el-button>\r\n <el-button type=\"primary\" @click=\"handleNewConfirm\">确定</el-button>\r\n </div>\r\n </el-dialog>\r\n </div>\r\n</template>\r\n\r\n<script>\r\nimport {\r\n listElective,\r\n batchOpenElective,\r\n batchCancelOpenElective,\r\n batchStopElective,\r\n exportElectiveList,\r\n exportElectiveStudentsExcel,\r\n exportElectiveStudentsWord\r\n} from '@/api/teachOffice/elective'\r\nimport { saveAs } from 'file-saver'\r\n\r\nexport default {\r\n name: 'Elective',\r\n data() {\r\n return {\r\n // ==================== 下拉选项 ====================\r\n statusOptions: ['拟制', '开放报名', '停止报名', '已开课'],\r\n pxccOptions: ['无', '本科', '硕士', '博士'],\r\n\r\n // ==================== 查询条件 ====================\r\n searchForm: {\r\n js: '',\r\n kbcnj: '',\r\n xxkzt: '',\r\n kckmmc: '',\r\n xxbmc: '',\r\n pxcc: ''\r\n },\r\n\r\n // ==================== 数据表格 ====================\r\n tableData: [],\r\n total: 0,\r\n loading: false,\r\n selectedRows: [],\r\n\r\n // ==================== 文件上传 ====================\r\n selectedFile: null,\r\n\r\n // ==================== 新建选修课弹窗 ====================\r\n dialogVisible: false,\r\n form: {\r\n kcmc: '',\r\n js: '',\r\n jc: '',\r\n jxcd: '',\r\n jhsxs: 0,\r\n yxsxs: 0,\r\n xf: 0,\r\n jh: 0\r\n },\r\n rules: {\r\n kcmc: [{ required: true, message: '请输入课程名称', trigger: 'blur' }],\r\n js: [{ required: true, message: '请输入实施教员', trigger: 'blur' }]\r\n },\r\n\r\n // ==================== 分页 ====================\r\n currentPage: 1,\r\n pageSize: 20\r\n }\r\n },\r\n computed: {\r\n fileName() {\r\n return (this.selectedFile && this.selectedFile.name) || '未选择任何文件'\r\n }\r\n },\r\n created() {\r\n this.loadList()\r\n },\r\n methods: {\r\n // 组装查询过滤条件(列表与导出共用,导出不含分页参数)\r\n buildFilter() {\r\n const q = {}\r\n if (this.searchForm.js) q.jyxm = this.searchForm.js\r\n if (this.searchForm.kbcnj) q.kxbcnj = this.searchForm.kbcnj\r\n if (this.searchForm.kckmmc) q.kmc = this.searchForm.kckmmc\r\n if (this.searchForm.xxbmc) q.xxbmc = this.searchForm.xxbmc\r\n if (this.searchForm.xxkzt) q.xkzt = this.searchForm.xxkzt\r\n if (this.searchForm.pxcc) q.pxcc = this.searchForm.pxcc\r\n return q\r\n },\r\n\r\n // ==================== 查询 ====================\r\n handleQuery() {\r\n this.currentPage = 1\r\n this.loadList()\r\n },\r\n loadList() {\r\n this.loading = true\r\n const params = Object.assign({ pageNum: this.currentPage, pageSize: this.pageSize }, this.buildFilter())\r\n listElective(params)\r\n .then(res => {\r\n const data = (res && res.data) || {}\r\n this.tableData = data.records || []\r\n this.total = data.total || 0\r\n })\r\n .finally(() => {\r\n this.loading = false\r\n })\r\n },\r\n\r\n // ==================== 导出 ====================\r\n handleDownloadList() {\r\n exportElectiveList(this.buildFilter())\r\n .then(blob => {\r\n saveAs(blob, '选修班列表.xlsx')\r\n this.$message.success('选修班列表已下载')\r\n })\r\n .catch(() => {})\r\n },\r\n handleDownloadWord() {\r\n const bhList = this.selectedRows.map(row => row.bh)\r\n if (bhList.length === 0) {\r\n this.$message.warning('请先选择选修班')\r\n return\r\n }\r\n exportElectiveStudentsWord(bhList)\r\n .then(blob => {\r\n saveAs(blob, '选修班学员名单.docx')\r\n this.$message.success('选修班学员名单Word已下载')\r\n })\r\n .catch(() => {})\r\n },\r\n handleDownloadExcel() {\r\n const bhList = this.selectedRows.map(row => row.bh)\r\n if (bhList.length === 0) {\r\n this.$message.warning('请先选择选修班')\r\n return\r\n }\r\n exportElectiveStudentsExcel(bhList)\r\n .then(blob => {\r\n saveAs(blob, '选修班学员名单.xlsx')\r\n this.$message.success('选修班学员名单Excel已下载')\r\n })\r\n .catch(() => {})\r\n },\r\n\r\n // ==================== 操作按钮 ====================\r\n handleOpenEarly() {\r\n const bhList = this.selectedRows.map(row => row.bh)\r\n if (bhList.length === 0) {\r\n this.$message.warning('请先选择选修班')\r\n return\r\n }\r\n batchOpenElective(bhList)\r\n .then(() => {\r\n this.$message.success('所选班已开放报名')\r\n this.loadList()\r\n })\r\n .catch(() => {})\r\n },\r\n handleCancelEarly() {\r\n const bhList = this.selectedRows.map(row => row.bh)\r\n if (bhList.length === 0) {\r\n this.$message.warning('请先选择选修班')\r\n return\r\n }\r\n batchCancelOpenElective(bhList)\r\n .then(() => {\r\n this.$message.success('所选班已取消开放报名')\r\n this.loadList()\r\n })\r\n .catch(() => {})\r\n },\r\n handleStopSignup() {\r\n const bhList = this.selectedRows.map(row => row.bh)\r\n if (bhList.length === 0) {\r\n this.$message.warning('请先选择选修班')\r\n return\r\n }\r\n batchStopElective(bhList)\r\n .then(() => {\r\n this.$message.success('已批量停止报名')\r\n this.loadList()\r\n })\r\n .catch(() => {})\r\n },\r\n handleReverseRange() {\r\n this.$message.warning('后端暂未提供该接口')\r\n },\r\n handleDownloadTemplate() {\r\n this.$message.warning('后端暂未提供该接口')\r\n },\r\n\r\n // ==================== 文件上传 ====================\r\n handleSelectFile() {\r\n this.$refs.fileInputRef && this.$refs.fileInputRef.click()\r\n },\r\n handleFileChange(e) {\r\n this.selectedFile = e.target.files[0] || null\r\n },\r\n handleUpload() {\r\n if (!this.selectedFile) {\r\n this.$message.warning('请先选择文件')\r\n return\r\n }\r\n this.$message.warning('后端暂未提供该接口')\r\n },\r\n\r\n // ==================== 表格多选 ====================\r\n handleSelectionChange(rows) {\r\n this.selectedRows = rows\r\n },\r\n\r\n // ==================== 新建选修课弹窗 ====================\r\n handleOpenNew() {\r\n this.$message.warning('后端暂未提供该接口')\r\n },\r\n handleNewConfirm() {\r\n if (!this.$refs.formRef) return\r\n this.$refs.formRef.validate((valid) => {\r\n if (!valid) return\r\n console.log('新建选修课:', JSON.parse(JSON.stringify(this.form)))\r\n this.$message.success('新建选修课成功(前端模拟)')\r\n this.dialogVisible = false\r\n })\r\n },\r\n\r\n // ==================== 分页 ====================\r\n handlePageChange(page) {\r\n this.currentPage = page\r\n this.loadList()\r\n },\r\n\r\n // 表格序号(跨页连续)\r\n tableIndex(index) {\r\n return (this.currentPage - 1) * this.pageSize + index + 1\r\n }\r\n }\r\n}\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n// ==================== 2. 查询条件区域 ====================\r\n.query-card {\r\n .query-field {\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 14px;\r\n min-height: 32px;\r\n\r\n .q-label {\r\n width: 120px;\r\n flex-shrink: 0;\r\n font-size: 13px;\r\n color: #303133;\r\n text-align: right;\r\n margin-right: 10px;\r\n white-space: nowrap;\r\n }\r\n\r\n .q-control {\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n }\r\n}\r\n\r\n.export-bar {\r\n align-items: center;\r\n}\r\n\r\n// ==================== 4. 操作按钮区域 ====================\r\n.action-card {\r\n .action-row {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 12px;\r\n margin-bottom: 12px;\r\n\r\n &:last-child {\r\n margin-bottom: 0;\r\n }\r\n }\r\n}\r\n\r\n// ==================== 5. 文件上传区域 ====================\r\n.upload-card {\r\n .upload-row {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n flex-wrap: wrap;\r\n gap: 12px;\r\n\r\n .upload-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n\r\n .file-name {\r\n font-size: 12px;\r\n color: #999;\r\n\r\n &.has-file {\r\n color: #303133;\r\n }\r\n }\r\n }\r\n\r\n .upload-right {\r\n display: flex;\r\n align-items: center;\r\n }\r\n }\r\n}\r\n\r\n// ==================== 6. 数据表格区域 ====================\r\n.table-card {\r\n .main-table {\r\n ::v-deep .cell {\r\n font-size: 12px;\r\n }\r\n }\r\n\r\n .triple-header,\r\n .triple-cell {\r\n display: flex;\r\n flex-direction: column;\r\n line-height: 1.4;\r\n }\r\n\r\n .pagination-wrap {\r\n display: flex;\r\n justify-content: flex-end;\r\n margin-top: 16px;\r\n }\r\n}\r\n</style>\r\n"]}]} |