functionMain.vue 77 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893
  1. <template>
  2. <div class="functionDiv">
  3. <div class="MainLeft">
  4. <div class="public-function-div">导航树
  5. <el-button
  6. @click="setCheckedNodes"
  7. size="small"
  8. class="refresh"
  9. >展开</el-button>
  10. <el-button
  11. @click="setCheckedKeys"
  12. size="small"
  13. class="refresh2"
  14. >收起</el-button>
  15. <el-button
  16. type="primary"
  17. @click="handleReset('formItem')"
  18. size="small"
  19. class="refresh3"
  20. v-privilege="activeMenu + 'ADD'"
  21. >新增顶级菜单</el-button>
  22. </div>
  23. <el-input
  24. placeholder="输入关键字进行过滤"
  25. class="filterTree"
  26. v-model="filterText"
  27. >
  28. </el-input>
  29. <el-tree
  30. ref="menuTree"
  31. :data="menuTree"
  32. :props="defaultProps"
  33. node-key="id"
  34. :default-expanded-keys="expandedKeys"
  35. draggable
  36. v-loading='treeLoading'
  37. @node-expand="expandNode"
  38. @node-collapse="expandCollapse"
  39. @node-drag-start="handleDragStart"
  40. @node-drag-end="handleDragEnd"
  41. :expand-on-click-node="true"
  42. @node-click="nodeClick"
  43. :style="{height: treeHeight + 'px'}"
  44. :filter-node-method="filterOrgTree"
  45. >
  46. <span class="fun-st-ellipsis" style="position: relative; width: 100%; font-size: 14px;" slot-scope="{ node, data }">
  47. <span :style="(data.status === '0' || node.parent.data.status === '0') ? 'color: #a09e9e;' : ''">{{ node.label }}</span>
  48. <span style="position: absolute; right: 0px;">
  49. <i v-if="data.menuType === '1'" class='el-icon-plus xl-icon-size addMenuPr' @click.stop="addTreeNode(node, data)"></i>
  50. <i class='el-icon-delete xl-icon-size delMenuPr' @click.stop="delTreeNode(node, data)"></i>
  51. </span>
  52. </span>
  53. </el-tree>
  54. </div>
  55. <div class="MainRight">
  56. <el-button
  57. type="primary"
  58. @click="menuExport"
  59. size="small"
  60. class="exportButton"
  61. v-privilege="activeMenu + 'EXPORT'"
  62. >导出</el-button>
  63. <el-tabs v-model="activeName">
  64. <el-tab-pane
  65. label="编辑区"
  66. name="editForm"
  67. >
  68. <el-form
  69. ref="formItem"
  70. :model="formItem"
  71. :rules="ruleValidate_formItem"
  72. label-width="80px"
  73. class="FormMain"
  74. >
  75. <el-row>
  76. <el-col :span="24">
  77. <el-form-item
  78. label="父菜单"
  79. prop="pName"
  80. >
  81. <el-input
  82. v-model="formItem.pName"
  83. disabled
  84. size="small"
  85. style="vertical-align:top;"
  86. >
  87. </el-input>
  88. </el-form-item>
  89. </el-col>
  90. <el-col :span="12">
  91. <el-form-item label="功能类型">
  92. <el-select
  93. v-model="formItem.menuType"
  94. prop="menuType"
  95. style="width: 100%;"
  96. @change="changeType"
  97. size="small"
  98. >
  99. <el-option
  100. v-for="item in formItem_type_data"
  101. :value="item.value"
  102. :key="item.value"
  103. :label="item.label"
  104. ></el-option>
  105. </el-select>
  106. </el-form-item>
  107. </el-col>
  108. <el-col :span="12">
  109. <el-form-item
  110. label="状态"
  111. prop="status"
  112. >
  113. <el-select
  114. v-model="formItem.status"
  115. prop="menuType"
  116. style="width: 100%;"
  117. size="small"
  118. >
  119. <el-option
  120. v-for="item in menuStatus"
  121. :value="item.value"
  122. :key="item.value"
  123. :label="item.label"
  124. ></el-option>
  125. </el-select>
  126. </el-form-item>
  127. </el-col>
  128. <!-- <el-col :span="12">
  129. <el-form-item label="名称"
  130. prop="menuName">
  131. <el-input v-model="formItem.menuName"
  132. placeholder="请输入"
  133. size="small"></el-input>
  134. </el-form-item>
  135. </el-col> -->
  136. <el-col :span="12">
  137. <el-form-item
  138. label="菜单名称"
  139. prop="menuLabel"
  140. >
  141. <el-input
  142. v-model="formItem.menuLabel"
  143. placeholder="请输入"
  144. size="small"
  145. ></el-input>
  146. </el-form-item>
  147. </el-col>
  148. <el-col :span="12">
  149. <el-form-item
  150. label="菜单图标"
  151. v-if="formItem.menuType === '1' && !formItem.pId"
  152. prop="menuIcon"
  153. >
  154. <!-- <el-input v-model="formItem.menuIcon"
  155. placeholder="请输入"
  156. size="small"></el-input> -->
  157. <el-select
  158. v-model="formItem.menuIcon"
  159. placeholder="请选择"
  160. size="small"
  161. >
  162. <el-option
  163. v-for="item in icons"
  164. :key="item.icon"
  165. :label="item.value"
  166. :value="item.value"
  167. >
  168. <span style="float: left;"><i
  169. class="xs-menu-icons"
  170. :class="item.value"
  171. ></i></span>
  172. <span style="float: left; margin-left:20px;">{{ item.value }}</span>
  173. </el-option>
  174. </el-select>
  175. </el-form-item>
  176. </el-col>
  177. <!--
  178. <el-col :span="12">
  179. <el-form-item label="控件编号"
  180. prop="privilege">
  181. <el-input v-model="formItem.privilege"
  182. :disabled="Number(formItem.menuType) !== 2"
  183. placeholder="请输入"
  184. size="small"></el-input>
  185. </el-form-item>
  186. </el-col> -->
  187. <!-- <el-col :span="12">
  188. <el-form-item label="同级排序"
  189. prop="seq">
  190. <el-input v-model="formItem.seq"
  191. placeholder="请输入"
  192. size="small"></el-input>
  193. </el-form-item>
  194. </el-col> -->
  195. </el-row>
  196. <el-form-item
  197. label="URL"
  198. v-if="formItem.menuType === '4'"
  199. prop="menuUrl"
  200. >
  201. <el-input
  202. v-model="formItem.menuUrl"
  203. type="textarea"
  204. :autosize="{minRows: 3,maxRows: 5}"
  205. placeholder="请输入"
  206. style="width:100%"
  207. ></el-input>
  208. </el-form-item>
  209. <!-- <el-form-item label="备注"
  210. prop="menuTip">
  211. <el-input v-model="formItem.menuTip"
  212. type="textarea"
  213. :autosize="{minRows: 3,maxRows: 5}"
  214. placeholder="请输入"
  215. style="width:100%"></el-input>
  216. </el-form-item> -->
  217. <!-- <el-tag
  218. :key="index"
  219. v-for="(item, index) in functionTable"
  220. closable
  221. :disable-transitions="false"
  222. @click.native="editFncMenu(item,index)"
  223. @close="handleClose(item.id, index)">
  224. {{item.menuLabel}}
  225. </el-tag>
  226. <el-button class="button-new-tag" size="small" @click="functionVis = true">+ 添加功能</el-button> -->
  227. <el-form-item v-show="operateStatus === 'edit'">
  228. <el-button
  229. style="float:right;"
  230. :loading="addLoading1"
  231. type="primary"
  232. size="small"
  233. v-privilege=" activeMenu + 'EDIT'"
  234. @click="handleSubmit('formItem')"
  235. >保存</el-button>
  236. </el-form-item>
  237. <el-form-item v-show="operateStatus !== 'edit'">
  238. <el-button
  239. style="float:right;"
  240. :loading="addLoading2"
  241. type="primary"
  242. size="small"
  243. v-privilege="activeMenu + 'ADD'"
  244. @click="handleSubmit('formItem')"
  245. >添加</el-button>
  246. </el-form-item>
  247. </el-form>
  248. <el-form>
  249. <el-button
  250. @click="addNewFunc"
  251. v-if="formItem.menuType === '4'"
  252. size="small"
  253. type="primary"
  254. style="margin: 0 0 10px 20px;"
  255. v-privilege="activeMenu + 'FUNADD'"
  256. >新增功能</el-button>
  257. <!-- <el-checkbox
  258. v-model="icoreFilterFlag"
  259. @change="changeVal"
  260. v-if="formItem.menuType === '4'"
  261. >过滤</el-checkbox> -->
  262. <el-table stripe
  263. ref="funTable"
  264. v-if="formItem.menuType === '4'"
  265. style="margin: 0 0 0 20px;"
  266. border
  267. @icoreFilterChange="icoreFilterChange"
  268. :icore-filter-flag="icoreFilterFlag"
  269. :height="funHeight"
  270. :highlight-current="true"
  271. :data="functionTable"
  272. >
  273. <el-table-column
  274. prop="menuLabel"
  275. label="功能名称"
  276. :show-overflow-tooltip="true"
  277. :key="Math.random()"
  278. fixed="left"
  279. align="center"
  280. >
  281. <template slot-scope="scope">
  282. <span v-if="!scope.row.addEdit">{{scope.row.menuLabel}}</span>
  283. <el-input
  284. v-else
  285. size="mini"
  286. v-model="scope.row.menuLabel"
  287. ></el-input>
  288. </template>
  289. </el-table-column>
  290. <el-table-column
  291. prop="privilege"
  292. :show-overflow-tooltip="true"
  293. label="控件编号"
  294. fixed="left"
  295. :key="Math.random()"
  296. align="center"
  297. >
  298. <template slot-scope="scope">
  299. <span v-if="!scope.row.addEdit">{{scope.row.privilege}}</span>
  300. <el-input
  301. v-else
  302. size="mini"
  303. v-model="scope.row.privilege"
  304. ></el-input>
  305. </template>
  306. </el-table-column>
  307. <el-table-column
  308. label="操作"
  309. type="noFilter"
  310. :key="Math.random()"
  311. align="center"
  312. >
  313. <template slot-scope="scope">
  314. <el-button
  315. type="primary"
  316. size="small"
  317. v-if="!scope.row.addEdit"
  318. @click="editTableRow(scope.row)"
  319. style="margin:0 10px;"
  320. v-show="editPr"
  321. >编辑</el-button>
  322. <el-button
  323. type="primary"
  324. size="small"
  325. style="margin:0 10px;"
  326. :loading="buttonLoading"
  327. v-else
  328. @click="addFncMenu(scope.row)"
  329. >保存</el-button>
  330. <el-button
  331. type="warning"
  332. size="small"
  333. style="margin:0 10px;"
  334. @click="handleClose(scope.row)"
  335. v-show="delPr"
  336. >删除</el-button>
  337. </template>
  338. </el-table-column>
  339. </el-table>
  340. </el-form>
  341. </el-tab-pane>
  342. <el-tab-pane
  343. label="用户列表"
  344. name="userList"
  345. >
  346. <el-table stripe
  347. ref="userTable"
  348. v-loading="userTable.loading"
  349. @filter-change="filterChange"
  350. border
  351. :height="treeHeight"
  352. highlight-current-row
  353. :data="userTable.list"
  354. >
  355. <el-table-column
  356. :show-overflow-tooltip="true"
  357. prop="userCode"
  358. label="账户"
  359. :filter-method="filterColumn"
  360. min-width="150"
  361. ></el-table-column>
  362. <el-table-column
  363. :show-overflow-tooltip="true"
  364. prop="userName"
  365. label="用户姓名"
  366. :filter-method="filterColumn"
  367. min-width="150"
  368. ></el-table-column>
  369. <el-table-column
  370. :show-overflow-tooltip="true"
  371. prop="orgName"
  372. label="机构"
  373. :filter-method="filterColumn"
  374. min-width="150"
  375. >
  376. </el-table-column>
  377. </el-table>
  378. </el-tab-pane>
  379. </el-tabs>
  380. </div>
  381. <el-dialog
  382. title="是否重置菜单顺序"
  383. :visible.sync="showDelet"
  384. width="30%"
  385. center
  386. >
  387. <span
  388. slot="footer"
  389. class="dialog-footer"
  390. >
  391. <el-button @click="showDelet = false">取 消</el-button>
  392. <el-button
  393. type="danger"
  394. @click="resetSeq"
  395. >确 定</el-button>
  396. </span>
  397. </el-dialog>
  398. </div>
  399. </template>
  400. <script>
  401. import store from '@/store/index.js';
  402. import { dgTree, objAssign } from '@/utils/util.js';
  403. import { checkCharLength, checkCharLength2, checkCharNoChinese, checkCharNoChinese2, checkChar, checkChinese, checkChar2 } from '@/utils/validator.js';
  404. import FileSaver from 'file-saver';
  405. export default {
  406. data () {
  407. return {
  408. icoreFilterFlag: false,
  409. filterText: '',
  410. store,
  411. activeMenu: '',
  412. // 操作状态
  413. operateStatus: 'add',
  414. funHeight: 300,
  415. treeHeight: 600,
  416. addLoading1: false,
  417. addLoading2: false,
  418. showDelet: false,
  419. menuTableData: [],
  420. menuTableKeys: [
  421. {
  422. key: 'menuLabel',
  423. label: '菜单名称',
  424. width: 'auto'
  425. },
  426. {
  427. key: 'menuType',
  428. label: '功能类型',
  429. width: 'auto'
  430. },
  431. {
  432. key: 'pMenuLabel',
  433. label: '父菜单',
  434. width: 'auto'
  435. },
  436. {
  437. key: 'status',
  438. label: '状态',
  439. width: 'auto'
  440. },
  441. {
  442. key: 'menuUrl',
  443. label: 'URL',
  444. width: 'auto'
  445. },
  446. {
  447. key: 'funMenu',
  448. label: '功能控件',
  449. width: 'auto'
  450. }
  451. ],
  452. formItem: {
  453. 'id': '',
  454. 'pId': '',
  455. 'pName': '',
  456. 'menuType': '1',
  457. 'menuCode': '',
  458. 'menuUrl': '',
  459. 'menuName': '',
  460. 'menuLabel': '',
  461. 'status': '1',
  462. 'seq': '',
  463. 'menuTip': '',
  464. 'menuIcon': '',
  465. 'privilege': ''
  466. },
  467. menuStatus: [
  468. {
  469. label: '停用',
  470. value: '0'
  471. }, {
  472. label: '启用',
  473. value: '1'
  474. }
  475. ],
  476. icons: [
  477. {
  478. icon: '',
  479. value: '无'
  480. },
  481. {
  482. icon: 'xs-icons-menu1',
  483. value: 'xs-icons-menu1'
  484. },
  485. {
  486. icon: 'xs-icons-menu2',
  487. value: 'xs-icons-menu2'
  488. },
  489. {
  490. icon: 'xs-icons-menu3',
  491. value: 'xs-icons-menu3'
  492. },
  493. {
  494. icon: 'xs-icons-menu4',
  495. value: 'xs-icons-menu4'
  496. },
  497. {
  498. icon: 'xs-icons-menu5',
  499. value: 'xs-icons-menu5'
  500. },
  501. {
  502. icon: 'xs-icons-menu6',
  503. value: 'xs-icons-menu6'
  504. },
  505. {
  506. icon: 'xs-icons-menu7',
  507. value: 'xs-icons-menu7'
  508. },
  509. {
  510. icon: 'xs-icons-menu8',
  511. value: 'xs-icons-menu8'
  512. },
  513. {
  514. icon: 'xs-icons-menu9',
  515. value: 'xs-icons-menu9'
  516. },
  517. {
  518. icon: 'xs-icons-menu10',
  519. value: 'xs-icons-menu10'
  520. },
  521. {
  522. icon: 'xs-icons-menu11',
  523. value: 'xs-icons-menu11'
  524. },
  525. {
  526. icon: 'xs-icons-menu12',
  527. value: 'xs-icons-menu12'
  528. },
  529. {
  530. icon: 'xs-icons-menu13',
  531. value: 'xs-icons-menu13'
  532. },
  533. {
  534. icon: 'xs-icons-menu14',
  535. value: 'xs-icons-menu14'
  536. },
  537. {
  538. icon: 'xs-icons-menu15',
  539. value: 'xs-icons-menu15'
  540. },
  541. {
  542. icon: 'xs-icons-menu16',
  543. value: 'xs-icons-menu16'
  544. },
  545. {
  546. icon: 'xs-icons-menu17',
  547. value: 'xs-icons-menu17'
  548. },
  549. {
  550. icon: 'xs-icons-menu18',
  551. value: 'xs-icons-menu18'
  552. },
  553. {
  554. icon: 'xs-icons-menu19',
  555. value: 'xs-icons-menu19'
  556. }
  557. ],
  558. ruleValidate_formItem: {
  559. menuCode: [
  560. { required: true, message: '菜单编码不能为空', trigger: 'change' },
  561. { validator: checkCharNoChinese, trigger: 'change' },
  562. { validator: checkCharLength2, max: 36, trigger: 'change' }
  563. ],
  564. menuType: [
  565. { required: true, message: '功能类型不能为空', trigger: 'change' }
  566. ],
  567. menuName: [
  568. { required: true, message: '名称不能为空', trigger: 'change' },
  569. { validator: checkCharLength, max: 100, trigger: 'change' }
  570. ],
  571. menuLabel: [
  572. { required: true, message: '菜单名称不能为空', trigger: 'change' },
  573. { validator: checkCharLength, max: 100, trigger: 'change' },
  574. { validator: checkChar2, trigger: 'change' }
  575. ],
  576. menuTip: [
  577. { validator: checkCharLength, max: 100, trigger: 'change' }
  578. ],
  579. menuUrl: [
  580. { required: true, message: 'URL不能为空', trigger: 'change' },
  581. { validator: checkCharLength, max: 1500, trigger: 'change' }
  582. ],
  583. menuIcon: [
  584. { validator: checkCharLength, max: 100, trigger: 'change' }
  585. ],
  586. status: [
  587. { required: true, message: '请选择菜单状态', trigger: 'change' }
  588. ],
  589. privilege: [
  590. { validator: checkCharNoChinese, trigger: 'change' }
  591. ]
  592. },
  593. fncRule: {
  594. privilege: [
  595. { validator: checkCharNoChinese, trigger: 'change' }
  596. ],
  597. menuLabel: [
  598. { required: true, message: '功能名称不能为空', trigger: 'change' },
  599. { validator: checkCharLength, max: 40, trigger: 'change' }
  600. ]
  601. },
  602. formLenMessage: {
  603. },
  604. formItem_type_data: [
  605. {
  606. value: '1',
  607. label: '菜单'
  608. }
  609. ],
  610. formItem_type_data_nopage: [
  611. {
  612. value: '1',
  613. label: '菜单'
  614. }
  615. ],
  616. formItem_type_data_havePage: [
  617. {
  618. value: '1',
  619. label: '菜单'
  620. },
  621. {
  622. value: '4',
  623. label: '页面'
  624. }
  625. ],
  626. formItem_type_data_noMenu: [
  627. {
  628. value: '4',
  629. label: '页面'
  630. }
  631. ],
  632. // el tabs
  633. activeName: 'editForm',
  634. // 机构树
  635. orgTree: {
  636. tree: [],
  637. items: [],
  638. item: {},
  639. // 默认配置数据对应项
  640. defaultProps: {
  641. children: 'children',
  642. label: 'orgName'
  643. },
  644. // 默认展开的ID数组
  645. expandedKeys: []
  646. },
  647. // 用户列表
  648. userTable: {
  649. height: 600,
  650. loading: false,
  651. list: [],
  652. listBack: [],
  653. // 选中项
  654. items: [],
  655. item: {},
  656. tableParams: JSON.parse(JSON.stringify(store.state.tableParams)),
  657. menuTreeBack: []
  658. },
  659. functionTable: [],
  660. functionTableFObj: null,
  661. defaultFuncTable: [{
  662. pId: '',
  663. menuType: '2',
  664. menuLabel: '新增',
  665. privilege: 'ADD',
  666. status: '1',
  667. addEdit: false
  668. }, {
  669. pId: '',
  670. menuType: '2',
  671. menuLabel: '查询',
  672. privilege: 'QUERY',
  673. status: '1',
  674. addEdit: false
  675. }, {
  676. pId: '',
  677. menuType: '2',
  678. menuLabel: '修改',
  679. privilege: 'PUT',
  680. status: '1',
  681. addEdit: false
  682. }, {
  683. pId: '',
  684. menuType: '2',
  685. menuLabel: '删除',
  686. privilege: 'DELETE',
  687. status: '1',
  688. addEdit: false
  689. }],
  690. fncFrom: {
  691. id: '',
  692. pId: '',
  693. menuType: '2',
  694. menuLabel: '',
  695. privilege: '',
  696. status: '1'
  697. },
  698. activeTree: [],
  699. buttonLoading: false,
  700. editPr: true,
  701. delPr: false,
  702. expandList: [],
  703. treeLoading: false
  704. }
  705. },
  706. created () {
  707. this.activeMenu = window.localStorage.getItem('activeMenu');
  708. },
  709. mounted () {
  710. this.initData();
  711. // 设置树区域高度
  712. this.$nextTick(() => {
  713. this.treeHeight = this.getTreeHeight(this.$refs['menuTree'].$el);
  714. });
  715. },
  716. watch: {
  717. filterText (val) {
  718. this.$refs.menuTree.filter(val);
  719. }
  720. },
  721. computed: {
  722. // 菜单树数据
  723. menuTree () {
  724. let menuTree = this.store.state.system.functionMain.menuTree;
  725. return menuTree;
  726. },
  727. // 树配置
  728. defaultProps () {
  729. return this.store.state.system.functionMain.defaultProps;
  730. },
  731. // 展开数组
  732. expandedKeys: {
  733. get: function () {
  734. return this.store.state.system.functionMain.expandedKeys;
  735. },
  736. set: function (data) {
  737. this.store.commit('system/functionMain/expandedKeys', data);
  738. }
  739. },
  740. // 选中节点数据
  741. menuItem () {
  742. return this.store.state.system.functionMain.item;
  743. }
  744. },
  745. methods: {
  746. expandNode (data, node, item) {
  747. if (this.expandList.indexOf(data.id) === -1) {
  748. this.expandList.push(data.id)
  749. }
  750. this.$nextTick(() => {
  751. $('.delMenuPr').css('display', this.checkPrivilege(this.activeMenu + 'MENUDELET') ? 'inline-block' : 'none')
  752. $('.addMenuPr').css('display', this.checkPrivilege(this.activeMenu + 'MENUADD') ? 'inline-block' : 'none')
  753. })
  754. },
  755. expandCollapse (data, node, item) {
  756. let index = this.expandList.indexOf(data.id)
  757. if (index !== -1) {
  758. this.expandList.splice(index, 1)
  759. }
  760. },
  761. handleDragEnd (draggingNode, dropNode, dropType, ev) {
  762. let that = this;
  763. // console.log('tree drag end: ', dropNode && dropNode.label, dropType);
  764. // console.log('tree draggingNode: ', draggingNode);
  765. // console.log('tree dropNode: ', dropNode);
  766. // console.log('tree dropType: ', dropType);
  767. // console.log('tree ev: ', ev);
  768. let a = dropNode.data && dropNode.data.menuType !== '1';
  769. // if (draggingNode.data.children) {
  770. // that.$message.error('含有子菜单的节点不允许直接拖动')
  771. // that.initData();
  772. // } else
  773. if (draggingNode.data.menuType === '2') {
  774. that.$message.error('功能菜单不允许拖拽')
  775. that.initData();
  776. } else if (dropType === 'inner' && a) {
  777. that.$message.error('菜单不能移动到页面下')
  778. that.initData();
  779. } else {
  780. var changeList = [draggingNode.data, dropNode.data];
  781. this.store.dispatch('system/functionMain/dragMenu', { 'dropType': dropType, 'changeList': changeList }).then(res => {
  782. if (res.code === '0') {
  783. this.$message.success('修改成功');
  784. } else {
  785. this.$message({ message: res.message, type: 'error' });
  786. }
  787. });
  788. }
  789. },
  790. handleDragStart (draggingNode, dropNode, dropType, ev) {
  791. this.menuTreeBack = this.menuTree;
  792. },
  793. initData () {
  794. // 查询列表
  795. this.treeLoading = true;
  796. this.store.dispatch('system/functionMain/menuTree').then(res => {
  797. if (res.code === '0') {
  798. this.store.commit('system/functionMain/menuTree', res.data);
  799. this.store.commit('system/functionMain/expandedKeys', this.expandList);
  800. this.menuTableData = this.upToTableData(res.data, '', []);
  801. this.$nextTick(() => {
  802. $('.delMenuPr').css('display', this.checkPrivilege(this.activeMenu + 'MENUDELET') ? 'inline-block' : 'none')
  803. $('.addMenuPr').css('display', this.checkPrivilege(this.activeMenu + 'MENUADD') ? 'inline-block' : 'none')
  804. })
  805. this.treeLoading = false;
  806. } else {
  807. this.$message({ message: res.message, type: 'error' });
  808. }
  809. });
  810. this.getOrg();
  811. },
  812. // 将树形数据转为列表
  813. upToTableData (tree, pName, arr) {
  814. if (!!tree && tree.length !== 0) {
  815. tree.forEach(item => {
  816. let obj = {}
  817. obj['菜单名称'] = item.menuLabel;
  818. if (item.menuType === '1') {
  819. obj['功能类型'] = '菜单';
  820. } else {
  821. obj['功能类型'] = '页面';
  822. }
  823. obj['父菜单'] = pName ? pName : '';
  824. if (item.status === '1') {
  825. obj['状态'] = '启用';
  826. } else {
  827. obj['状态'] = '停用';
  828. }
  829. obj['菜单图标'] = item.menuIcon ? item.menuIcon : '';
  830. obj['URL'] = item.menuUrl === null ? '' : item.menuUrl;
  831. if (item.funChildren && item.funChildren.length > 0) {
  832. let str = '';
  833. for (let funObj of item.funChildren) {
  834. if (str === '') {
  835. str += funObj.menuLabel + '-' + funObj.privilege;
  836. } else {
  837. str += '、' + funObj.menuLabel + '-' + funObj.privilege;
  838. }
  839. }
  840. obj['功能控件'] = str;
  841. } else {
  842. obj['功能控件'] = '';
  843. }
  844. arr.push(obj)
  845. if (item.children && item.children.length > 0) {
  846. this.upToTableData(item.children, item.menuLabel, arr);
  847. }
  848. })
  849. }
  850. return arr
  851. },
  852. // 点击树事件
  853. nodeClick (item, el) {
  854. let that = this;
  855. this.icoreFilterFlag = false;
  856. // 放入
  857. this.store.commit('system/functionMain/item', item);
  858. // 加入
  859. this.formItem = objAssign(this.formItem, item);
  860. this.formItem.pName = el.parent.label;
  861. // 点击时为编辑状态
  862. this.operateStatus = 'edit';
  863. if (this.activeName === 'userList') {
  864. this.getMenuUser(item)
  865. }
  866. if (item.menuType === '4') {
  867. this.$nextTick(() => {
  868. this.funHeight = this.getTreeHeight(this.$refs['funTable'].$el) - 70;
  869. this.icoreFilterFlag = false;
  870. })
  871. }
  872. // 判断菜单下是否有页面
  873. let havPage = this.checkHavePage(item);
  874. if (item.funChildren) {
  875. let arr = [];
  876. for (let i = 0; i < item.funChildren.length; i++) {
  877. item.funChildren[i].addEdit = false;
  878. arr.push(item.funChildren[i])
  879. }
  880. this.functionTable = arr;
  881. this.functionTableFObj = item.funChildren;
  882. this.$nextTick(() => {
  883. this.editPr = this.checkPrivilege(this.activeMenu + 'FUNEDIT');
  884. this.delPr = this.checkPrivilege(this.activeMenu + 'FUNDELETE');
  885. })
  886. } else {
  887. this.functionTable = [];
  888. }
  889. if (item.menuType === '1' && havPage) {
  890. this.formItem_type_data = this.formItem_type_data_nopage;
  891. } else if (item.menuType === '4') {
  892. this.formItem_type_data = this.formItem_type_data_noMenu;
  893. } else {
  894. this.formItem_type_data = this.formItem_type_data_havePage
  895. }
  896. },
  897. // 清空 清空为添加,添加直接添加顶级目录
  898. handleReset (name) {
  899. this.$refs[name].resetFields();
  900. this.operateStatus = 'add';
  901. // 默认为菜单
  902. this.formItem.menuType = '1';
  903. this.formItem_type_data = this.formItem_type_data_nopage;
  904. },
  905. // 添加点击
  906. addTreeNode (node, item) {
  907. this.formItem_type_data = this.formItem_type_data_havePage;
  908. this.operateStatus = 'add';
  909. this.$refs['formItem'].resetFields();
  910. // 设置pId为当前ID
  911. this.formItem.pId = item.menuId;
  912. this.formItem.pName = item.menuLabel;
  913. // 清空ID
  914. this.formItem.id = '';
  915. this.formItem.menuUrl = '';
  916. this.formItem.menuLabel = '';
  917. // 添加默认功能菜单
  918. let arr = [];
  919. for (let i = 0; i < this.defaultFuncTable.length; i++) {
  920. arr.push(this.defaultFuncTable[i]);
  921. }
  922. this.functionTable = arr;
  923. },
  924. // 计算树区域高度
  925. getTreeHeight (dom) {
  926. return window.innerHeight - dom.offsetTop;
  927. },
  928. // renderContent (h, { node, data, store }) {
  929. // let render = [];
  930. // // let prl = this.$store.state.ownPrivilege;
  931. // // while (prl.length === 0) {
  932. // // continue;
  933. // // }
  934. // if (data.menuType === '1') {
  935. // render = [
  936. // h('span', {
  937. // class: 'el-icon-delete xl-icon-size delMenuPr',
  938. // attrs: {
  939. // title: '删除'
  940. // },
  941. // on: {
  942. // click: (event) => {
  943. // this.delTreeNode(node, data);
  944. // event.stopPropagation();
  945. // }
  946. // }
  947. // })
  948. // ];
  949. // // 如果是菜单增加 添加按钮
  950. // render = [h('span', {
  951. // class: 'el-icon-plus xl-icon-size addMenuPr',
  952. // attrs: {
  953. // title: '添加'
  954. // },
  955. // on: {
  956. // click: (event) => {
  957. // this.addTreeNode(node, data, event);
  958. // event.stopPropagation();
  959. // this.formItem_type_data = this.formItem_type_data_havePage;
  960. // }
  961. // }
  962. // })].concat(render);
  963. // } else {
  964. // render = [
  965. // h('span', {
  966. // class: 'el-icon-delete xl-icon-size delMenuPr',
  967. // attrs: {
  968. // title: '删除'
  969. // },
  970. // on: {
  971. // click: (event) => {
  972. // this.delTreeNode(node, data);
  973. // event.stopPropagation();
  974. // }
  975. // }
  976. // })
  977. // ].concat(render);
  978. // }
  979. // return h('span',
  980. // {
  981. // style: {
  982. // position: 'relative',
  983. // width: '100%',
  984. // fontSize: '14px'
  985. // },
  986. // class: 'fun-st-ellipsis'
  987. // },
  988. // [
  989. // h('span', node.label),
  990. // h('span', {
  991. // style: {
  992. // position: 'absolute',
  993. // right: '0px'
  994. // }
  995. // }, render)
  996. // ]);
  997. // },
  998. /**
  999. * 删除树节点元素
  1000. */
  1001. delTreeNode (node, data) {
  1002. if ((data.children && data.children.length > 0) || (node.childNodes && node.childNodes.length > 0) || (data.funChildren && data.funChildren.length > 0) || (node.funChildren && node.funChildren.length > 0)) {
  1003. this.$message.error('此节点有子节点或者功能,不允许直接删除');
  1004. return false;
  1005. }
  1006. //
  1007. this.$confirm('确定要删除已选择的记录吗?', '提示', {
  1008. customClass: 'org-Manage-changeprimaryforbutton',
  1009. confirmButtonText: '确定',
  1010. cancelButtonText: '取消',
  1011. type: 'warning'
  1012. }).then(() => {
  1013. this.store.dispatch('system/functionMain/delMenu', data.id).then(res => {
  1014. if (res.code === '0') {
  1015. this.$message.success('删除成功');
  1016. // 更新树
  1017. this.handleReset('formItem')
  1018. this.$refs['menuTree'].remove(data.id);
  1019. } else {
  1020. this.$message.error(res.message);
  1021. }
  1022. });
  1023. }).catch(() => {
  1024. this.$message.info('已取消操作');
  1025. });
  1026. this.$nextTick(() => {
  1027. document.getElementsByClassName('org-Manage-changeprimaryforbutton')[0].getElementsByClassName('el-message-box__btns')[0].getElementsByTagName('button')[0].classList.add('el-button--primary')
  1028. document.getElementsByClassName('org-Manage-changeprimaryforbutton')[0].getElementsByClassName('el-message-box__btns')[0].getElementsByTagName('button')[1].classList.remove('el-button--primary')
  1029. });
  1030. },
  1031. /**
  1032. * 保存数据
  1033. * */
  1034. handleSubmit (name) {
  1035. this.$refs[name].validate((valid) => {
  1036. if (valid) {
  1037. if (this.operateStatus === 'edit') {
  1038. if (!this.formItem.id) {
  1039. this.$message.error('请选择数据再来操作');
  1040. return;
  1041. }
  1042. this.$confirm('确定要修改已选择的记录吗?', '提示', {
  1043. confirmButtonText: '确定',
  1044. cancelButtonText: '取消',
  1045. type: 'warning'
  1046. }).then(() => {
  1047. // 修改数据
  1048. this.addLoading1 = true;
  1049. //
  1050. this.store.dispatch('system/functionMain/editMenu', { id: this.menuItem.id, form: this.formItem }).then(res => {
  1051. //
  1052. this.addLoading1 = false;
  1053. //
  1054. if (res.code === '0') {
  1055. this.$message.success('保存成功');
  1056. //
  1057. this.formItem = objAssign(this.formItem, res.data);
  1058. // 更新菜单项
  1059. dgTree(this.menuTree, 'children', item => {
  1060. if (item.id === this.formItem.id) {
  1061. item.id = this.formItem.id;
  1062. item.pId = this.formItem.pId;
  1063. item.menuType = this.formItem.menuType;
  1064. item.menuCode = this.formItem.menuCode;
  1065. item.menuUrl = this.formItem.menuUrl;
  1066. item.menuName = this.formItem.menuName;
  1067. item.menuLabel = this.formItem.menuLabel;
  1068. item.status = this.formItem.status;
  1069. item.menuTip = this.formItem.menuTip;
  1070. item.menuIcon = this.formItem.menuIcon;
  1071. }
  1072. });
  1073. // this.store.commit('system/functionMain/menuTree', this.menuTree);
  1074. this.initData();
  1075. this.$refs['menuTree'].setCurrentKey(res.data.id);
  1076. } else {
  1077. this.$message({ message: res.message, type: 'error' });
  1078. }
  1079. });
  1080. }).catch(() => {
  1081. this.$message({
  1082. type: 'info',
  1083. message: '已取消操作'
  1084. });
  1085. });
  1086. } else if (this.operateStatus === 'add') {
  1087. // 添加
  1088. this.addLoading2 = true;
  1089. //
  1090. this.store.dispatch('system/functionMain/addMenu', this.formItem).then(res => {
  1091. //
  1092. this.addLoading2 = false;
  1093. //
  1094. if (res.code === '0') {
  1095. this.$message.success('添加成功');
  1096. // 更新树
  1097. this.$refs['menuTree'].append(res.data, this.formItem.pId);
  1098. this.$refs['menuTree'].setCurrentKey(res.data.id);
  1099. this.$nextTick(() => {
  1100. $('.delMenuPr').css('display', this.checkPrivilege('480431426513276928DELET') ? 'inline-block' : 'none')
  1101. $('.addMenuPr').css('display', this.checkPrivilege('480431426513276928ADD') ? 'inline-block' : 'none')
  1102. })
  1103. this.initData();
  1104. if (res.data.menuType === '4') {
  1105. this.addNewFunctionMain(res.data.id);
  1106. }
  1107. res.data.funChildren = [];
  1108. this.functionTableFObj = res.data.funChildren;
  1109. } else {
  1110. this.$message({ message: res.message, type: 'error' });
  1111. }
  1112. });
  1113. }
  1114. }
  1115. })
  1116. },
  1117. // 树形控件过滤数据
  1118. filterOrgTree (value, data) {
  1119. if (!value) return true;
  1120. return data.menuLabel.indexOf(value) !== -1;
  1121. },
  1122. // 重置菜单顺序
  1123. resetSeq () {
  1124. let that = this;
  1125. that.axios.get('/pass/v1/sysmenus/resetSeq').then(function (res) {
  1126. if (res.code === '0') {
  1127. that.$message.success('重置菜单排序成功')
  1128. that.initData();
  1129. that.showDelet = false;
  1130. } else {
  1131. that.$message.error(res.message);
  1132. that.showDelet = false;
  1133. }
  1134. }).catch(function () {
  1135. // do some thing
  1136. })
  1137. },
  1138. // 用户过滤
  1139. filterChange (filters) {
  1140. var _this = this;
  1141. _this.setFilterDatas(_this.$refs.userTable.columns, _this.$refs.userTable.tableData, ['userCode', 'userName', 'orgName']);
  1142. // _this.tableParams.page.total = _this.$refs.userTable.tableData.length;
  1143. },
  1144. // 查询机构名称
  1145. getOrgName (list, code) {
  1146. var name = '';
  1147. for (let i = 0; i < list.length; i++) {
  1148. try {
  1149. if (list[i].orgCode === code) {
  1150. name = list[i].orgName
  1151. return name
  1152. } else if (list[i].children && list[i].children.length >= 1) {
  1153. name = this.getOrgName(list[i].children, code);
  1154. if (name) {
  1155. return name
  1156. }
  1157. }
  1158. } catch (error) {
  1159. console.log(error)
  1160. }
  1161. }
  1162. return name;
  1163. },
  1164. getOrg () {
  1165. // 查询机构树
  1166. this.store.dispatch('system/organizManage/tree').then(res => {
  1167. if (res.code === '0') {
  1168. dgTree(res.data, 'children', item => {
  1169. if ('children' in item && item.children.length < 1) {
  1170. delete item.children;
  1171. }
  1172. });
  1173. this.orgTree.tree = res.data;
  1174. this.getUser(this.userTable.tableParams.form);
  1175. } else {
  1176. this.$message.error(res.message);
  1177. }
  1178. });
  1179. },
  1180. // 获取用户列表
  1181. getUser (form) {
  1182. let _this = this;
  1183. form.pageSize = '1000000';
  1184. this.store.dispatch('system/usersManage/list', form).then(res => {
  1185. if (res.code === '0') {
  1186. this.userTable.list = res.data.list;
  1187. this.userTable.listBack = res.data.list;
  1188. this.userTable.tableParams.form.pageNum = res.data.pageNum;
  1189. this.userTable.tableParams.form.pageSize = res.data.pageSize;
  1190. this.userTable.tableParams.page.total = res.data.total;
  1191. for (let a = 0; a < this.userTable.list.length; a++) {
  1192. this.userTable.list[a].orgName = this.getOrgName(this.orgTree.tree, this.userTable.list[a].orgCode)
  1193. this.userTable.listBack[a].orgName = this.getOrgName(this.orgTree.tree, this.userTable.list[a].orgCode)
  1194. }
  1195. // 设置过滤数据 setFilterDatas(列数组对象, 数据, 需要过滤的字段, 列名转义对象)
  1196. _this.setFilterDatas(_this.$refs.userTable.columns, _this.userTable.list, ['userCode', 'userName', 'orgName']);
  1197. } else {
  1198. this.$message.error(res.message);
  1199. this.userTable.tableParams.form.pageNum = 1;
  1200. this.userTable.tableParams.page.total = 0;
  1201. }
  1202. });
  1203. },
  1204. // 获取指定菜单下用户列表
  1205. getMenuUser (item) {
  1206. let that = this;
  1207. that.axios.get('pass/v1/sysuserroles/selectByMenuId/' + item.id).then((res) => {
  1208. if (res.code === '0') {
  1209. that.userTable.list = res.data;
  1210. for (let i = 0; i < that.userTable.listBack.length; i++) {
  1211. for (let j = 0; j < that.userTable.list.length; j++) {
  1212. if (that.userTable.listBack[i].userCode === that.userTable.list[j].userCode) {
  1213. that.userTable.list[j].userName = that.userTable.listBack[i].userName
  1214. that.userTable.list[j].orgName = that.userTable.listBack[i].orgName
  1215. }
  1216. }
  1217. }
  1218. if (res.data.length === 0) {
  1219. that.$refs.userTable.columns[0].filters = [];
  1220. that.$refs.userTable.columns[1].filters = [];
  1221. that.$refs.userTable.columns[2].filters = [];
  1222. }
  1223. that.setFilterDatas(that.$refs.userTable.columns, res.data, ['userCode', 'userName', 'orgName']);
  1224. } else {
  1225. this.$message.error(res.message)
  1226. }
  1227. }).catch(() => {
  1228. that.$message.error('请求失败')
  1229. })
  1230. },
  1231. changeType (val) {
  1232. if (val !== 2) {
  1233. this.formItem.privilege = ''
  1234. }
  1235. if (val === '4') {
  1236. this.$nextTick(() => {
  1237. this.funHeight = this.getTreeHeight(this.$refs['funTable'].$el) - 70
  1238. })
  1239. }
  1240. },
  1241. // 新增多个功能菜单
  1242. addNewFunctionMain (id) {
  1243. let that = this;
  1244. if (this.functionTable.length > 0) {
  1245. for (let i = 0; i < this.functionTable.length; i++) {
  1246. this.functionTable[i].pId = id;
  1247. }
  1248. that.axios.put('pass/v1/sysmenus/bathInsert', JSON.stringify(that.functionTable)).then((res) => {
  1249. if (res.code === '0') {
  1250. // do some thing
  1251. that.initData();
  1252. // that.functionTableFObj.splice(0,arr.length);
  1253. that.axios.get('pass/v1/sysmenus/?pId=' + id)
  1254. .then((res1) => {
  1255. if (res1.code === '0') {
  1256. for (let item of res1.data.list) {
  1257. that.functionTableFObj.push(item);
  1258. }
  1259. }
  1260. else {
  1261. this.$message.error(res1.message)
  1262. }
  1263. })
  1264. } else {
  1265. this.$message.error(res.message)
  1266. }
  1267. }).catch((error) => {
  1268. that.$message.error(error);
  1269. })
  1270. }
  1271. },
  1272. // 删除菜单
  1273. handleClose (row) {
  1274. let that = this;
  1275. let index = that.getRowIndex(row.privilege, 2);
  1276. if (row.id) {
  1277. this.$confirm('确定要删除已选择的记录吗?', '提示', {
  1278. customClass: 'org-Manage-changeprimaryforbutton',
  1279. confirmButtonText: '确定',
  1280. cancelButtonText: '取消',
  1281. type: 'warning'
  1282. }).then(() => {
  1283. this.store.dispatch('system/functionMain/delMenu', row.id).then(res => {
  1284. if (res.code === '0') {
  1285. this.$message.success('删除成功');
  1286. this.initData();
  1287. that.functionTable.splice(index, 1);
  1288. for (let indexf = 0; indexf < that.functionTableFObj.length; indexf++) {
  1289. if (that.functionTableFObj[indexf].id === row.id) {
  1290. // 删除树节点中绑定的对应数据
  1291. that.functionTableFObj.splice(indexf, 1);
  1292. break;
  1293. }
  1294. }
  1295. } else {
  1296. this.$message.error(res.message);
  1297. }
  1298. });
  1299. }).catch(() => {
  1300. this.$message.info('已取消操作');
  1301. });
  1302. this.$nextTick(() => {
  1303. document.getElementsByClassName('org-Manage-changeprimaryforbutton')[0].getElementsByClassName('el-message-box__btns')[0].getElementsByTagName('button')[0].classList.add('el-button--primary')
  1304. document.getElementsByClassName('org-Manage-changeprimaryforbutton')[0].getElementsByClassName('el-message-box__btns')[0].getElementsByTagName('button')[1].classList.remove('el-button--primary')
  1305. });
  1306. } else {
  1307. that.functionTable.splice(index, 1);
  1308. }
  1309. },
  1310. addFncMenu (row) {
  1311. this.buttonLoading = true;
  1312. try {
  1313. let rule = {
  1314. max: 40,
  1315. required: true,
  1316. errName: '功能名称'
  1317. };
  1318. let rule2 = {
  1319. max: 36,
  1320. required: true,
  1321. errName: '控件编号'
  1322. }
  1323. this.checkCharLength(rule, row.menuLabel, '功能名称不能为空');
  1324. this.checkCharLength(rule2, row.privilege, '控件编号不能为空')
  1325. this.checkCharNoChinese(row.privilege);
  1326. if (this.formItem.id) {
  1327. if (!row.id) {
  1328. this.store.dispatch('system/functionMain/addMenu', row).then(res => {
  1329. this.addLoading2 = false;
  1330. if (res.code === '0') {
  1331. this.$message.success('添加成功');
  1332. res.data.addEdit = false;
  1333. this.functionTable[this.getRowIndex(res.data.privilege, 2)] = res.data;
  1334. row.addEdit = false;
  1335. this.functionTableFObj.push(res.data);
  1336. this.initData();
  1337. } else {
  1338. this.$message({ message: res.message, type: 'error' });
  1339. }
  1340. });
  1341. } else {
  1342. this.store.dispatch('system/functionMain/editMenu', { id: row.id, form: row }).then(res => {
  1343. this.addLoading1 = false;
  1344. if (res.code === '0') {
  1345. this.$message.success('保存成功');
  1346. this.getRowIndex(res.data);
  1347. row.addEdit = false;
  1348. for (let i = 0; i < this.functionTableFObj.length; i++) {
  1349. if (row.id === this.functionTableFObj[i].id) {
  1350. for (let key in this.functionTableFObj[i]) {
  1351. this.functionTableFObj[i][key] = row[key];
  1352. }
  1353. break;
  1354. }
  1355. }
  1356. this.initData();
  1357. } else {
  1358. this.$message({ message: res.message, type: 'error' });
  1359. }
  1360. });
  1361. }
  1362. } else {
  1363. let arr = row;
  1364. let idx = this.getRowIndex(row.privilege, 1);
  1365. arr.menuType = '2';
  1366. arr.status = '1';
  1367. arr.addEdit = false;
  1368. this.functionTable[idx] = arr;
  1369. }
  1370. } catch (err) {
  1371. this.$message.error(err.message)
  1372. }
  1373. this.buttonLoading = false;
  1374. },
  1375. editTableRow (row) {
  1376. let that = this;
  1377. if (row.menuId) {
  1378. for (let i = 0; i < that.functionTable.length; i++) {
  1379. if (that.functionTable[i].menuId === row.menuId) {
  1380. that.functionTable[i].addEdit = true;
  1381. }
  1382. }
  1383. } else {
  1384. for (let i = 0; i < that.functionTable.length; i++) {
  1385. if (that.functionTable[i].menuLabel === row.menuLabel) {
  1386. that.functionTable[i].addEdit = true;
  1387. }
  1388. }
  1389. }
  1390. },
  1391. // 新增一条空数据
  1392. addNewFunc () {
  1393. let obj = {
  1394. id: '',
  1395. pId: this.formItem.id || '',
  1396. menuType: '2',
  1397. menuLabel: '',
  1398. privilege: '',
  1399. status: '1',
  1400. addEdit: true
  1401. }
  1402. this.functionTable.push(obj)
  1403. },
  1404. // 获取当前编辑行的index
  1405. getRowIndex (data, type) {
  1406. let that = this;
  1407. let index = 0;
  1408. if (!type) {
  1409. for (let i = 0; i < that.functionTable.length; i++) {
  1410. if (that.functionTable[i].id === data.id) {
  1411. data.addEdit = false;
  1412. that.functionTable[i] = data;
  1413. break;
  1414. }
  1415. }
  1416. } else {
  1417. for (let i = 0; i < that.functionTable.length; i++) {
  1418. if (that.functionTable[i].privilege === data) {
  1419. index = i;
  1420. break;
  1421. }
  1422. }
  1423. }
  1424. return index
  1425. },
  1426. // 校验方法
  1427. checkCharLength (rule, value, msg) {
  1428. if (value) {
  1429. let chineseLen = 3;
  1430. let iLen = chineseLen > 1 ? this._charLength(value, chineseLen) : value.length;
  1431. if (rule.min && rule.min > 0 && iLen < rule.min) {
  1432. throw new Error(rule.errName + '最少输入' + rule.min + '个字符(一个中文占' + chineseLen + '个字符)')
  1433. }
  1434. if (rule.max && rule.max > 0 && iLen > rule.max) {
  1435. throw new Error(rule.errName + '最多输入' + rule.max + '个字符(一个中文占' + chineseLen + '个字符)')
  1436. }
  1437. } else {
  1438. if (rule.required) {
  1439. throw new Error(rule.errName + '不能为空')
  1440. }
  1441. }
  1442. },
  1443. checkCharNoChinese (value) {
  1444. let reg = /^[-_a-zA-Z0-9]+$/;
  1445. if (value && !reg.test(value)) {
  1446. throw new Error('请输入英文字母、数字、下划线(_)或横线(-)的组合')
  1447. }
  1448. },
  1449. _charLength (str, chineseLen) {
  1450. if (!str || str.length <= 0) { return 0; };
  1451. // str = mytrim(str);
  1452. let chineseLength = 3; // utf-8编码,中文长度
  1453. if (chineseLen && chineseLen > 0) {
  1454. chineseLength = chineseLen
  1455. }
  1456. let objValue = str;
  1457. let objLength = 0;
  1458. let compareChar = '';
  1459. let regExp = new RegExp("^[A-Za-z0-9 -_`~!@#$%^&*()-+=|,<.>/?;:'\\\"]$");
  1460. for (let count = 0; count < objValue.length; count++) {
  1461. compareChar = objValue.substring(count, count + 1);
  1462. if (regExp.test(compareChar)) {
  1463. objLength += 1;
  1464. } else if (compareChar === '\\') {
  1465. objLength += 1;
  1466. } else {
  1467. objLength += chineseLength;
  1468. }
  1469. }
  1470. return objLength;
  1471. },
  1472. icoreFilterChange (item) {
  1473. // do something
  1474. },
  1475. checkHavePage (item) {
  1476. let status = false
  1477. if (item.children) {
  1478. try {
  1479. for (let i = 0; i < item.children.length; i++) {
  1480. if (item.children[i].children && !item.children[i].funChildren) {
  1481. for (let b = 0; b < item.children[i].children.length; b++) {
  1482. status = this.checkHavePage(item.children[i].children)
  1483. }
  1484. } else if (item.children[i].funChildren) {
  1485. status = true
  1486. break
  1487. }
  1488. }
  1489. } catch (err) {
  1490. console.log(err)
  1491. }
  1492. } else {
  1493. status = false
  1494. }
  1495. return status
  1496. },
  1497. setCheckedKeys () {
  1498. this.defaultExpand = false;
  1499. for (var i = 0; i < this.$refs.menuTree.store._getAllNodes().length; i++) {
  1500. this.$refs.menuTree.store._getAllNodes()[i].expanded = this.defaultExpand;
  1501. }
  1502. this.$nextTick(() => {
  1503. $('.delMenuPr').css('display', this.checkPrivilege(this.activeMenu + 'MENUDELET') ? 'inline-block' : 'none')
  1504. $('.addMenuPr').css('display', this.checkPrivilege(this.activeMenu + 'MENUADD') ? 'inline-block' : 'none')
  1505. })
  1506. },
  1507. setCheckedNodes () {
  1508. this.defaultExpand = true; // 展开所有节点
  1509. for (var i = 0; i < this.$refs.menuTree.store._getAllNodes().length; i++) {
  1510. if (this.$refs.menuTree.store._getAllNodes()[i].data.status === '1') {
  1511. this.$refs.menuTree.store._getAllNodes()[i].expanded = this.defaultExpand;
  1512. }
  1513. }
  1514. this.$nextTick(() => {
  1515. $('.delMenuPr').css('display', this.checkPrivilege(this.activeMenu + 'MENUDELET') ? 'inline-block' : 'none')
  1516. $('.addMenuPr').css('display', this.checkPrivilege(this.activeMenu + 'MENUADD') ? 'inline-block' : 'none')
  1517. })
  1518. },
  1519. changeVal (val) {
  1520. this.$nextTick(() => {
  1521. if (!val) {
  1522. let temp = [];
  1523. for (let i = 0; i < this.functionTable.length; i++) {
  1524. temp.push(this.functionTable[i])
  1525. }
  1526. this.functionTable = temp;
  1527. }
  1528. })
  1529. },
  1530. // 菜单导出
  1531. menuExport () {
  1532. // if (this.menuTableData.length > 0) {
  1533. // let et = XLSX.utils.table_to_book(document.getElementById('menuExcel'));
  1534. // let etout = XLSX.write(et, {
  1535. // bookType: 'xlsx',
  1536. // bookSST: true,
  1537. // type: 'array',
  1538. // cellStyles: true
  1539. // });
  1540. // try {
  1541. // FileSaver.saveAs(new Blob([etout], {
  1542. // type: 'application/octet-stream'
  1543. // }), '新泰能源管控系统菜单详情.xlsx'); //导出的文件名
  1544. // this.$message({
  1545. // type: 'success',
  1546. // message: '正在为您导出...'
  1547. // });
  1548. // } catch (e) {
  1549. // console.log(e, etout) ;
  1550. // }
  1551. // return etout;
  1552. // } else {
  1553. // this.$message.error('当前无数据可供导出!');
  1554. // }
  1555. let data = this.menuTableData;
  1556. if (data.length < 1) {
  1557. this.$message.error('当前无数据可供导出!');
  1558. return false;
  1559. }
  1560. // 表格标题
  1561. var dataTitle = '新泰能源管控系统菜单详情';
  1562. // 配置文件类型
  1563. const wopts = { bookType: 'xlsx', bookSST: true, type: 'binary', cellStyles: true };
  1564. this.downloadExl(data, wopts, dataTitle)
  1565. },
  1566. downloadExl(json, type, dataTitle) {
  1567. // 设置表格中cell默认的字体,居中,颜色等
  1568. var defaultCellStyle = {
  1569. // font: {
  1570. // name: "宋体", sz: 11, color: { auto: 1 } ,
  1571. // },
  1572. // border: {
  1573. // color: { auto: 1 },
  1574. // top: { style: 'thin' },
  1575. // bottom: { style: 'thin'},
  1576. // left: { style: 'thin' },
  1577. // right: { style: 'thin' }
  1578. // },
  1579. alignment: {
  1580. /// 自动换行
  1581. wrapText: 1,
  1582. // 居中
  1583. // horizontal: "center",
  1584. // vertical: "center",
  1585. // indent: 0
  1586. }
  1587. };
  1588. var tmpdata = json[0];
  1589. json.unshift({});
  1590. var keyMap = []; // 获取keys
  1591. for (var k in tmpdata) {
  1592. keyMap.push(k);
  1593. json[0][k] = k;
  1594. }
  1595. var tmpdata = [];// 用来保存转换好的json
  1596. json.map((v, i) => {
  1597. let data = keyMap.map((k, j) => {
  1598. // console.log(k,this.getCharCol(j));
  1599. return Object.assign({}, {
  1600. v: v[k],
  1601. position: (j > 25 ? this.getCharCol(j) : String.fromCharCode(65 + j)) + (i + 2)
  1602. });
  1603. });
  1604. return data;
  1605. }).reduce((prev, next) => prev.concat(next)).forEach((v, i) => tmpdata[v.position] = {
  1606. v: v.v,
  1607. s: defaultCellStyle
  1608. });
  1609. var outputPos = Object.keys(tmpdata); // 设置区域,比如表格从A1到D10
  1610. tmpdata["A1"] = {v:dataTitle};
  1611. outputPos = ["A1"].concat(outputPos);
  1612. tmpdata["A1"].s = { font: { sz: 14, bold: true, vertAlign:true }, alignment:{ vertical:"center", horizontal:"center" }};// <====设置xlsx单元格样式 fill: { bgColor: { rgb: "E8E8E8"}, fgColor: { rgb: "E8E8E8" } }
  1613. tmpdata["!merges"] = [{
  1614. s: { c: 0, r: 0 },
  1615. e: { c: 6, r: 0 }
  1616. }];// <====合并单元格
  1617. tmpdata["!cols"] = [
  1618. {wpx: 150},
  1619. {wpx: 100},
  1620. {wpx: 150},
  1621. {wpx: 100},
  1622. {wpx: 150},
  1623. {wpx: 400},
  1624. {wpx: 400},
  1625. ];// <====设置一列宽度
  1626. var tmpWB = {
  1627. SheetNames: ['mySheet'], // 保存的表标题
  1628. Sheets: {
  1629. 'mySheet': Object.assign({},
  1630. tmpdata, // 内容
  1631. {
  1632. '!ref': outputPos[0] + ':' + outputPos[outputPos.length - 1] // 设置填充区域
  1633. }
  1634. )
  1635. }
  1636. };
  1637. var tmpDown = new Blob([this.s2ab(XLSX.write(tmpWB,
  1638. // 这里的数据是用来定义导出的格式类型
  1639. { bookType: (type == undefined ? 'xlsx' : type.bookType), bookSST: false, type: 'binary' }, { defaultCellStyle: this.defaultCellStyle }
  1640. ))], {
  1641. type: ""
  1642. });
  1643. this.saveAs(tmpDown, "新泰能源管控系统菜单详情" + '.' + (type.bookType == "biff2" ? "xls" : type.bookType));
  1644. },
  1645. // 下载功能
  1646. saveAs(obj, fileName) {
  1647. var tmpa = document.createElement("a");
  1648. tmpa.download = fileName || "未命名";
  1649. // 兼容ie
  1650. if ("msSaveOrOpenBlob" in navigator) {
  1651. window.navigator.msSaveOrOpenBlob(obj, "新泰能源管控系统菜单详情"+ ".xlsx");
  1652. } else {
  1653. tmpa.href = URL.createObjectURL(obj);
  1654. }
  1655. tmpa.click();
  1656. setTimeout(function() {
  1657. URL.revokeObjectURL(obj);
  1658. }, 100);
  1659. },
  1660. // 获取26个英文字母用来表示excel的列
  1661. getCharCol(n) {
  1662. let temCol = '',
  1663. s = '',
  1664. m = 0
  1665. while (n > 0) {
  1666. m = n % 26 + 1
  1667. s = String.fromCharCode(m + 64) + s
  1668. n = (n - m) / 26
  1669. }
  1670. return s
  1671. },
  1672. s2ab(s) {
  1673. if (typeof ArrayBuffer !== 'undefined') {
  1674. var buf = new ArrayBuffer(s.length);
  1675. var view = new Uint8Array(buf);
  1676. for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
  1677. return buf;
  1678. } else {
  1679. var buf = new Array(s.length);
  1680. for (var i = 0; i != s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF;
  1681. return buf;
  1682. }
  1683. }
  1684. }
  1685. }
  1686. </script>
  1687. <style scope>
  1688. .functionDiv {
  1689. position: relative;
  1690. min-width: 1100px;
  1691. }
  1692. .MainLeft {
  1693. width: 30%;
  1694. border-right: 1px solid #e0e0e0;
  1695. float: left;
  1696. overflow: hidden;
  1697. height: inherit;
  1698. }
  1699. .el-tree {
  1700. overflow-x: hidden !important;
  1701. }
  1702. .MainRight {
  1703. width: 70%;
  1704. float: left;
  1705. }
  1706. .exportButton {
  1707. position: absolute;
  1708. right: 20px;
  1709. top: 10px;
  1710. z-index: 1999;
  1711. }
  1712. .FormMain {
  1713. margin: 20px 20px;
  1714. }
  1715. .searchContent {
  1716. margin: 20px 0px 0px 20px;
  1717. text-align: left;
  1718. width: 100%;
  1719. }
  1720. .public-function-div {
  1721. height: 45px;
  1722. font-size: 16px;
  1723. padding: 10px 20px;
  1724. border-bottom: 1px solid #d5d5d5;
  1725. position: relative;
  1726. }
  1727. .public-function-div .refresh {
  1728. position: absolute;
  1729. right: 15px;
  1730. top: 10px;
  1731. }
  1732. .public-function-div .refresh2 {
  1733. position: absolute;
  1734. right: 80px;
  1735. top: 10px;
  1736. }
  1737. .public-function-div .refresh3 {
  1738. position: absolute;
  1739. right: 145px;
  1740. top: 10px;
  1741. }
  1742. .fun-st-ellipsis {
  1743. overflow: hidden;
  1744. text-overflow: ellipsis;
  1745. white-space: nowrap;
  1746. word-break: keep-all;
  1747. padding-right: 60px;
  1748. }
  1749. .filterTree {
  1750. width: 95%;
  1751. margin: 10px 2.5%;
  1752. }
  1753. /** el-tabs **/
  1754. .el-tabs__item {
  1755. font-size: 16px;
  1756. height: 46px;
  1757. line-height: 46px;
  1758. }
  1759. .el-tabs__nav-scroll {
  1760. padding-left: 20px;
  1761. }
  1762. #pane-userList {
  1763. padding: 10px;
  1764. }
  1765. .el-select {
  1766. width: 100%;
  1767. }
  1768. .xs-menu-icons {
  1769. display: inline-block;
  1770. width: 26px;
  1771. height: 26px;
  1772. cursor: pointer;
  1773. transform: scale(0.8);
  1774. background: url(../../../assets/img/menu/menu_b.png) 0 0 no-repeat;
  1775. -webkit-transition: background-position 0.3s;
  1776. transition: background-position 0.3s;
  1777. }
  1778. .xs-icons-menu1 {
  1779. background-position: -25px -24px;
  1780. }
  1781. .xs-icons-menu2 {
  1782. background-position: -73px -24px;
  1783. }
  1784. .xs-icons-menu3 {
  1785. background-position: -120px -24px;
  1786. }
  1787. .xs-icons-menu4 {
  1788. background-position: -168px -24px;
  1789. }
  1790. .xs-icons-menu5 {
  1791. background-position: -25px -70px;
  1792. }
  1793. .xs-icons-menu6 {
  1794. background-position: -73px -70px;
  1795. }
  1796. .xs-icons-menu7 {
  1797. background-position: -120px -70px;
  1798. }
  1799. .xs-icons-menu8 {
  1800. background-position: -168px -70px;
  1801. }
  1802. .xs-icons-menu9 {
  1803. background-position: -25px -119px;
  1804. }
  1805. .xs-icons-menu10 {
  1806. background-position: -73px -119px;
  1807. }
  1808. .xs-icons-menu11 {
  1809. background-position: -120px -119px;
  1810. }
  1811. .xs-icons-menu12 {
  1812. background-position: -168px -119px;
  1813. }
  1814. .xs-icons-menu13 {
  1815. background-position: -25px -168px;
  1816. }
  1817. .xs-icons-menu14 {
  1818. background-position: -73px -168px;
  1819. }
  1820. .xs-icons-menu15 {
  1821. background-position: -120px -168px;
  1822. }
  1823. .xs-icons-menu16 {
  1824. background-position: -168px -168px;
  1825. }
  1826. .xs-icons-menu17 {
  1827. background-position: -25px -217px;
  1828. }
  1829. .xs-icons-menu18 {
  1830. background-position: -73px -217px;
  1831. }
  1832. .xs-icons-menu19 {
  1833. background-position: -120px -217px;
  1834. }
  1835. .el-tree-node__content .el-icon-plus {
  1836. margin-right: 20px;
  1837. }
  1838. .el-tag {
  1839. margin: 0 0 10px 10px;
  1840. cursor: pointer;
  1841. }
  1842. .danger {
  1843. color: #f00;
  1844. }
  1845. .roleForm .el-form-item__content {
  1846. margin-top: 13px;
  1847. }
  1848. .delMenuPr,
  1849. .addMenuPr {
  1850. display: none;
  1851. }
  1852. .el-tree-node__content:hover {
  1853. background-color: #bbdffb;
  1854. }
  1855. .el-tree-node:focus .el-tree-node__content {
  1856. background-color: #bbdffb;
  1857. }
  1858. .el-tree .is-current .el-tree-node__content {
  1859. background-color: #bbdffb;
  1860. }
  1861. .is-current .el-tree-node__children .el-tree-node .el-tree-node__content {
  1862. background-color: #fff;
  1863. }
  1864. </style>