阅行客电子档案
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

533 lines
18 KiB

2 years ago
2 years ago
2 years ago
  1. <template>
  2. <!--用户数据-->
  3. <div class="elect-cont-right">
  4. <!--工具栏-->
  5. <div class="head-container">
  6. <crudOperation :permission="permission">
  7. <template v-slot:left>
  8. <el-button v-permission="permission.add" size="mini" @click="crud.toAdd">
  9. <i class="iconfont icon-xinzeng" />
  10. 新增
  11. </el-button>
  12. <el-button v-permission="permission.edit" size="mini" :disabled="selections.length !== 1" @click="crud.toEdit(selections[0])">
  13. <i class="iconfont icon-bianji" />
  14. 编辑
  15. </el-button>
  16. <el-button slot="reference" v-permission="permission.del" size="mini" :loading="crud.delAllLoading" :disabled="selections.length === 0" @click="toDelete(selections)">
  17. <i class="iconfont icon-shanchu" />
  18. 删除
  19. </el-button>
  20. </template>
  21. <template v-slot:right>
  22. <el-button :loading="crud.downloadLoading" size="mini" :disabled="selections.length === 0" @click="doExport(selections)">
  23. <i class="iconfont icon-daochu" />
  24. 导出
  25. </el-button>
  26. <span class="tip">注意门类节点下才可新增归档范围定义</span>
  27. </template>
  28. </crudOperation>
  29. </div>
  30. <!--表单渲染-->
  31. <el-dialog :close-on-click-modal="false" :modal-append-to-body="false" append-to-body :before-close="crud.cancelCU" :visible.sync="crud.status.cu > 0" :title="crud.status.title">
  32. <div class="setting-dialog">
  33. <el-form ref="form" :inline="true" :model="form" :rules="rules" label-width="90px">
  34. <el-form-item v-if="crud.status.add === 1" label="所属门类" prop="categoryId">
  35. <treeselect
  36. v-model="form.categoryId"
  37. :options="categoryDatas"
  38. placeholder="选择所属门类"
  39. flat
  40. :multiple="false"
  41. :normalizer="normalizer"
  42. @select="selectCategoryTree"
  43. />
  44. </el-form-item>
  45. <el-form-item v-if="crud.status.edit === 1" label="所属门类" prop="categoryId">
  46. <el-input v-model="form.category.cnName" disabled />
  47. </el-form-item>
  48. <el-form-item label="档案分类" prop="archivesClassId">
  49. <!-- :load-options="loadClassifyTree" -->
  50. <treeselect
  51. v-model="form.archivesClassId"
  52. :options="classifyOptions"
  53. :normalizer="classifyNormalizer"
  54. placeholder="选择门类之后再选择档案分类"
  55. />
  56. </el-form-item>
  57. <el-form-item label="编码" prop="scopeCode">
  58. <el-input v-model="form.scopeCode" />
  59. </el-form-item>
  60. <el-form-item label="保管期限" prop="retention">
  61. <el-select v-model="form.retention" placeholder="请选择" style="width:225px;">
  62. <el-option v-for="item in periodOptions" :key="item.value" :label="item.label" :value="item.value" />
  63. </el-select>
  64. </el-form-item>
  65. <el-row>
  66. <el-form-item label="名称说明" prop="scopeName">
  67. <el-input v-model="form.scopeName" type="textarea" :rows="6" style="width: 580px;" />
  68. </el-form-item>
  69. </el-row>
  70. <el-form-item label="顶级范围" prop="isTop" style="width: 345px;">
  71. <el-radio-group v-model="form.isTop" @input="changeIsTop">
  72. <el-radio label="1"></el-radio>
  73. <el-radio label="0"></el-radio>
  74. </el-radio-group>
  75. </el-form-item>
  76. <el-form-item
  77. v-if="form.isTop === '0'"
  78. label="上级分类"
  79. prop="pid"
  80. style="margin-right: 0;"
  81. >
  82. <!-- :load-options="loadScopeTree" -->
  83. <treeselect
  84. v-model="form.pid"
  85. :options="scopes"
  86. placeholder="选择门类之后再选择上级范围"
  87. :normalizer="scopeNormalizer"
  88. />
  89. </el-form-item>
  90. </el-form>
  91. <div slot="footer" class="dialog-footer">
  92. <el-button type="text" @click="crud.cancelCU">取消</el-button>
  93. <el-button :loading="crud.status.cu === 2" type="primary" @click="crud.submitCU">确定</el-button>
  94. </div>
  95. </div>
  96. </el-dialog>
  97. <!--表格渲染-->
  98. <el-table
  99. ref="table"
  100. v-loading="crud.loading"
  101. lazy
  102. :data="tableData"
  103. :row-key="getRowKey"
  104. :load="getSonClass"
  105. :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
  106. highlight-current-row
  107. @select-all="selectAll"
  108. @select="selectTr"
  109. @selection-change="selectionChangeHandler"
  110. @row-click="clickRowHandler"
  111. >
  112. <el-table-column type="selection" align="center" width="55" />
  113. <el-table-column :show-overflow-tooltip="true" prop="scopeCode" label="编码" />
  114. <el-table-column :show-overflow-tooltip="true" prop="scopeName" label="名称或说明" />
  115. <el-table-column :show-overflow-tooltip="true" prop="retention" label="保管期限">
  116. <!-- <template slot-scope="scope">
  117. <div>{{ scope.row.retention === 0 ? '永久' : scope.row.retention === 1 ? '定期30年' : '定期10年' }}</div>
  118. </template> -->
  119. </el-table-column>
  120. <el-table-column :show-overflow-tooltip="true" prop="category" label="所属门类">
  121. <template slot-scope="scope">
  122. <div v-if="scope.row.category">{{ scope.row.category.cnName }}</div>
  123. </template>
  124. </el-table-column>
  125. <el-table-column :show-overflow-tooltip="true" prop="archivesClass" label="所属分类">
  126. <template slot-scope="scope">
  127. <div v-if="scope.row.archivesClass">{{ scope.row.archivesClass.name }}</div>
  128. </template>
  129. </el-table-column>
  130. </el-table>
  131. <!--分页组件-->
  132. <pagination v-if="tableData.length !== 0" />
  133. </div>
  134. </template>
  135. <script>
  136. import { FetchCategoryMenu } from '@/api/system/category/category'
  137. import { FetchArchivesClassTree } from '@/api/system/archivesClass'
  138. import crudScope from '@/api/system/archivesScope'
  139. import CRUD, { presenter, header, form, crud } from '@crud/crud'
  140. import crudOperation from '@crud/CRUD.operation'
  141. import pagination from '@crud/Pagination'
  142. import Treeselect from '@riophae/vue-treeselect'
  143. import '@riophae/vue-treeselect/dist/vue-treeselect.css'
  144. // import { LOAD_CHILDREN_OPTIONS } from '@riophae/vue-treeselect'
  145. import { exportFile } from '@/utils/index'
  146. import qs from 'qs'
  147. import { mapGetters } from 'vuex'
  148. const defaultForm = {
  149. id: null,
  150. categoryId: null,
  151. archivesClassId: null,
  152. scopeName: null,
  153. scopeCode: null,
  154. isTop: '1',
  155. pid: null,
  156. retention: null
  157. }
  158. export default {
  159. name: 'Classify',
  160. components: { crudOperation, pagination, Treeselect },
  161. cruds() {
  162. return CRUD({ title: '范围', url: 'api/archivesScope/initArchivesScope', crudMethod: { ...crudScope }, optShow: {
  163. add: false,
  164. edit: false,
  165. del: false,
  166. reset: false,
  167. download: false,
  168. group: false
  169. }})
  170. },
  171. mixins: [presenter(), header(), form(defaultForm), crud()],
  172. props: {
  173. selectedCategory: {
  174. type: Object,
  175. default: function() {
  176. return {}
  177. }
  178. }
  179. },
  180. data() {
  181. return {
  182. tableData: [],
  183. classifyOptions: [],
  184. categoryDatas: [],
  185. scopes: [],
  186. selections: [],
  187. isAllSelect: false,
  188. rules: {
  189. categoryId: [{ required: true, message: '请选择所属门类', trigger: 'change' }],
  190. archivesClassId: [{ required: true, message: '请选择档案分类', trigger: 'change' }],
  191. scopeCode: [{ required: true, message: '编码不可为空', trigger: 'blur' }],
  192. scopeName: [{ required: true, message: '名称不可为空', trigger: 'blur' }],
  193. isTop: [{ required: true, message: '请选择是否为顶级分类', trigger: 'change' }],
  194. pid: [{ required: true, message: '请选择上级分类', trigger: 'change' }]
  195. // retention: [{ required: true, message: '请选择保管期限', trigger: 'change' }]
  196. },
  197. permission: {
  198. add: ['admin', 'scope:add'],
  199. edit: ['admin', 'scope:edit'],
  200. del: ['admin', 'scope:del']
  201. },
  202. defaultProps: {
  203. children: 'children',
  204. label: 'cnName'
  205. },
  206. periodOptions: [
  207. {
  208. value: '永久',
  209. label: '永久'
  210. },
  211. {
  212. value: '定期30年',
  213. label: '定期30年'
  214. },
  215. {
  216. value: '定期10年',
  217. label: '定期10年'
  218. }
  219. ]
  220. }
  221. },
  222. computed: {
  223. ...mapGetters([
  224. 'baseApi'
  225. ])
  226. },
  227. watch: {
  228. selectedCategory: function(newValue, oldValue) {
  229. this.crud.refresh()
  230. }
  231. },
  232. created() {
  233. },
  234. methods: {
  235. getRowKey(row) {
  236. return row.id
  237. },
  238. // 获取数据前设置默认参数
  239. [CRUD.HOOK.beforeRefresh]() {
  240. this.tableData = []
  241. this.crud.query.categoryId = this.selectedCategory.id
  242. },
  243. [CRUD.HOOK.afterRefresh](crud) {
  244. crud.data.forEach(function(item, index) {
  245. if (item.sonNum !== 0) {
  246. item.hasChildren = true
  247. item.children = null
  248. } else {
  249. item.hasChildren = false
  250. }
  251. })
  252. this.tableData = this.crud.data
  253. },
  254. // 提交前做的操作
  255. [CRUD.HOOK.afterValidateCU](crud) {
  256. console.log(crud.form)
  257. delete crud.form.isTop
  258. return true
  259. },
  260. changeIsTop(val) {
  261. if (this.crud.status.edit) {
  262. if (val === '1') {
  263. this.form.pid = null
  264. }
  265. }
  266. },
  267. // 新增与编辑前做的操作
  268. [CRUD.HOOK.afterToCU](crud, form) {
  269. this.getCategoryDataTree()
  270. if (this.crud.status.edit) {
  271. this.form.categoryId = this.form.category.id
  272. this.form.archivesClassId = this.form.archivesClass.id
  273. this.getScopeTree(this.form.category.id)
  274. this.getClassifyTree(this.form.category.id)
  275. } else {
  276. this.form.categoryId = null
  277. this.scopes = []
  278. }
  279. if (form.id != null) {
  280. if (form.pid === null) {
  281. form.isTop = '1'
  282. } else {
  283. form.isTop = '0'
  284. }
  285. }
  286. },
  287. selectCategoryTree(val) {
  288. console.log(val)
  289. // this.form.categoryId = val.id
  290. this.getScopeTree(val.id)
  291. this.getClassifyTree(val.id)
  292. },
  293. filterData(data) {
  294. return data.filter(node => {
  295. if (node.children && node.children.length > 0) {
  296. node.children = this.filterData(node.children) // 递归处理子节点
  297. }
  298. return node.isType !== 3 // 过滤掉isType为3的节点
  299. })
  300. },
  301. getCategoryDataTree() {
  302. FetchCategoryMenu().then(res => {
  303. this.categoryDatas = this.filterData(res)
  304. })
  305. },
  306. getClassifyTree(categoryId) {
  307. FetchArchivesClassTree({ 'categoryId': categoryId }).then(res => {
  308. this.classifyOptions = res.map(function(obj) {
  309. if (obj.childArchivesClass !== null) {
  310. obj.hasChildren = true
  311. } else {
  312. obj.hasChildren = false
  313. }
  314. if (obj.hasChildren) {
  315. obj.children = null
  316. }
  317. return obj
  318. })
  319. })
  320. },
  321. // loadClassifyTree({ action, parentNode, callback }) {
  322. // if (action === LOAD_CHILDREN_OPTIONS) {
  323. // FetchArchivesClassTree().then(res => {
  324. // parentNode.children = res.map(function(obj) {
  325. // if (obj.childArchivesClass !== 0) {
  326. // obj.hasChildren = true
  327. // } else {
  328. // obj.hasChildren = false
  329. // }
  330. // if (obj.hasChildren) {
  331. // obj.children = null
  332. // }
  333. // return obj
  334. // })
  335. // setTimeout(() => {
  336. // callback()
  337. // }, 100)
  338. // })
  339. // }
  340. // },
  341. getSonClass(tree, treeNode, resolve) {
  342. setTimeout(() => {
  343. crudScope.FetchSonArchivesScope({ pid: tree.id }).then(res => {
  344. const data = res.map(function(obj) {
  345. if (obj.sonNum !== 0 && obj.sonNum) {
  346. obj.hasChildren = true
  347. obj.children = null
  348. } else {
  349. obj.hasChildren = false
  350. }
  351. return obj
  352. })
  353. resolve(data)
  354. })
  355. }, 100)
  356. },
  357. getScopeTree(categoryId) {
  358. crudScope.FetchArchivesScopeTree({ 'categoryId': categoryId }).then(res => {
  359. this.scopes = res.map(function(obj) {
  360. if (obj.childArchivesClass !== null) {
  361. obj.hasChildren = true
  362. } else {
  363. obj.hasChildren = false
  364. }
  365. if (obj.hasChildren) {
  366. obj.children = null
  367. }
  368. return obj
  369. })
  370. })
  371. },
  372. // 获取弹窗内门类数据
  373. // loadScopeTree({ action, parentNode, callback }) {
  374. // if (action === LOAD_CHILDREN_OPTIONS) {
  375. // crudScope.FetchArchivesScopeTree().then(res => {
  376. // parentNode.children = res.map(function(obj) {
  377. // if (obj.childArchivesClass !== 0) {
  378. // obj.hasChildren = true
  379. // } else {
  380. // obj.hasChildren = false
  381. // }
  382. // if (obj.hasChildren) {
  383. // obj.children = null
  384. // }
  385. // return obj
  386. // })
  387. // setTimeout(() => {
  388. // callback()
  389. // }, 100)
  390. // })
  391. // }
  392. // },
  393. selectAll() {
  394. this.isAllSelect = !this.isAllSelect
  395. const data = this.tableData
  396. this.toggleSelect(data, this.isAllSelect, 'all')
  397. },
  398. // 选择某行
  399. selectTr(selection, row) {
  400. this.$set(row, 'isChecked', !row.isChecked)
  401. this.$nextTick(() => {
  402. this.isAllSelect = row.isChecked
  403. this.toggleSelect(row, row.isChecked, 'tr')
  404. })
  405. },
  406. // 递归子级
  407. toggleSelect(data, flag, type) {
  408. if (type === 'all') {
  409. if (data.length > 0) {
  410. data.forEach((item) => {
  411. this.toggleSelection(item, flag)
  412. if (item.children && item.children.length > 0) {
  413. this.toggleSelect(item.children, flag, type)
  414. }
  415. })
  416. }
  417. } else {
  418. if (data.children && data.children.length > 0) {
  419. data.children.forEach((item) => {
  420. item.isChecked = flag
  421. this.$refs.table.toggleRowSelection(item, flag)
  422. this.toggleSelect(item, flag, type)
  423. })
  424. }
  425. }
  426. },
  427. // 改变选中
  428. toggleSelection(row, flag) {
  429. this.$set(row, 'isChecked', flag)
  430. this.$nextTick(() => {
  431. if (flag) {
  432. this.$refs.table.toggleRowSelection(row, flag)
  433. } else {
  434. this.$refs.table.clearSelection()
  435. }
  436. })
  437. },
  438. // table - 当前选中得row
  439. clickRowHandler(row) {
  440. this.$refs.table.clearSelection()
  441. this.$refs.table.toggleRowSelection(row)
  442. },
  443. selectionChangeHandler(val) {
  444. this.selections = val
  445. },
  446. doExport(data) {
  447. crud.downloadLoading = true
  448. this.$confirm('此操作将导出所选数据' + '<span>你是否还要继续?</span>', '提示', {
  449. confirmButtonText: '继续',
  450. cancelButtonText: '取消',
  451. type: 'warning',
  452. dangerouslyUseHTMLString: true
  453. }).then(() => {
  454. const ids = []
  455. data.forEach(val => {
  456. ids.push(val.id)
  457. })
  458. const params = {
  459. 'classIds': ids
  460. }
  461. exportFile(this.baseApi + '/api/archivesScope/download?' + qs.stringify(params, { indices: false }))
  462. }).catch(() => {
  463. })
  464. },
  465. toDelete(datas) {
  466. this.$confirm('此操作将删除当前所选' + this.crud.title + '<span>你是否还要继续?</span>', '提示', {
  467. confirmButtonText: '继续',
  468. cancelButtonText: '取消',
  469. type: 'warning',
  470. dangerouslyUseHTMLString: true
  471. }).then(() => {
  472. this.crud.delAllLoading = true
  473. const ids = []
  474. datas.forEach(val => {
  475. ids.push(val.id)
  476. })
  477. // const params = {
  478. // 'scopeIds': ids
  479. // }
  480. crudScope.del(ids).then(() => {
  481. this.crud.notify('删除成功', CRUD.NOTIFICATION_TYPE.SUCCESS)
  482. this.crud.delAllLoading = false
  483. this.crud.refresh()
  484. }).catch(err => {
  485. this.crud.delAllLoading = false
  486. console.log(err)
  487. })
  488. }).catch(() => {
  489. })
  490. },
  491. normalizer(node) {
  492. if (node.children && !node.children.length) {
  493. delete node.children
  494. }
  495. return {
  496. id: node.id,
  497. label: node.cnName,
  498. children: node.children,
  499. isDisabled: node.isType !== 2
  500. }
  501. },
  502. classifyNormalizer(node) {
  503. if (node.childArchivesClass && !node.childArchivesClass.length) {
  504. delete node.childArchivesClass
  505. }
  506. return {
  507. id: node.id,
  508. label: node.name,
  509. children: node.childArchivesClass
  510. }
  511. },
  512. scopeNormalizer(node) {
  513. if (node.archivesScopeDTOs && !node.archivesScopeDTOs.length) {
  514. delete node.archivesScopeDTOs
  515. }
  516. return {
  517. id: node.id,
  518. label: node.scopeName,
  519. children: node.archivesScopeDTOs
  520. }
  521. }
  522. }
  523. }
  524. </script>
  525. <style lang="scss" scoped>
  526. .tip{
  527. line-height: 28px;
  528. }
  529. </style>