阅行客电子档案
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.

531 lines
17 KiB

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