data-rule-manage.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. <template>
  2. <div :class="[$style.wrapHeight, $style.dataclass]">
  3. <div :class="$style.rowHeight">
  4. <audit-class-tree
  5. ref="auditMaintainCatalogTree"
  6. show-line
  7. top-node-text="数据分类"
  8. :is-select-dep="true"
  9. :draggable="true"
  10. :cate="true"
  11. :tree-data="categoryTreeSearched"
  12. :replace-fields="{ title: 'categoryName', key: 'id' }"
  13. v-bind="{ checkable: true, checkStrictly: true }"
  14. style="width: 20%"
  15. @treeSelect="treeSelect"
  16. @onChangeSearch="onCategorySearch"
  17. @onCheck="onCategoryCheck"
  18. >
  19. <div style="display: flex;justify-content: space-between">
  20. <a-button type="primary" @click="onCategoryAdd">新建分类</a-button>
  21. <a-button type="primary" :disabled="!nowCategory" @click="onCategoryEdit">编辑</a-button>
  22. <a-popconfirm
  23. title="确定删除此分类吗?"
  24. ok-text="确定"
  25. cancel-text="取消"
  26. @confirm="onCategoryDel"
  27. @cancel="showCategory = false"
  28. >
  29. <a-button :disabled="!nowCategory">删除</a-button>
  30. </a-popconfirm>
  31. <!-- <a-button @click="some">测试</a-button>-->
  32. </div>
  33. </audit-class-tree>
  34. <div :class="$style.rightcard">
  35. <a-card>
  36. <!-- page-id="audit/datacube/iamServerInfo" -->
  37. <SdDataTableEx
  38. ref="dataTable"
  39. :projectlist="true"
  40. form-id="iamServerInfo"
  41. :columns="columns"
  42. :actions="actions"
  43. data-url="api/xcoa-mobile/v1/server-info/serverList"
  44. :filter-expressions="expressions"
  45. :search-fields="['tableNameCN', 'tableNameEN']"
  46. >
  47. <template slot="operation" slot-scope="text, record">
  48. <a-button type="link" @click="tableEdit(record)">编辑</a-button>
  49. <a-button type="link" @click="tableDel(record)">删除</a-button>
  50. </template>
  51. </SdDataTableEx>
  52. </a-card>
  53. </div>
  54. </div>
  55. <a-modal v-model="showCategory" @ok="onCategorySave">
  56. <a-form-model
  57. ref="categoryForm"
  58. :model="categoryForm"
  59. :rules="categoryRules"
  60. :label-col="{ span: 5 }"
  61. :wrapper-col="{ span: 19 }"
  62. >
  63. <a-form-model-item label="父级分类">
  64. <a-cascader
  65. v-model="parentId"
  66. :disabled="isType === 'exit'"
  67. :options="categoryOptions"
  68. :change-on-select="true"
  69. placeholder="请选择"
  70. :field-names="{ label: 'categoryName', value: 'id', children: 'children' }"
  71. />
  72. </a-form-model-item>
  73. <a-form-model-item label="分类名称" prop="categoryName">
  74. <a-input v-model="categoryForm.categoryName"></a-input>
  75. </a-form-model-item>
  76. <a-form-model-item label="分类类型">
  77. <a-select v-model="categoryForm.classifyType">
  78. <a-select-option value="1">宽表类型</a-select-option>
  79. <a-select-option value="2">财务报表非结构化</a-select-option>
  80. </a-select>
  81. </a-form-model-item>
  82. <a-form-model-item label="分类描述">
  83. <a-input v-model="categoryForm.categoryDesc"></a-input>
  84. </a-form-model-item>
  85. <a-form-model-item label="分类排序" prop="sortNum">
  86. <a-input-number v-model="categoryForm.sortNum"></a-input-number>
  87. </a-form-model-item>
  88. </a-form-model>
  89. </a-modal>
  90. <a-modal v-model="showTable" @ok="tableEditConfirm">
  91. <a-form-model
  92. ref="tableForm"
  93. :model="tableForm"
  94. :rules="tableRules"
  95. :label-col="{ span: 6 }"
  96. :wrapper-col="{ span: 16 }"
  97. >
  98. <a-form-model-item label="服务器ip" prop="ip">
  99. <a-input v-model="tableForm.ip"></a-input>
  100. </a-form-model-item>
  101. <a-form-model-item label="账号" prop="account">
  102. <a-input v-model="tableForm.account" autocomplete="new-user"></a-input>
  103. </a-form-model-item>
  104. <a-form-model-item label="密码" prop="pass">
  105. <a-input-password v-model="tableForm.pass" autocomplete="new-password"></a-input-password>
  106. </a-form-model-item>
  107. <a-form-model-item label="表中文名" prop="tableNameCN">
  108. <a-input v-model="tableForm.tableNameCN"></a-input>
  109. </a-form-model-item>
  110. <a-form-model-item label="表英文名" prop="tableNameEN">
  111. <a-input v-model="tableForm.tableNameEN"></a-input>
  112. </a-form-model-item>
  113. <a-form-model-item label="数据库名称" prop="databaseName">
  114. <a-input v-model="tableForm.databaseName"></a-input>
  115. </a-form-model-item>
  116. <a-form-model-item label="端口号" prop="port">
  117. <a-input v-model="tableForm.port"></a-input>
  118. </a-form-model-item>
  119. <a-form-model-item label="数据库schema" prop="schemaName">
  120. <a-input v-model="tableForm.schemaName"></a-input>
  121. </a-form-model-item>
  122. <!-- 序号 -->
  123. <a-form-model-item label="序号">
  124. <a-input-number v-model="tableForm.sortNum" :min="0"></a-input-number>
  125. </a-form-model-item>
  126. </a-form-model>
  127. </a-modal>
  128. </div>
  129. </template>
  130. <script>
  131. import { Modal, message } from 'ant-design-vue'
  132. import auditClassTree from './audit-class-tree.vue'
  133. import auditAdvancedQueryMixins from '../../components/audit-advanced-query-mixins'
  134. import auditAdvancedGroupMixins from '../../components/audit-advanced-group-mixins'
  135. import SdDataTableEx from '@/common/components/sd-data-table-ex.vue'
  136. import TableActionTypes from '@/common/services/table-action-types'
  137. import apis from './data-market'
  138. import { generateTree, getTreeIds } from '@product/iam/audit/dataMarket/util'
  139. import axios from '@/common/services/axios-instance'
  140. export default {
  141. name: 'DataRuleManage',
  142. metaInfo: {
  143. title: '数据权限管理',
  144. },
  145. components: {
  146. SdDataTableEx,
  147. auditClassTree,
  148. },
  149. mixins: [auditAdvancedQueryMixins, auditAdvancedGroupMixins],
  150. data() {
  151. return {
  152. columns: [
  153. { dataIndex: 'classifyId', sdHidden: true },
  154. { dataIndex: 'classifyName', sdHidden: true },
  155. { dataIndex: 'ip', sdHidden: true },
  156. { dataIndex: 'account', sdHidden: true },
  157. { dataIndex: 'pass', sdHidden: true },
  158. { title: '表中文名', dataIndex: 'tableNameCN' },
  159. { title: '表英文名', dataIndex: 'tableNameEN' },
  160. // 序号
  161. { title: '序号', dataIndex: 'sortNum' },
  162. { dataIndex: 'databaseName', sdHidden: true },
  163. { dataIndex: 'port', sdHidden: true },
  164. { dataIndex: 'schemaName', sdHidden: true },
  165. {
  166. title: '操作',
  167. scopedSlots: { customRender: 'operation' },
  168. },
  169. ],
  170. actions: [
  171. {
  172. label: '新建数据表',
  173. permission: null,
  174. type: TableActionTypes.primary,
  175. callback: this.tableAdd,
  176. },
  177. {
  178. label: '数据授权',
  179. permission: null,
  180. callback: this.categoryAuth,
  181. },
  182. {
  183. label: '删除',
  184. permission: null,
  185. type: TableActionTypes.ex.delete,
  186. },
  187. ],
  188. expressions: [
  189. {
  190. dataType: 'long',
  191. name: 'classifyId',
  192. op: 'eq',
  193. longValue: 0,
  194. },
  195. ],
  196. isroot: true,
  197. className: '',
  198. categoryTree: [],
  199. categoryTreeSearched: [],
  200. categoryForm: {},
  201. nowCategory: null,
  202. showCategory: false,
  203. categoryRules: {
  204. categoryName: [{ required: true, message: '请输入分类名称', trigger: 'blur' }],
  205. sortNum: [{ required: true, message: '请输入分类排序', trigger: 'blur' }],
  206. },
  207. tableRules: {
  208. ip: [{ required: true, message: '请输入ip地址', trigger: 'blur' }],
  209. account: [{ required: true, message: '请输入数据表账号', trigger: 'blur' }],
  210. pass: [{ required: true, message: '请输入数据表密码', trigger: 'blur' }],
  211. tableNameCN: [{ required: true, message: '请输入表中文名', trigger: 'blur' }],
  212. tableNameEN: [{ required: true, message: '请输入表英文名', trigger: 'blur' }],
  213. databaseName: [{ required: true, message: '请输入数据库名称', trigger: 'blur' }],
  214. port: [{ required: true, message: '请输入端口号', trigger: 'blur' }],
  215. schemaName: [{ required: true, message: '请输入schema', trigger: 'blur' }],
  216. },
  217. categoryChecked: [],
  218. tableForm: {},
  219. showTable: false,
  220. parentId: [],
  221. isType: '',
  222. }
  223. },
  224. computed: {
  225. categoryOptions() {
  226. return [{ categoryName: '顶级分类', id: 0, children: this.categoryTree }]
  227. },
  228. },
  229. created() {
  230. this.getCategory()
  231. },
  232. methods: {
  233. tableAdd() {
  234. if (!this.nowCategory) {
  235. Modal.warning({ title: '提示', content: '请先选择分类' })
  236. return
  237. }
  238. if (this.nowCategory.classifyType === '2') {
  239. Modal.warning({ title: '提示', content: '此类型的分类不支持添加数据表' })
  240. return
  241. }
  242. this.tableForm = {
  243. classifyId: this.nowCategory.id,
  244. classifyName: this.nowCategory.categoryName,
  245. ip: '',
  246. account: '',
  247. pass: '',
  248. tableNameCN: '',
  249. tableNameEN: '',
  250. databaseName: '',
  251. port: '',
  252. schemaName: '',
  253. sortNum: 0,
  254. }
  255. this.showTable = true
  256. },
  257. tableEdit(table) {
  258. this.tableForm = { ...table }
  259. this.showTable = true
  260. },
  261. tableEditConfirm() {
  262. this.$refs.tableForm.validate((valid) => {
  263. if (valid) {
  264. // const data = {
  265. // pageFlowId: '08ecc6f9-ed1d-4559-98ea-76a0e9661d6a',
  266. // pagePath: 'audit/datacube/iamServerInfo',
  267. // eventId: 'save',
  268. // inputs: Object.entries(this.tableForm).map(([k, v]) => ({ name: k, value: v })),
  269. // }
  270. // if (this.tableForm.id) data.eventId = 'update'
  271. apis.saveDataTable(this.tableForm).then((res) => {
  272. message.success('保存成功')
  273. this.refresh()
  274. this.showTable = false
  275. })
  276. } else {
  277. return false
  278. }
  279. })
  280. },
  281. tableDel(table) {
  282. const that = this
  283. Modal.confirm({
  284. title: '提示',
  285. content: '是否删除此项?',
  286. onOk() {
  287. return new Promise((resolve, reject) => {
  288. axios
  289. .delete('api/xcoa-mobile/v1/iam-page/iamServerInfo', { params: { ids: table.id } })
  290. .then((res) => {
  291. message.success('已删除')
  292. that.refresh()
  293. resolve()
  294. })
  295. })
  296. },
  297. })
  298. },
  299. onCategoryCheck({ checked }) {
  300. this.categoryChecked = [...checked]
  301. },
  302. onCategoryAdd() {
  303. this.parentId = []
  304. this.categoryForm = {
  305. parentId: [],
  306. classifyType: '1',
  307. categoryName: '',
  308. categoryDesc: '',
  309. sortNum: 0,
  310. }
  311. this.showCategory = true
  312. this.isType = 'add'
  313. },
  314. onCategoryEdit() {
  315. const { id, parentId, categoryName, classifyType, categoryDesc, sortNum } = this.nowCategory
  316. const ids = [0, ...getTreeIds(this.categoryTree, id)]
  317. this.parentId = ids
  318. this.categoryForm = {
  319. id,
  320. parentId: ids,
  321. categoryName,
  322. classifyType,
  323. categoryDesc,
  324. sortNum,
  325. }
  326. this.showCategory = true
  327. this.isType = 'exit'
  328. },
  329. onCategoryDel() {
  330. apis.categoryDel({ ids: this.nowCategory.id }).finally(() => {
  331. this.nowCategory = null
  332. this.getCategory()
  333. })
  334. },
  335. onCategorySave() {
  336. if (this.parentId.length === 0) {
  337. return message.error('请选择父级分类')
  338. }
  339. this.$refs.categoryForm.validate((valid) => {
  340. if (valid) {
  341. if (this.isType === 'add') {
  342. if (this.parentId.length >= 2) {
  343. this.categoryForm.parentId = this.parentId[this.parentId.length - 1]
  344. } else {
  345. this.categoryForm.parentId = 0
  346. }
  347. } else {
  348. if (this.parentId.length >= 2) {
  349. this.categoryForm.parentId = this.parentId[this.parentId.length - 2]
  350. } else {
  351. this.categoryForm.parentId = 0
  352. }
  353. }
  354. const data = {
  355. pageFlowId: '08ecc6f9-ed1d-4559-98ea-76a0e9661d6a',
  356. pagePath: 'audit/datacube/iamDataCube',
  357. eventId: 'save',
  358. inputs: Object.entries(this.categoryForm).map(([k, v]) => ({ name: k, value: v })),
  359. }
  360. // console.log(data)
  361. apis.setShareStatus(data).then((res) => {
  362. message.success('保存成功')
  363. this.getCategory()
  364. this.showCategory = false
  365. })
  366. } else {
  367. return false
  368. }
  369. })
  370. },
  371. // 搜索分类
  372. onCategorySearch(val) {
  373. this.categoryTreeSearched = this.categoryFilter(this.categoryTree, val)
  374. },
  375. categoryFilter(list, val) {
  376. const res = list.filter((i) => i.categoryName.includes(val))
  377. res.forEach((item) => {
  378. if (item.children && item.children.length) {
  379. item.children = this.categoryFilter(item.children, val)
  380. }
  381. })
  382. return res
  383. },
  384. getCategory() {
  385. apis.categoryListWhole().then((res) => {
  386. this.categoryTree = generateTree(res.data, 'id', 'parentId', 'children')
  387. this.onCategorySearch('')
  388. })
  389. },
  390. treeSelect(selectedKeys, info) {
  391. const nowNode = info.selectedNodes[0]
  392. if (nowNode) {
  393. this.nowCategory = nowNode.data.props
  394. this.expressions = [
  395. {
  396. dataType: 'long',
  397. name: 'classifyId',
  398. op: 'eq',
  399. longValue: this.nowCategory.id,
  400. },
  401. ]
  402. } else {
  403. this.nowCategory = null
  404. }
  405. },
  406. refresh() {
  407. this.$refs.dataTable.refresh()
  408. },
  409. tableAuth() {
  410. const tableIds = this.$refs.dataTable.getSelectedRowKeys()
  411. if (tableIds.length) {
  412. const url = '#/data-rule-apply?selectid=' + tableIds.join(',') // 新页面要打开的路由地址
  413. // 新页面要打开的路由地址
  414. window.open(url, '_blank')
  415. } else {
  416. Modal.warning({ title: '提示', content: '请选择数据表!' })
  417. }
  418. },
  419. categoryAuth() {
  420. if (this.categoryChecked.length) {
  421. const url = '#/data-rule-apply?classid=' + this.categoryChecked.join(',') // 新页面要打开的路由地址
  422. // 新页面要打开的路由地址
  423. window.open(url, '_blank')
  424. } else {
  425. Modal.warning({ title: '提示', content: '请选择数据分类!' })
  426. }
  427. },
  428. },
  429. }
  430. </script>
  431. <style module lang="scss">
  432. @use '@/common/design' as *;
  433. .wrap-height {
  434. height: 100%;
  435. .row-height {
  436. display: flex;
  437. flex: auto;
  438. height: 100%;
  439. .rightcard {
  440. flex: 1;
  441. width: calc(100% - 20%);
  442. height: 100%;
  443. }
  444. }
  445. }
  446. .dataclass {
  447. :global(.projectlist .ant-table-empty .ant-table-body) {
  448. overflow-x: hidden !important;
  449. }
  450. :global(span > .ant-btn:nth-child(2)) {
  451. color: #fff;
  452. background-color: #1890ff;
  453. border-color: #1890ff;
  454. }
  455. // :global(.ant-table-placeholder) {
  456. // width: auto;
  457. // }
  458. }
  459. </style>