ExportTemplate.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. <template>
  2. <section class="content">
  3. <div class="part-box">
  4. <h2 class="part-box-title">模板管理</h2>
  5. <!-- 表单 -->
  6. <el-form class="part-filter-form" inline :model="formSearch">
  7. <el-form-item v-if="isSuperAdmin" label="学校">
  8. <el-select
  9. v-model="formSearch.rootOrgId"
  10. clearable
  11. filterable
  12. placeholder="请选择"
  13. class="search_width"
  14. >
  15. <el-option
  16. v-for="item in rootOrgList"
  17. :key="item.id"
  18. :label="item.name"
  19. :value="item.id"
  20. />
  21. </el-select>
  22. </el-form-item>
  23. <el-form-item label="模板名称">
  24. <el-input
  25. v-model="formSearch.fileName"
  26. placeholder="请输入模板名称"
  27. class="search_width"
  28. ></el-input>
  29. </el-form-item>
  30. <el-form-item label="模板类型" prop="type" class="form-item">
  31. <el-select
  32. v-model="formSearch.type"
  33. class="search_width"
  34. :clearable="true"
  35. >
  36. <el-option label="试卷导出" value="PAPER_EXPORT"> </el-option>
  37. <el-option label="答案导出" value="ANWSER_EXPORT"> </el-option>
  38. <el-option label="离线试卷" value="OUTLINE_PAPER_EXPORT">
  39. </el-option>
  40. <el-option label="试卷预览" value="PAPER_VIEW"> </el-option>
  41. <el-option label="答案预览" value="ANWSER_VIEW"> </el-option>
  42. </el-select>
  43. </el-form-item>
  44. <el-form-item>
  45. <el-button type="danger" @click="handleSearchBtn">查询</el-button>
  46. </el-form-item>
  47. </el-form>
  48. <div class="part-box-action">
  49. <el-button type="primary" plain icon="icon icon-set" @click="operConfig"
  50. >配置
  51. </el-button>
  52. <el-button type="primary" icon="icon icon-plus-white" @click="addFile"
  53. >新增</el-button
  54. >
  55. </div>
  56. </div>
  57. <div class="part-box">
  58. <!-- 页面列表 -->
  59. <el-table :data="tableData" resizable>
  60. <el-table-column prop="fileName" label="模板名称"> </el-table-column>
  61. <el-table-column prop="suffix" width="100" label="文件类型">
  62. </el-table-column>
  63. <el-table-column width="150" prop="typeName" label="模板类型">
  64. </el-table-column>
  65. <el-table-column width="160" prop="creationTime" label="上传时间">
  66. </el-table-column>
  67. <el-table-column width="150" prop="createUser" label="上传人">
  68. </el-table-column>
  69. <el-table-column label="状态" width="70">
  70. <template slot-scope="scope">
  71. <span v-if="scope.row.enable">
  72. <el-tooltip
  73. class="item"
  74. effect="dark"
  75. content="启用"
  76. placement="left"
  77. >
  78. <i class="icon icon-right"></i>
  79. </el-tooltip>
  80. </span>
  81. <span v-else>
  82. <el-tooltip
  83. class="item"
  84. effect="dark"
  85. content="禁用"
  86. placement="left"
  87. >
  88. <i class="icon icon-error"></i>
  89. </el-tooltip>
  90. </span>
  91. </template>
  92. </el-table-column>
  93. <el-table-column :context="_self" label="操作" width="220">
  94. <div slot-scope="scope">
  95. <el-button
  96. size="mini"
  97. type="primary"
  98. plain
  99. @click="downFile(scope.row)"
  100. >
  101. 下载
  102. </el-button>
  103. <el-button
  104. v-if="!scope.row.enable"
  105. size="mini"
  106. type="primary"
  107. plain
  108. @click="enable(scope.row)"
  109. >
  110. 启用
  111. </el-button>
  112. <el-button
  113. v-if="scope.row.enable"
  114. size="mini"
  115. type="danger"
  116. plain
  117. @click="disenable(scope.row)"
  118. >
  119. 禁用
  120. </el-button>
  121. <el-button
  122. size="mini"
  123. type="danger"
  124. plain
  125. @click="deleteFile(scope.row)"
  126. >
  127. 删除
  128. </el-button>
  129. </div>
  130. </el-table-column>
  131. </el-table>
  132. <div class="part-page">
  133. <el-pagination
  134. v-if="paginationShow"
  135. :current-page="currentPage"
  136. :page-size="pageSize"
  137. :page-sizes="[10, 20, 50, 100, 200, 300]"
  138. layout="total, sizes, prev, pager, next, jumper"
  139. :total="total"
  140. @current-change="handleCurrentChange"
  141. @size-change="handleSizeChange"
  142. />
  143. </div>
  144. </div>
  145. <el-dialog
  146. title="新增模板"
  147. width="550px"
  148. :visible.sync="fileModel"
  149. :close-on-click-modal="false"
  150. :modal="false"
  151. append-to-body
  152. custom-class="side-dialog"
  153. @close="closeFileModel"
  154. >
  155. <el-form
  156. ref="fileForm"
  157. :key="fileModelKey"
  158. :inline="true"
  159. :model="fileForm"
  160. :rules="fileRules"
  161. label-width="90px"
  162. >
  163. <el-form-item label="模板名称" prop="templateName">
  164. <el-input
  165. v-model="fileForm.templateName"
  166. class="pull-length"
  167. placeholder="请输入模板名称"
  168. ></el-input>
  169. </el-form-item>
  170. <el-form-item label="模板类型" prop="type" class="form-item">
  171. <el-select v-model="fileForm.type" :clearable="true" class="input">
  172. <el-option label="试卷导出" value="PAPER_EXPORT"> </el-option>
  173. <el-option label="答案导出" value="ANWSER_EXPORT"> </el-option>
  174. <el-option label="离线试卷" value="OUTLINE_PAPER_EXPORT">
  175. </el-option>
  176. <el-option label="试卷预览" value="PAPER_VIEW"> </el-option>
  177. <el-option label="答案预览" value="ANWSER_VIEW"> </el-option>
  178. </el-select>
  179. </el-form-item>
  180. <el-form-item label="文件" prop="dataFile">
  181. <el-input
  182. v-model="fileForm.fileName"
  183. class="pull-length"
  184. :readonly="true"
  185. placeholder="文件最大限制10M"
  186. />
  187. </el-form-item>
  188. <el-form-item>
  189. <el-upload
  190. :before-upload="handleUploadFile"
  191. accept=".ftl,.zip"
  192. action="/upload"
  193. >
  194. <el-button
  195. type="primary"
  196. size="small"
  197. icon="ios-cloud-upload-outline"
  198. >请选择文件
  199. </el-button>
  200. </el-upload>
  201. </el-form-item>
  202. </el-form>
  203. <div slot="footer">
  204. <el-button type="primary" :loading="fileForm.loading" @click="subFile"
  205. >确定</el-button
  206. >
  207. <el-button @click="closeFileModel">取消</el-button>
  208. </div>
  209. </el-dialog>
  210. <el-dialog
  211. title="配置信息"
  212. width="550px"
  213. :visible.sync="configModel"
  214. :close-on-click-modal="false"
  215. :modal="false"
  216. append-to-body
  217. custom-class="side-dialog"
  218. @close="closeConfigModel"
  219. >
  220. <el-form
  221. ref="configForm"
  222. :key="configModelKey"
  223. :inline="true"
  224. :model="configForm"
  225. :rules="configRules"
  226. label-width="90px"
  227. >
  228. <el-form-item v-if="isSuperAdmin" label="学校名称">
  229. <el-input
  230. v-model="configForm.orgName"
  231. disabled="true"
  232. class="pull-length"
  233. ></el-input>
  234. </el-form-item>
  235. <el-form-item label="配置名称" prop="serviceName">
  236. <el-input
  237. v-model="configForm.serviceName"
  238. class="pull-length"
  239. placeholder="请输入serviceName"
  240. ></el-input>
  241. </el-form-item>
  242. </el-form>
  243. <div slot="footer">
  244. <el-button
  245. type="primary"
  246. :loading="configForm.loading"
  247. @click="subConfig"
  248. >确定</el-button
  249. >
  250. <el-button @click="closeConfigModel">取消</el-button>
  251. </div>
  252. </el-dialog>
  253. </section>
  254. </template>
  255. <script>
  256. import { QUESTION_API } from "@/constants/constants.js";
  257. import { mapState } from "vuex";
  258. export default {
  259. name: "ExportTemplate",
  260. data() {
  261. var reg = /\.zip|\.ftl$/;
  262. var validateFile = function (rule, value, callback) {
  263. if (value) {
  264. var upFileName = value.name;
  265. if (value.size > 1024 * 1024 * 10) {
  266. return callback(new Error("文件大小限制为10M"));
  267. } else if (!upFileName.match(reg)) {
  268. return callback(new Error("文件类型只能是ftl或zip"));
  269. } else {
  270. callback();
  271. }
  272. } else {
  273. callback();
  274. }
  275. };
  276. return {
  277. rootOrgList: [],
  278. loading: false,
  279. fileModel: false,
  280. fileModelKey: Math.random(),
  281. configModel: false,
  282. configModelKey: Math.random(),
  283. paginationShow: false,
  284. formSearch: {
  285. rootOrgId: null,
  286. fileName: "",
  287. type: "",
  288. },
  289. fileForm: {
  290. templateName: null,
  291. type: null,
  292. fileName: null,
  293. dataFile: null,
  294. loading: false,
  295. },
  296. configForm: {
  297. serviceName: null,
  298. orgName: null,
  299. loading: false,
  300. },
  301. tableData: [],
  302. currentPage: 1,
  303. pageSize: 10,
  304. total: 10,
  305. fileRules: {
  306. templateName: [
  307. {
  308. required: true,
  309. type: "string",
  310. message: "请输入模板名称",
  311. trigger: "change",
  312. },
  313. {
  314. pattern: /^[^\\/\\?%#&=\\+]*$/,
  315. message: "名称不能包含特殊字符 / ? % # & = +",
  316. trigger: "change",
  317. },
  318. ],
  319. type: [
  320. {
  321. required: true,
  322. type: "string",
  323. message: "请选择模板类型",
  324. trigger: "change",
  325. },
  326. ],
  327. dataFile: [
  328. {
  329. required: true,
  330. type: "object",
  331. message: "请选择文件",
  332. trigger: "change",
  333. },
  334. {
  335. validator: validateFile,
  336. type: "object",
  337. trigger: "change",
  338. },
  339. ],
  340. },
  341. configRules: {
  342. serviceName: [
  343. {
  344. required: true,
  345. type: "string",
  346. message: "请输入配置名称",
  347. trigger: "change",
  348. },
  349. {
  350. pattern: /^[^\\/\\?%#&=\\+]*$/,
  351. message: "名称不能包含特殊字符 / ? % # & = +",
  352. trigger: "change",
  353. },
  354. ],
  355. },
  356. };
  357. },
  358. computed: {
  359. ...mapState({ user: (state) => state.user }),
  360. isSuperAdmin() {
  361. return this.user.roleList.some((role) => role.roleCode == "SUPER_ADMIN");
  362. },
  363. },
  364. watch: {
  365. "formSearch.rootOrgId": {
  366. immediate: false,
  367. handler(val) {
  368. if (val == null) {
  369. this.curDir = "";
  370. } else {
  371. this.curDir = "/";
  372. this.formSearch.parentId = -1;
  373. this.handleSearchBtn();
  374. }
  375. },
  376. },
  377. },
  378. //初始化查询
  379. created() {
  380. this.init();
  381. },
  382. methods: {
  383. downFile(row) {
  384. window.location.href = row.fullFilePath;
  385. },
  386. enable(row) {
  387. var url =
  388. QUESTION_API +
  389. "/exportTemplate/enable/" +
  390. this.formSearch.rootOrgId +
  391. "/" +
  392. row.id;
  393. this.$httpWithMsg.put(url).then(() => {
  394. this.$notify({
  395. type: "success",
  396. message: "启用成功!",
  397. });
  398. this.searchForm();
  399. });
  400. },
  401. disenable(row) {
  402. var url =
  403. QUESTION_API +
  404. "/exportTemplate/disenable/" +
  405. this.formSearch.rootOrgId +
  406. "/" +
  407. row.id;
  408. this.$httpWithMsg.put(url).then(() => {
  409. this.$notify({
  410. type: "success",
  411. message: "禁用成功!",
  412. });
  413. this.searchForm();
  414. });
  415. },
  416. deleteFile(row) {
  417. this.$confirm("确定删除?", "提示", {
  418. confirmButtonText: "确定",
  419. cancelButtonText: "取消",
  420. type: "warning",
  421. }).then(() => {
  422. var url =
  423. QUESTION_API +
  424. "/exportTemplate/" +
  425. this.formSearch.rootOrgId +
  426. "/" +
  427. row.id;
  428. this.$httpWithMsg.delete(url).then(() => {
  429. this.$notify({
  430. type: "success",
  431. message: "删除成功!",
  432. });
  433. this.searchForm();
  434. });
  435. });
  436. },
  437. handleUploadFile(file) {
  438. this.fileForm.dataFile = file;
  439. this.fileForm.fileName = file.name;
  440. return false;
  441. },
  442. addFile() {
  443. if (this.formSearch.rootOrgId == null) {
  444. this.$notify({
  445. type: "warning",
  446. message: "请选择学校",
  447. });
  448. return;
  449. }
  450. this.fileModel = true;
  451. },
  452. operConfig() {
  453. if (this.formSearch.rootOrgId == null) {
  454. this.$notify({
  455. type: "warning",
  456. message: "请选择学校",
  457. });
  458. return;
  459. }
  460. this.loading = true;
  461. var url =
  462. QUESTION_API + "/exportTemplate/config/" + this.formSearch.rootOrgId;
  463. this.$httpWithMsg
  464. .get(url)
  465. .then((response) => {
  466. this.configForm.serviceName = response.data.exportServiceName;
  467. if (this.isSuperAdmin) {
  468. for (const org of this.rootOrgList) {
  469. if (this.formSearch.rootOrgId == org.id) {
  470. this.configForm.orgName = org.name;
  471. break;
  472. }
  473. }
  474. }
  475. this.configModel = true;
  476. })
  477. .finally(() => (this.loading = false));
  478. },
  479. async subFile() {
  480. const res = await this.$refs.fileForm.validate();
  481. if (res === false) {
  482. return;
  483. }
  484. this.fileForm.loading = true;
  485. var params =
  486. "?templateName=" +
  487. this.fileForm.templateName +
  488. "&type=" +
  489. this.fileForm.type;
  490. var url =
  491. QUESTION_API +
  492. "/exportTemplate/add/" +
  493. this.formSearch.rootOrgId +
  494. params;
  495. let formData = new FormData();
  496. formData.append("dataFile", this.fileForm.dataFile);
  497. this.$httpWithMsg
  498. .post(url, formData)
  499. .then(() => {
  500. this.$notify({
  501. type: "success",
  502. message: "上传成功!",
  503. });
  504. this.closeFileModel();
  505. this.searchForm();
  506. })
  507. .finally(() => (this.fileForm.loading = false));
  508. },
  509. async subConfig() {
  510. const res = await this.$refs.configForm.validate();
  511. if (res === false) {
  512. return;
  513. }
  514. this.configForm.loading = true;
  515. var params = "?serviceName=" + this.configForm.serviceName;
  516. var url =
  517. QUESTION_API +
  518. "/exportTemplate/config/" +
  519. this.formSearch.rootOrgId +
  520. params;
  521. this.$httpWithMsg
  522. .put(url)
  523. .then(() => {
  524. this.$notify({
  525. type: "success",
  526. message: "配置成功!",
  527. });
  528. this.closeConfigModel();
  529. })
  530. .finally(() => (this.configForm.loading = false));
  531. },
  532. closeFileModel() {
  533. this.fileModel = false;
  534. this.$refs.fileForm.resetFields();
  535. this.fileModelKey = Math.random();
  536. this.fileForm.fileName = null;
  537. this.fileForm.type = null;
  538. this.fileForm.dataFile = null;
  539. this.fileForm.templateName = null;
  540. },
  541. closeConfigModel() {
  542. this.configModel = false;
  543. this.$refs.configForm.resetFields();
  544. this.configModelKey = Math.random();
  545. this.configForm.orgName = null;
  546. this.configForm.serviceName = null;
  547. },
  548. handleSearchBtn() {
  549. this.currentPage = 1;
  550. this.searchForm();
  551. },
  552. handleSizeChange(val) {
  553. this.pageSize = val;
  554. this.currentPage = 1;
  555. this.searchForm();
  556. },
  557. handleCurrentChange(val) {
  558. this.currentPage = val;
  559. this.searchForm();
  560. },
  561. //查询
  562. searchForm() {
  563. if (this.formSearch.rootOrgId == null) {
  564. this.$notify({
  565. type: "warning",
  566. message: "请选择学校",
  567. });
  568. return;
  569. }
  570. this.loading = true;
  571. var url =
  572. QUESTION_API +
  573. "/exportTemplate/page/" +
  574. this.currentPage +
  575. "/" +
  576. this.pageSize;
  577. this.$httpWithMsg
  578. .get(url, { params: this.formSearch })
  579. .then((response) => {
  580. this.tableData = response.data.content;
  581. this.total = response.data.totalElements;
  582. this.loading = false;
  583. this.$nextTick(function () {
  584. this.paginationShow = true;
  585. });
  586. })
  587. .finally(() => (this.loading = false));
  588. },
  589. init() {
  590. if (this.isSuperAdmin) {
  591. this.$httpWithMsg
  592. .get(QUESTION_API + "/org/getRootOrgList")
  593. .then((response) => {
  594. this.rootOrgList = response.data;
  595. });
  596. } else {
  597. this.formSearch.rootOrgId = this.user.rootOrgId;
  598. this.searchForm();
  599. }
  600. },
  601. },
  602. };
  603. </script>
  604. <style scoped>
  605. .page {
  606. margin-top: 10px;
  607. }
  608. .pull-length {
  609. width: 300px;
  610. }
  611. .details-length {
  612. width: 400px;
  613. }
  614. .pull-center {
  615. margin-top: 20px;
  616. }
  617. .editForm .el-form-item {
  618. margin-bottom: 12px;
  619. }
  620. .form-row {
  621. margin-top: 20px;
  622. }
  623. </style>