register.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. <template>
  2. <a-card size="small" :bordered="false">
  3. <a-row :gutter="24">
  4. <!-- 左侧菜单树列表 -->
  5. <a-col :span="8">
  6. <a-row :gutter="24" class="textCount">
  7. <a-icon type="info-circle" style="color: #1890FF;margin-right: 10px;" />
  8. <span>当前选择:<span style="color: #40a9ff;font-weight: 600;">{{ selectedMenu }}</span><span v-if="selectedKeys.length" class="imgSize" @click="cancelSel">取消选择</span></span>
  9. </a-row>
  10. <a-row :gutter="24" >
  11. <a-row :gutter="24" >
  12. <a-input-search placeholder="搜索" style="width: 100%" @change="onChange" />
  13. </a-row>
  14. <a-tree
  15. @expand="onExpand"
  16. :treeData="getMenus"
  17. :expandedKeys="expandedKeys"
  18. :autoExpandParent="autoExpandParent"
  19. @select="onSelect"
  20. :selectedKeys="selectedKeys"
  21. >
  22. <template slot="title" slot-scope="{title}">
  23. <span v-if="title.indexOf(searchValue) > -1">
  24. {{ title.substr(0, title.indexOf(searchValue)) }}
  25. <span style="color: #f50">{{ searchValue }}</span>
  26. {{ title.substr(title.indexOf(searchValue) + searchValue.length) }}
  27. </span>
  28. <span v-else>{{ title }}</span>
  29. </template>
  30. </a-tree>
  31. </a-row>
  32. </a-col>
  33. <!-- 右侧 -->
  34. <a-col :span="16" >
  35. <a-form :form="form" @submit="handleSubmit">
  36. <a-form-item label=" " :colon="false" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
  37. <a-button style="margin-right: 10px;" type="primary" icon="plus" @click="addChild">添加子分类</a-button>
  38. <a-button style="margin-right: 10px;background-color: #19be6b;color: #fff;" type="" icon="plus" @click="addTop">添加根节点</a-button>
  39. <a-button style="margin-right: 10px;background-color: red;color: #fff;" type="" icon="delete" @click="remove()">删除</a-button>
  40. </a-form-item>
  41. <!-- 父路径 -->
  42. <a-form-item label="父路径" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
  43. <a-input
  44. disabled
  45. placeholder=""
  46. v-decorator="['formData.parentPath', {
  47. initialValue: formData.parentPath,
  48. rules: [] }]"
  49. />
  50. </a-form-item>
  51. <!-- 显示名称-->
  52. <a-form-item label="显示名称" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
  53. <a-input
  54. placeholder="请输入节点显示名称(最多30个字符)"
  55. :maxLength="30"
  56. v-decorator="['formData.dispname', {
  57. initialValue: formData.dispname,
  58. rules: [{ required: true, message: '请输入节点显示名称!' }] }]"
  59. />
  60. </a-form-item>
  61. <!-- 名称 -->
  62. <a-form-item label="编码" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
  63. <a-input
  64. placeholder="请输入节点code"
  65. v-decorator="['formData.name', {
  66. initialValue: formData.name,
  67. rules: [{ required: true, message: '请输入节点code!' }] }]"
  68. />
  69. </a-form-item>
  70. <!-- 值 -->
  71. <a-form-item label="值" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
  72. <a-input
  73. :maxlength="20"
  74. placeholder="请输入节点值"
  75. v-decorator="['formData.value', {
  76. initialValue: formData.value,
  77. rules: [{ required: true, message: '请输入节点值!' }] }]"
  78. />
  79. </a-form-item>
  80. <!-- 排序值 -->
  81. <a-form-item label="排序" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
  82. <a-input-number
  83. style="width: 100%;"
  84. placeholder="请输入排序值(0~999999)"
  85. v-decorator="['formData.index', {
  86. initialValue: formData.index,
  87. rules: [{ required: true, message: '请输入排序值!' }] }]"
  88. :max="999999"
  89. :min="0"
  90. />
  91. </a-form-item>
  92. <!-- 状态 -->
  93. <a-form-item label="是否启用" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
  94. <a-radio-group
  95. name="radioGroup"
  96. v-decorator="[
  97. 'formData.isEnable',
  98. {
  99. initialValue: formData.isEnable,
  100. rules: [{ required: true, message: '请选择状态!' }] },
  101. ]"
  102. >
  103. <a-radio :value="1">是</a-radio>
  104. <a-radio :value="0">否</a-radio>
  105. </a-radio-group>
  106. </a-form-item>
  107. <a-form-item label="备注" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
  108. <a-textarea
  109. v-decorator="[
  110. 'formData.desc',
  111. { initialValue: formData.desc,
  112. rules: [] },
  113. ]"
  114. :maxLength="500"
  115. style="min-height: 60px;"
  116. placeholder="最多500字符"
  117. autosize />
  118. </a-form-item>
  119. <a-form-item :wrapper-col="{ span: 12, offset: 5 }">
  120. <a-button type="primary" @click="handleSubmit()">
  121. 保存
  122. </a-button>
  123. <a-button :style="{ marginLeft: '8px' }" @click="reset">
  124. 重置
  125. </a-button>
  126. </a-form-item>
  127. </a-form>
  128. </a-col>
  129. </a-row>
  130. </a-card>
  131. </template>
  132. <script>
  133. import { STable, VSelect } from '@/components'
  134. import { listRegister, saveRegister, delRegisterNode } from '@/api/register'
  135. import _ from 'lodash'
  136. export default {
  137. name: 'Menu',
  138. components: {
  139. STable, VSelect
  140. },
  141. props: {},
  142. data () {
  143. return {
  144. treeData: [],
  145. dataList: [],
  146. searchValue: '',
  147. actions: 'addTop', // addTop:添加一级分类,addChild:添加子分类,edit
  148. expandedKeys: [],
  149. autoExpandParent: true,
  150. selectedKeys: [],
  151. selectedData: {}, // 被选中的节点数据
  152. selectedMenu: '', // 选择的树节点名
  153. formLayout: 'horizontal',
  154. form: this.$form.createForm(this, { name: 'register' }),
  155. parentData: {}, // 父级菜单
  156. formData: {},
  157. formDataBack: {
  158. id: '',
  159. dispname: '',
  160. name: '',
  161. value: '',
  162. index: '',
  163. parentPath: '',
  164. isEnable: '',
  165. desc: '',
  166. parentId: '0'
  167. }
  168. }
  169. },
  170. computed: {
  171. getMenus () {
  172. this.generateList(this.treeData)
  173. return this.treeData
  174. }
  175. },
  176. methods: {
  177. initPage () {
  178. this.addTop()
  179. this.initTree()
  180. },
  181. onExpand (expandedKeys) {
  182. console.log('onExpand', expandedKeys)
  183. this.expandedKeys = expandedKeys
  184. this.autoExpandParent = false
  185. },
  186. onSelect (selectedKeys, info) {
  187. console.log('onSelect', info)
  188. this.selectedKeys = selectedKeys
  189. if (info.selected) {
  190. this.selectedData = info
  191. const data = info.selectedNodes[0].data.props
  192. this.selectedMenu = data.dispname
  193. this.formData = {
  194. id: data.id,
  195. dispname: data.dispname,
  196. name: data.name,
  197. value: data.value,
  198. index: data.index,
  199. parentPath: data.parentPath,
  200. isEnable: data.isEnable,
  201. desc: data.desc,
  202. parentId: data.parentId
  203. }
  204. this.formData.isEnable = Number(this.formData.isEnable)
  205. this.actions = 'edit'
  206. } else {
  207. this.selectedMenu = ''
  208. this.clear()
  209. }
  210. },
  211. generateList (data) {
  212. for (let i = 0; i < data.length; i++) {
  213. const node = data[i]
  214. node.key = node.id
  215. node.title = node.dispname
  216. const key = node.title
  217. this.dataList.push({ key, title: key })
  218. node.scopedSlots = { title: 'title' }
  219. // node.slots = { icon: node.type == '0' ? 'file' : 'pushpin' }
  220. if (node.children) {
  221. this.generateList(node.children)
  222. }
  223. }
  224. },
  225. getParentKey (key, tree) {
  226. let parentKey
  227. for (let i = 0; i < tree.length; i++) {
  228. const node = tree[i]
  229. if (node.children) {
  230. if (node.children.some(item => item.title == key)) {
  231. parentKey = node.key
  232. } else if (this.getParentKey(key, node.children)) {
  233. parentKey = this.getParentKey(key, node.children)
  234. }
  235. }
  236. }
  237. return parentKey
  238. },
  239. onChange (e) {
  240. const value = e.target.value
  241. const expandedKeys = this.dataList
  242. .map(item => {
  243. if (item.title.indexOf(value) > -1) {
  244. return this.getParentKey(item.title, this.treeData)
  245. }
  246. return null
  247. })
  248. .filter((item, i, self) => item && self.indexOf(item) === i)
  249. Object.assign(this, {
  250. expandedKeys,
  251. searchValue: value,
  252. autoExpandParent: true
  253. })
  254. },
  255. // 初始化 查询Tree 数据
  256. initTree () {
  257. const _this = this
  258. listRegister().then(res => {
  259. if (res.status === '200') {
  260. const treeData = res.data
  261. if (treeData) {
  262. _this.treeData = treeData
  263. }
  264. } else {
  265. this.$Message.warning(res.message)
  266. }
  267. })
  268. },
  269. // 添加根节点
  270. addTop () {
  271. this.clear()
  272. this.actions = 'addTop'
  273. this.formData = _.cloneDeep(this.formDataBack)
  274. },
  275. // 添加子节点
  276. addChild () {
  277. if (!this.selectedKeys.length) {
  278. this.$message.warning('请先选择一个根节点')
  279. }
  280. this.actions = 'addChild'
  281. const currentNode = this.selectedData.selectedNodes[0].data.props
  282. this.formData = _.cloneDeep(this.formDataBack)
  283. this.formData.parentId = currentNode.id
  284. if (currentNode.parentId === 0) {
  285. this.formData.parentPath = currentNode.dispname
  286. } else {
  287. this.formData.parentPath = currentNode.parentPath + ' > ' + currentNode.dispname
  288. }
  289. },
  290. // 取消选择
  291. cancelSel () {
  292. this.selectedKeys = []
  293. this.selectedMenu = ''
  294. this.clear()
  295. },
  296. reset () {
  297. if (this.actions != 'addTop') {
  298. const data = {
  299. id: this.formData.id,
  300. parentId: this.formData.parentId,
  301. parentPath: this.formData.parentPath
  302. }
  303. console.log(data, 'data')
  304. this.formData = _.cloneDeep(this.formDataBack)
  305. this.formData.id = data.id
  306. this.formData.parentId = data.parentId
  307. this.formData.parentPath = data.parentPath
  308. }
  309. this.cancelSel()
  310. },
  311. // 清空列表
  312. clear () {
  313. this.form.resetFields()
  314. this.formData = _.cloneDeep(this.formDataBack)
  315. },
  316. // 删除数据
  317. remove () {
  318. if (!this.selectedKeys.length) {
  319. return this.$message.warning('您还未选择要删除的数据')
  320. }
  321. if (this.selectedData.node.$children.length) {
  322. return this.$message.warning('请先删除子节点')
  323. }
  324. const _this = this
  325. console.log(_this.formData.id, '_this.formData.id')
  326. this.$confirm({
  327. title: '警告',
  328. content: `确定要删除您选择的 ${_this.formData.dispname} 的数据吗?`,
  329. centered: true,
  330. onOk () {
  331. delRegisterNode({
  332. id: _this.formData.id
  333. }).then(res => {
  334. if (res.status == 200) {
  335. _this.$message.success('删除成功')
  336. _this.cancelSel()
  337. _this.initTree()
  338. }
  339. }).catch(() => {
  340. _this.$message.success('删除失败, 请稍后重试')
  341. })
  342. }
  343. })
  344. },
  345. // 保存提交
  346. handleSubmit () {
  347. const _this = this
  348. this.form.validateFields((err, values) => {
  349. if (!err) {
  350. console.log(values.formData, ' formData.type222222222')
  351. let params = {}
  352. if (this.actions === 'addTop') {
  353. params = Object.assign({}, values.formData)
  354. } else {
  355. params = Object.assign(_this.formData, values.formData)
  356. }
  357. saveRegister(params).then(res => {
  358. if (res.status + '' === '200') {
  359. _this.initTree()
  360. _this.cancelSel()
  361. this.$message.success(res.message ? res.message : '保存成功')
  362. } else {
  363. // this.$message.error(res.message ? res.message : '保存失败')
  364. }
  365. })
  366. }
  367. })
  368. }
  369. },
  370. mounted () {
  371. // this.initTree()
  372. },
  373. beforeCreate () {
  374. this.form = this.$form.createForm(this, { name: 'register' })
  375. },
  376. beforeRouteEnter (to, from, next) {
  377. next(vm => {
  378. vm.initPage()
  379. })
  380. },
  381. watch: {
  382. }
  383. }
  384. </script>
  385. <style>
  386. .menu-box::-webkit-scrollbar{
  387. width: 6px;
  388. height: 6px ;
  389. }
  390. .menu-box::-webkit-scrollbar-thumb{
  391. width: 6px;
  392. height: 6px ;
  393. border-radius: 4px;
  394. -webkit-box-shadow: inset 0 0 2px #d1d1d1;
  395. background: #e4e4e4;
  396. }
  397. .textCount{
  398. border: 1px solid #91d5ff;
  399. background-color: #e6f7ff;
  400. border-radius: 5px;
  401. padding: 5px 10px 5px 20px;
  402. margin: 10px 0;
  403. color: rgba(0, 0, 0);
  404. }
  405. .imgSize{
  406. color: #2d8cf0;
  407. margin-left: 10px;
  408. font-size: 14px;
  409. }
  410. </style>