index.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. <template>
  2. <div class="app-container">
  3. <!-- 表格 -->
  4. <el-table v-loading="loading" :data="planList" @selection-change="handleSelectionChange" :height="clientHeight" border :cell-style="tableCellStyle">
  5. <el-table-column type="selection" width="55" align="center" />
  6. <el-table-column label="课程内容" align="center" prop="plantName" :show-overflow-tooltip="true"/>
  7. <el-table-column label="具体内容" align="center" prop="classContent" :show-overflow-tooltip="true"/>
  8. <el-table-column label="开始日期" align="center" prop="startDate" width="150">
  9. <template slot-scope="scope">
  10. <span>{{ parseTime(scope.row.startDate, '{y}-{m}-{d}') }}</span>
  11. </template>
  12. </el-table-column>
  13. <el-table-column label="结束日期" align="center" prop="endDate" width="150">
  14. <template slot-scope="scope">
  15. <span>{{ parseTime(scope.row.endDate, '{y}-{m}-{d}') }}</span>
  16. </template>
  17. </el-table-column>
  18. <el-table-column label="实际完成日期" align="center" prop="dateOfCompletion" width="150">
  19. <template slot-scope="scope">
  20. <span>{{ parseTime(scope.row.dateOfCompletion, '{y}-{m}-{d}') }}</span>
  21. </template>
  22. </el-table-column>
  23. <el-table-column label="学习状态" align="center" prop="studyState" :formatter="studyStateFormat" width="120"/>
  24. <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
  25. <template slot-scope="scope">
  26. <el-button
  27. size="mini"
  28. type="text"
  29. icon="el-icon-circle-check"
  30. v-hasPermi="['spec:plan:edit']"
  31. @click="handleFeedback(scope.row)"
  32. v-if="scope.row.studyState == 0"
  33. >反馈</el-button>
  34. <el-button
  35. size="mini"
  36. type="text"
  37. icon="el-icon-document"
  38. @click="handleDoc(scope.row)"
  39. v-hasPermi="['spec:plan:edit']"
  40. >学员附件</el-button>
  41. <el-button
  42. size="mini"
  43. type="text"
  44. icon="el-icon-document"
  45. @click="handleDoc(scope.row)"
  46. v-hasPermi="['spec:plan:edit']"
  47. >学习资料</el-button>
  48. </template>
  49. </el-table-column>
  50. </el-table>
  51. <!-- 分页 -->
  52. <pagination
  53. v-show="total>0"
  54. :total="total"
  55. :page.sync="queryParams.pageNum"
  56. :limit.sync="queryParams.pageSize"
  57. @pagination="getList"
  58. />
  59. <!-- 附件对话框 -->
  60. <el-dialog v-dialogDrag :title="doc.title" :visible.sync="doc.open" width="800px" append-to-body>
  61. <el-upload
  62. ref="doc"
  63. :limit="50"
  64. :headers="doc.headers"
  65. :action="doc.url + '?pType=' + doc.pType + '&pId=' + doc.pId"
  66. :disabled="doc.isUploading"
  67. :on-progress="handleFileDocProgress"
  68. :on-success="handleFileDocSuccess"
  69. :auto-upload="true"
  70. drag
  71. >
  72. <i class="el-icon-upload"></i>
  73. <div class="el-upload__text">
  74. {{ $t('将文件拖到此处,或') }}
  75. <em>{{ $t('点击上传') }}</em>
  76. </div>
  77. </el-upload>
  78. <el-table :data="doc.commonfileList" border>
  79. <el-table-column :label="$t('文件名')" align="center" prop="fileName" :show-overflow-tooltip="true">
  80. <template slot-scope="scope">
  81. <a class="link-type" @click="handleDownload(scope.row)">
  82. <span>{{ scope.row.fileName }}</span>
  83. </a>
  84. </template>
  85. </el-table-column>
  86. <el-table-column :label="$t('大小(Kb)')" align="center" prop="fileSize" :show-overflow-tooltip="true" width="80" />
  87. <el-table-column :label="$t('上传人')" align="center" prop="creator" :show-overflow-tooltip="true" width="120"/>
  88. <el-table-column :label="$t('操作')" align="center" width="180" class-name="small-padding fixed-width">
  89. <template slot-scope="scope">
  90. <el-button
  91. v-if="scope.row.fileName.endsWith('pdf')"
  92. size="mini"
  93. type="text"
  94. icon="el-icon-view"
  95. @click="handleSee(scope.row)"
  96. >{{ $t('预览') }}</el-button>
  97. <el-button
  98. size="mini"
  99. type="text"
  100. icon="el-icon-download"
  101. @click="handleDownload(scope.row)"
  102. >{{ $t('下载') }}</el-button>
  103. <el-button
  104. size="mini"
  105. type="text"
  106. icon="el-icon-delete"
  107. @click="handleDeleteDoc(scope.row)"
  108. >{{ $t('删除') }}</el-button>
  109. </template>
  110. </el-table-column>
  111. </el-table>
  112. <el-dialog v-dialogDrag :title="pdf.title" :visible.sync="pdf.open" width="1300px" append-to-body>
  113. <div style="margin-top: -60px;float: right;margin-right: 40px;">
  114. <el-button size="mini" type="text" @click="openPdf">{{$t('新页面打开PDF')}}</el-button></div>
  115. <div style="margin-top: -30px">
  116. <iframe :src="pdf.pdfUrl" frameborder="0" width="100%" height="700px"></iframe>
  117. </div>
  118. </el-dialog>
  119. <div slot="footer" class="dialog-footer">
  120. <el-button @click="doc.open = false">{{ $t('返 回') }}</el-button>
  121. </div>
  122. </el-dialog>
  123. <!-- 反馈对话框 -->
  124. <el-dialog v-dialogDrag :title="feedbackDialog.title" :visible.sync="feedbackDialog.open" width="800px" append-to-body>
  125. <el-upload
  126. ref="doc"
  127. :limit="50"
  128. :headers="doc.headers"
  129. :action="doc.url + '?pType=' + doc.pType + '&pId=' + doc.pId"
  130. :disabled="doc.isUploading"
  131. :on-progress="handleFileDocProgress"
  132. :on-success="handleFileDocSuccess"
  133. :auto-upload="true"
  134. drag
  135. >
  136. <i class="el-icon-upload"></i>
  137. <div class="el-upload__text">
  138. {{ $t('将文件拖到此处,或') }}
  139. <em>{{ $t('点击上传') }}</em>
  140. </div>
  141. </el-upload>
  142. <el-table :data="doc.commonfileList" border>
  143. <el-table-column :label="$t('文件名')" align="center" prop="fileName" :show-overflow-tooltip="true">
  144. <template slot-scope="scope">
  145. <a class="link-type" @click="handleDownload(scope.row)">
  146. <span>{{ scope.row.fileName }}</span>
  147. </a>
  148. </template>
  149. </el-table-column>
  150. <el-table-column :label="$t('大小(Kb)')" align="center" prop="fileSize" :show-overflow-tooltip="true" width="80" />
  151. <el-table-column :label="$t('上传人')" align="center" prop="creator" :show-overflow-tooltip="true" width="120"/>
  152. <el-table-column :label="$t('操作')" align="center" width="180" class-name="small-padding fixed-width">
  153. <template slot-scope="scope">
  154. <el-button
  155. v-if="scope.row.fileName.endsWith('pdf')"
  156. size="mini"
  157. type="text"
  158. icon="el-icon-view"
  159. @click="handleSee(scope.row)"
  160. >{{ $t('预览') }}</el-button>
  161. <el-button
  162. size="mini"
  163. type="text"
  164. icon="el-icon-download"
  165. @click="handleDownload(scope.row)"
  166. >{{ $t('下载') }}</el-button>
  167. <el-button
  168. size="mini"
  169. type="text"
  170. icon="el-icon-delete"
  171. @click="handleDeleteDoc(scope.row)"
  172. >{{ $t('删除') }}</el-button>
  173. </template>
  174. </el-table-column>
  175. </el-table>
  176. <el-form>
  177. <el-form-item label="我学到了什么?">
  178. <el-input v-model="feedbackParams.answer1" placeholder="请输入" type="textarea"></el-input>
  179. </el-form-item>
  180. <el-form-item label="理论学习和平时操作的不同之处?">
  181. <el-input v-model="feedbackParams.answer2" placeholder="请输入" type="textarea"></el-input>
  182. </el-form-item>
  183. <el-form-item label="完成此课程后有什么更好的合理化建议?">
  184. <el-input v-model="feedbackParams.answer3" placeholder="请输入" type="textarea"></el-input>
  185. </el-form-item>
  186. </el-form>
  187. <div slot="footer" class="dialog-footer">
  188. <el-button @click="handleSubmitFeedback()">{{ $t('保 存') }}</el-button>
  189. <el-button @click="feedbackDialog.open = false">{{ $t('返 回') }}</el-button>
  190. </div>
  191. </el-dialog>
  192. </div>
  193. </template>
  194. <script>
  195. import {
  196. updateAnswer,
  197. addAnswer,
  198. getAnswerByPlanIdAndQuestionId
  199. } from "@/api/training/spec/answer";
  200. import {
  201. getPlan,
  202. delPlan,
  203. addPlan,
  204. updatePlan,
  205. exportPlan,
  206. importTemplate,
  207. listPlanByStaffId
  208. } from "@/api/training/spec/plan";
  209. import {
  210. allFileList,
  211. delCommonfile
  212. } from "@/api/common/commonfile";
  213. import { treeselect } from "@/api/system/dept";
  214. import { getToken } from "@/utils/auth";
  215. import Treeselect from "@riophae/vue-treeselect";
  216. import "@riophae/vue-treeselect/dist/vue-treeselect.css";
  217. export default {
  218. name: "MyPlan",
  219. components: { Treeselect },
  220. data() {
  221. return {
  222. // 遮罩层
  223. loading: true,
  224. // 选中数组
  225. ids: [],
  226. dataListSelections: [],
  227. // 非单个禁用
  228. single: true,
  229. // 非多个禁用
  230. multiple: true,
  231. // 显示搜索条件
  232. showSearch: false,
  233. // 总条数
  234. total: 0,
  235. // 培训计划表格数据
  236. planList: [],
  237. // 弹出层标题
  238. title: "",
  239. // 操作
  240. operation: "",
  241. // 部门树选项
  242. deptOptions: undefined,
  243. clientHeight:300,
  244. // 是否显示弹出层
  245. open: false,
  246. // 学习状态字典
  247. studyStateOptions: [],
  248. // 报告附件参数
  249. doc: {
  250. file: "",
  251. // 是否显示弹出层(报告附件)
  252. open: false,
  253. // 弹出层标题(报告附件)
  254. title: "",
  255. // 是否禁用上传
  256. isUploading: false,
  257. // 是否更新已经存在的用户数据
  258. updateSupport: 0,
  259. // 报告附件上传位置编号
  260. ids: 0,
  261. // 设置上传的请求头部
  262. headers: { Authorization: "Bearer " + getToken() },
  263. // 上传的地址
  264. url: process.env.VUE_APP_BASE_API + "/common/commonfile/uploadFile",
  265. commonfileList: null,
  266. queryParams: {
  267. pId: null,
  268. pType: 'plan'
  269. },
  270. pType: 'plan',
  271. pId: null
  272. },
  273. // 反馈对话框参数
  274. feedbackDialog: {
  275. // 是否显示弹出层(报告附件)
  276. open: false,
  277. // 弹出层标题(报告附件)
  278. title: ""
  279. },
  280. // 反馈参数
  281. feedbackParams: {
  282. answer1: null,
  283. answer2: null,
  284. answer3: null
  285. },
  286. // 计划id
  287. planId: null,
  288. // 查询参数
  289. queryParams: {
  290. pageNum: 1,
  291. pageSize: 20,
  292. staffId: null,
  293. plantName: null,
  294. startDate: null,
  295. endDate: null,
  296. classHour: null,
  297. studyState: null,
  298. // approveStatus: 1
  299. },
  300. // 表单参数
  301. form: {},
  302. // 表单校验
  303. rules: {
  304. },
  305. // pdf文件参数
  306. pdf : {
  307. title: '',
  308. pdfUrl: '',
  309. numPages: null,
  310. open: false,
  311. pageNum: 1,
  312. pageTotalNum: 1,
  313. loadedRatio: 0,
  314. },
  315. };
  316. },
  317. watch: {
  318. // 根据名称筛选部门树
  319. deptName(val) {
  320. this.$refs.tree.filter(val);
  321. }
  322. },
  323. created() {
  324. //设置表格高度对应屏幕高度
  325. this.$nextTick(() => {
  326. this.clientHeight = document.body.clientHeight -250
  327. })
  328. this.getList();
  329. this.getTreeselect();
  330. this.getDicts("st_study_state").then(response => {
  331. this.studyStateOptions = response.data;
  332. });
  333. },
  334. methods: {
  335. /** 单元格样式 */
  336. tableCellStyle(row, column, rowIndex, columnIndex) {
  337. if (row.column.label === "实际完成日期" && row.row.dateOfCompletion > row.row.endDate) {
  338. return "background: #FFEEEE"
  339. }
  340. },
  341. /** 反馈按钮处理 */
  342. handleFeedback(row) {
  343. this.feedbackParams = {};
  344. let feedback1 = {};
  345. feedback1.planId = row.id;
  346. feedback1.questionId = 1;
  347. let feedback2 = {};
  348. feedback2.planId = row.id;
  349. feedback2.questionId = 2;
  350. let feedback3 = {};
  351. feedback3.planId = row.id;
  352. feedback3.questionId = 3;
  353. getAnswerByPlanIdAndQuestionId(feedback1).then(response => {
  354. let data = response.data;
  355. if (data != null) {
  356. this.feedbackParams.answer1 = data.answer;
  357. }
  358. return getAnswerByPlanIdAndQuestionId(feedback2);
  359. }).then(response => {
  360. let data = response.data;
  361. if (data != null) {
  362. this.feedbackParams.answer2 = data.answer;
  363. }
  364. return getAnswerByPlanIdAndQuestionId(feedback3);
  365. }).then(response => {
  366. let data = response.data;
  367. if (data != null) {
  368. this.feedbackParams.answer3 = data.answer;
  369. }
  370. this.planId = row.id;
  371. this.feedbackDialog.title = row.plantName + "学习心得";
  372. this.feedbackDialog.open = true;
  373. });
  374. },
  375. /** 提交反馈处理 */
  376. handleSubmitFeedback() {
  377. // 打包数据
  378. let feedback1 = {};
  379. feedback1.planId = this.planId;
  380. feedback1.questionId = 1;
  381. feedback1.answer = this.feedbackParams.answer1;
  382. let feedback2 = {};
  383. feedback2.planId = this.planId;
  384. feedback2.questionId = 2;
  385. feedback2.answer = this.feedbackParams.answer2;
  386. let feedback3 = {};
  387. feedback3.planId = this.planId;
  388. feedback3.questionId = 3;
  389. feedback3.answer = this.feedbackParams.answer3;
  390. // 保存数据
  391. getAnswerByPlanIdAndQuestionId(feedback1).then(response => {
  392. let data = response.data;
  393. if (data != null) {
  394. feedback1.id = data.id;
  395. updateAnswer(feedback1);
  396. } else {
  397. addAnswer(feedback1);
  398. }
  399. });
  400. getAnswerByPlanIdAndQuestionId(feedback2).then(response => {
  401. let data = response.data;
  402. if (data != null) {
  403. feedback2.id = data.id;
  404. updateAnswer(feedback2);
  405. } else {
  406. addAnswer(feedback2);
  407. }
  408. });
  409. getAnswerByPlanIdAndQuestionId(feedback3).then(response => {
  410. let data = response.data;
  411. if (data != null) {
  412. feedback3.id = data.id;
  413. updateAnswer(feedback3);
  414. } else {
  415. addAnswer(feedback3);
  416. }
  417. });
  418. // 隐藏对话框
  419. this.feedbackDialog.open = false;
  420. // 提示
  421. this.msgSuccess("保存成功");
  422. },
  423. /** 文件下载处理 */
  424. handleDownload(row) {
  425. var name = row.fileName;
  426. var url = row.fileUrl;
  427. var suffix = url.substring(url.lastIndexOf("."), url.length);
  428. const a = document.createElement('a');
  429. a.setAttribute('download', name);
  430. a.setAttribute('target', '_blank');
  431. a.setAttribute('href', process.env.VUE_APP_BASE_API + url);
  432. a.click();
  433. },
  434. openPdf() {
  435. window.open(this.pdf.pdfUrl);//path是文件的全路径地址
  436. },
  437. handleSee(row) {
  438. this.pdf.open = true;
  439. this.pdf.title = row.fileName;
  440. this.pdf.pdfUrl = process.env.VUE_APP_BASE_API +'/pdf/web/viewer.html?file=' + process.env.VUE_APP_BASE_API + row.fileUrl;
  441. },
  442. /** 报告附件按钮操作 */
  443. handleDoc(row) {
  444. this.doc.id = row.id;
  445. this.doc.title = row.plantName + this.$t('学习资料');
  446. this.doc.open = true;
  447. this.doc.queryParams.pId = row.id;
  448. this.doc.pId = row.id;
  449. this.getFileList();
  450. this.$nextTick(() => {
  451. this.$refs.doc.clearFiles();
  452. })
  453. },
  454. getFileList() {
  455. allFileList(this.doc.queryParams).then(response => {
  456. this.doc.commonfileList = response;
  457. });
  458. },
  459. /** 附件上传中处理 */
  460. handleFileDocProgress(event, file, fileList) {
  461. this.doc.file = file;
  462. this.doc.isUploading = true;
  463. },
  464. /** 附件上传成功处理 */
  465. handleFileDocSuccess(response, file, fileList) {
  466. this.doc.isUploading = false;
  467. this.$alert(response.msg, this.$t('导入结果'), { dangerouslyUseHTMLString: true });
  468. this.getFileList()
  469. },
  470. /** 删除按钮操作 */
  471. handleDeleteDoc(row) {
  472. const ids = row.id || this.ids;
  473. this.$confirm(this.$t('是否确认删除?'), this.$t('警告'), {
  474. confirmButtonText: this.$t('确定'),
  475. cancelButtonText: this.$t('取消'),
  476. type: "warning"
  477. }).then(function() {
  478. return delCommonfile(ids);
  479. }).then(() => {
  480. this.getFileList()
  481. this.msgSuccess(this.$t('删除成功'));
  482. })
  483. },
  484. /** 查询培训计划列表 */
  485. getList() {
  486. this.loading = true;
  487. listPlanByStaffId(this.queryParams).then(response => {
  488. this.planList = response.rows;
  489. this.total = response.total;
  490. this.loading = false;
  491. });
  492. },
  493. /** 查询部门下拉树结构 */
  494. getTreeselect() {
  495. treeselect().then(response => {
  496. this.deptOptions = response.data;
  497. });
  498. },
  499. /** 学习状态字典翻译 */
  500. studyStateFormat(row, column) {
  501. return this.selectDictLabel(this.studyStateOptions, row.studyState);
  502. },
  503. /** 取消按钮 */
  504. cancel() {
  505. this.open = false;
  506. this.reset();
  507. },
  508. /** 表单重置 */
  509. reset() {
  510. this.form = {
  511. id: null,
  512. staffId: null,
  513. plantName: null,
  514. delFlag: null,
  515. createrCode: null,
  516. createdate: null,
  517. updaterCode: null,
  518. updatedate: null,
  519. deptId: null,
  520. startDate: null,
  521. endDate: null,
  522. classHour: null,
  523. classContent: null,
  524. studyState: null
  525. };
  526. this.resetForm("form");
  527. },
  528. /** 搜索按钮操作 */
  529. handleQuery() {
  530. this.queryParams.pageNum = 1;
  531. this.getList();
  532. },
  533. /** 重置按钮操作 */
  534. resetQuery() {
  535. this.resetForm("queryForm");
  536. this.handleQuery();
  537. },
  538. /** 多选框选中数据 */
  539. handleSelectionChange(selection) {
  540. this.ids = selection.map(item => item.id)
  541. this.single = selection.length!==1
  542. this.multiple = !selection.length
  543. this.dataListSelections = selection
  544. },
  545. /** 新增按钮操作 */
  546. handleAdd() {
  547. this.reset();
  548. this.open = true;
  549. this.title = "添加培养计划";
  550. this.operation = "add";
  551. },
  552. /** 修改按钮操作 */
  553. handleUpdate(row) {
  554. this.reset();
  555. const id = row.id || this.ids
  556. getPlan(id).then(response => {
  557. this.form = response.data;
  558. this.open = true;
  559. this.title = "修改培养计划";
  560. this.operation = "modify";
  561. });
  562. },
  563. /** 提交按钮 */
  564. submitForm() {
  565. this.$refs["form"].validate(valid => {
  566. if (valid) {
  567. if (this.form.id != null) {
  568. updatePlan(this.form).then(response => {
  569. this.msgSuccess("修改成功");
  570. this.open = false;
  571. this.getList();
  572. });
  573. } else {
  574. addPlan(this.form).then(response => {
  575. this.msgSuccess("新增成功");
  576. this.open = false;
  577. this.getList();
  578. });
  579. }
  580. }
  581. });
  582. },
  583. /** 删除按钮操作 */
  584. handleDelete(row) {
  585. const ids = row.id || this.ids;
  586. this.$confirm('是否确认删除?', "警告", {
  587. confirmButtonText: "确定",
  588. cancelButtonText: "取消",
  589. type: "warning"
  590. }).then(function() {
  591. return delPlan(ids);
  592. }).then(() => {
  593. this.getList();
  594. this.msgSuccess("删除成功");
  595. })
  596. },
  597. /** 导出按钮操作 */
  598. handleExport() {
  599. const queryParams = this.queryParams;
  600. this.$confirm('是否确认导出所有培养计划数据项?', "警告", {
  601. confirmButtonText: "确定",
  602. cancelButtonText: "取消",
  603. type: "warning"
  604. }).then(function() {
  605. return exportPlan(queryParams);
  606. }).then(response => {
  607. this.download(response.msg);
  608. })
  609. },
  610. /** 导入按钮操作 */
  611. handleImport() {
  612. this.upload.title = "用户导入";
  613. this.upload.open = true;
  614. },
  615. /** 下载模板操作 */
  616. importTemplate() {
  617. importTemplate().then(response => {
  618. this.download(response.msg);
  619. });
  620. },
  621. /** 文件上传中处理 */
  622. handleFileUploadProgress(event, file, fileList) {
  623. this.upload.isUploading = true;
  624. },
  625. /** 文件上传成功处理 */
  626. handleFileSuccess(response, file, fileList) {
  627. this.upload.open = false;
  628. this.upload.isUploading = false;
  629. this.$refs.upload.clearFiles();
  630. this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
  631. this.getList();
  632. },
  633. /** 提交上传文件 */
  634. submitFileForm() {
  635. this.$refs.upload.submit();
  636. },
  637. }
  638. };
  639. </script>