user.vue 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142
  1. <template>
  2. <el-row>
  3. <el-col :span="5">
  4. <div class="box">
  5. <el-scrollbar>
  6. <basic-container>
  7. <avue-tree :option="treeOption" :data="treeData" @node-click="nodeClick"/>
  8. </basic-container>
  9. </el-scrollbar>
  10. </div>
  11. </el-col>
  12. <el-col :span="19">
  13. <basic-container>
  14. <avue-crud :option="option"
  15. :search.sync="search"
  16. :table-loading="loading"
  17. :data="data"
  18. ref="crud"
  19. v-model="form"
  20. :permission="permissionList"
  21. @row-del="rowDel"
  22. @row-update="rowUpdate"
  23. @row-save="rowSave"
  24. :before-open="beforeOpen"
  25. :page.sync="page"
  26. @search-change="searchChange"
  27. @search-reset="searchReset"
  28. @selection-change="selectionChange"
  29. @current-change="currentChange"
  30. @size-change="sizeChange"
  31. @refresh-change="refreshChange"
  32. @on-load="onLoad">
  33. <template slot="menuLeft">
  34. <el-button type="primary"
  35. size="small"
  36. v-if="permission.user_add && !auditMode"
  37. icon="el-icon-plus"
  38. @click="$refs.crud.rowAdd()">新 增
  39. </el-button>
  40. <el-button type="danger"
  41. size="small"
  42. plain
  43. icon="el-icon-delete"
  44. v-if="permission.user_delete && !auditMode"
  45. @click="handleDelete">删 除
  46. </el-button>
  47. <!-- <el-button type="primary"
  48. size="small"
  49. plain
  50. icon="el-icon-s-operation"
  51. v-if="userInfo.role_name.includes('admin') && !auditMode"
  52. @click="handleAudit">审 核
  53. </el-button>
  54. <el-button type="success"
  55. size="small"
  56. plain
  57. icon="el-icon-check"
  58. v-if="userInfo.role_name.includes('admin') && auditMode"
  59. @click="handleAuditPass">通 过
  60. </el-button>
  61. <el-button type="danger"
  62. size="small"
  63. plain
  64. icon="el-icon-close"
  65. v-if="userInfo.role_name.includes('admin') && auditMode"
  66. @click="handleAuditRefuse">拒 绝
  67. </el-button>
  68. <el-button type="primary"
  69. size="small"
  70. plain
  71. icon="el-icon-refresh-left"
  72. v-if="userInfo.role_name.includes('admin') && auditMode"
  73. @click="handleAuditBack">返 回
  74. </el-button> -->
  75. <el-button type="info"
  76. size="small"
  77. plain
  78. v-if="permission.user_role && !auditMode"
  79. icon="el-icon-user"
  80. @click="handleGrant">角色配置
  81. </el-button>
  82. <el-button type="info"
  83. size="small"
  84. plain
  85. v-if="permission.user_reset && !auditMode"
  86. icon="el-icon-refresh"
  87. @click="handleReset">密码重置
  88. </el-button>
  89. <!-- <el-button type="info"
  90. size="small"
  91. plain
  92. v-if="userInfo.role_name.includes('admin') && !auditMode"
  93. icon="el-icon-setting"
  94. @click="handlePlatform">平台配置
  95. </el-button> -->
  96. <el-button type="info"
  97. size="small"
  98. plain
  99. v-if="userInfo.role_name.includes('admin') && !auditMode"
  100. icon="el-icon-coordinate"
  101. @click="handleLock">账号解封
  102. </el-button>
  103. <el-button type="success"
  104. size="small"
  105. plain
  106. v-if="userInfo.role_name.includes('admin') && !auditMode"
  107. icon="el-icon-upload2"
  108. @click="handleImport">导入
  109. </el-button>
  110. <el-button type="warning"
  111. size="small"
  112. plain
  113. v-if="userInfo.role_name.includes('admin') && !auditMode"
  114. icon="el-icon-download"
  115. @click="handleExport">导出
  116. </el-button>
  117. </template>
  118. <template slot-scope="{row}"
  119. slot="tenantName">
  120. <el-tag>{{row.tenantName}}</el-tag>
  121. </template>
  122. <template slot-scope="{row}"
  123. slot="roleName">
  124. <el-tag>{{row.roleName}}</el-tag>
  125. </template>
  126. <template slot-scope="{row}"
  127. slot="deptName">
  128. <el-tag>{{row.deptName}}</el-tag>
  129. </template>
  130. <template slot-scope="{row}"
  131. slot="userTypeName">
  132. <el-tag>{{row.userTypeName}}</el-tag>
  133. </template>
  134. </avue-crud>
  135. <el-dialog title="用户角色配置"
  136. append-to-body
  137. :visible.sync="roleBox"
  138. width="345px">
  139. <el-tree :data="roleGrantList"
  140. show-checkbox
  141. check-strictly
  142. default-expand-all
  143. node-key="id"
  144. ref="treeRole"
  145. :default-checked-keys="roleTreeObj"
  146. :props="props">
  147. </el-tree>
  148. <span slot="footer" class="dialog-footer">
  149. <el-button @click="roleBox = false">取 消</el-button>
  150. <el-button type="primary"
  151. @click="submitRole">确 定</el-button>
  152. </span>
  153. </el-dialog>
  154. <el-dialog title="用户数据导入"
  155. append-to-body
  156. :visible.sync="excelBox"
  157. width="555px">
  158. <avue-form :option="excelOption" v-model="excelForm" :upload-after="uploadAfter">
  159. <template slot="excelTemplate">
  160. <el-button type="primary" @click="handleTemplate">
  161. 点击下载<i class="el-icon-download el-icon--right"></i>
  162. </el-button>
  163. </template>
  164. </avue-form>
  165. </el-dialog>
  166. <el-dialog title="用户平台配置"
  167. append-to-body
  168. :visible.sync="platformBox">
  169. <avue-crud :option="platformOption"
  170. :table-loading="platformLoading"
  171. :data="platformData"
  172. ref="platformCrud"
  173. v-model="platformForm"
  174. :before-open="platformBeforeOpen"
  175. :page.sync="platformPage"
  176. :permission="platformPermissionList"
  177. @row-update="platformRowUpdate"
  178. @search-change="platformSearchChange"
  179. @search-reset="platformSearchReset"
  180. @selection-change="platformSelectionChange"
  181. @current-change="platformCurrentChange"
  182. @size-change="platformSizeChange"
  183. @refresh-change="platformRefreshChange"
  184. @on-load="platformOnLoad">
  185. <template slot-scope="{row}"
  186. slot="tenantName">
  187. <el-tag>{{row.tenantName}}</el-tag>
  188. </template>
  189. <template slot-scope="{row}"
  190. slot="userTypeName">
  191. <el-tag>{{row.userTypeName}}</el-tag>
  192. </template>
  193. </avue-crud>
  194. </el-dialog>
  195. </basic-container>
  196. </el-col>
  197. </el-row>
  198. </template>
  199. <script>
  200. import {
  201. getList,
  202. getUser,
  203. getUserPlatform,
  204. remove,
  205. update,
  206. updatePlatform,
  207. add,
  208. grant,
  209. resetPassword, unlock,
  210. auditPass, auditRefuse
  211. } from "@/api/system/user";
  212. import {exportBlob} from "@/api/common";
  213. import {getDeptTree, getDeptLazyTree} from "@/api/system/dept";
  214. import {getRoleTree} from "@/api/system/role";
  215. import {getPostList} from "@/api/system/post";
  216. import {mapGetters} from "vuex";
  217. import website from '@/config/website';
  218. import {getToken} from '@/util/auth';
  219. import {downloadXls} from "@/util/util";
  220. import {dateNow} from "@/util/date";
  221. import NProgress from 'nprogress';
  222. import 'nprogress/nprogress.css';
  223. import func from "@/util/func";
  224. import { sensitive } from '@/util/sensitive';
  225. export default {
  226. data() {
  227. const validatePass = (rule, value, callback) => {
  228. if (value === '') {
  229. callback(new Error('请输入密码'));
  230. } else {
  231. callback();
  232. }
  233. };
  234. const validatePass2 = (rule, value, callback) => {
  235. if (value === '') {
  236. callback(new Error('请再次输入密码'));
  237. } else if (value !== this.form.password) {
  238. callback(new Error('两次输入密码不一致!'));
  239. } else {
  240. callback();
  241. }
  242. };
  243. return {
  244. form: {},
  245. search:{},
  246. sensitiveManager: null,
  247. roleBox: false,
  248. excelBox: false,
  249. platformBox: false,
  250. initFlag: true,
  251. auditMode: false,
  252. selectionList: [],
  253. query: {},
  254. loading: true,
  255. platformLoading: false,
  256. page: {
  257. pageSize: 20,
  258. currentPage: 1,
  259. total: 0
  260. },
  261. platformPage: {
  262. pageSize: 10,
  263. currentPage: 1,
  264. total: 0
  265. },
  266. init: {
  267. roleTree: [],
  268. deptTree: [],
  269. },
  270. props: {
  271. label: "title",
  272. value: "key"
  273. },
  274. roleGrantList: [],
  275. roleTreeObj: [],
  276. treeDeptId: '',
  277. treeData: [],
  278. treeOption: {
  279. nodeKey: 'id',
  280. lazy: true,
  281. treeLoad: function (node, resolve) {
  282. const parentId = (node.level === 0) ? 0 : node.data.id;
  283. getDeptLazyTree(parentId).then(res => {
  284. resolve(res.data.data.map(item => {
  285. return {
  286. ...item,
  287. leaf: !item.hasChildren
  288. }
  289. }))
  290. });
  291. },
  292. addBtn: false,
  293. menu: false,
  294. size: 'small',
  295. props: {
  296. labelText: '标题',
  297. label: 'title',
  298. value: 'value',
  299. children: 'children'
  300. }
  301. },
  302. option: {
  303. height: 'auto',
  304. calcHeight: 30,
  305. tip: false,
  306. searchShow: true,
  307. searchMenuSpan: 6,
  308. border: true,
  309. index: true,
  310. selection: true,
  311. addBtn: false,
  312. viewBtn: true,
  313. dialogType: 'drawer',
  314. dialogClickModal: false,
  315. column: [
  316. {
  317. label: "登录账号",
  318. prop: "account",
  319. search: true,
  320. display: false
  321. },
  322. {
  323. label: "所属企业",
  324. prop: "tenantName",
  325. slot: true,
  326. display: false
  327. },
  328. {
  329. label: "用户姓名",
  330. prop: "realName",
  331. search: true,
  332. display: false
  333. },
  334. {
  335. label: "所属角色",
  336. prop: "roleName",
  337. slot: true,
  338. display: false
  339. },
  340. {
  341. label: "所属部门",
  342. prop: "deptName",
  343. slot: true,
  344. display: false
  345. },
  346. // {
  347. // label: "用户平台",
  348. // prop: "userTypeName",
  349. // slot: true,
  350. // display: false
  351. // },
  352. // {
  353. // label: "用户平台",
  354. // type: "select",
  355. // dicUrl: "/api/kd-system/dict/dictionary?code=user_type",
  356. // props: {
  357. // label: "dictValue",
  358. // value: "dictKey"
  359. // },
  360. // dataType: "number",
  361. // search: true,
  362. // hide: true,
  363. // display: false,
  364. // prop: "userType",
  365. // rules: [{
  366. // required: true,
  367. // message: "请选择用户平台",
  368. // trigger: "blur"
  369. // }]
  370. // },
  371. ],
  372. group: [
  373. {
  374. label: '基础信息',
  375. prop: 'baseInfo',
  376. icon: 'el-icon-user-solid',
  377. column: [
  378. // {
  379. // label: "所属租户",
  380. // prop: "tenantId",
  381. // type: "tree",
  382. // dicUrl: "/api/kd-system/tenant/select",
  383. // props: {
  384. // label: "tenantName",
  385. // value: "tenantId"
  386. // },
  387. // hide: !website.tenantMode,
  388. // addDisplay: website.tenantMode,
  389. // editDisplay: website.tenantMode,
  390. // viewDisplay: website.tenantMode,
  391. // rules: [{
  392. // required: true,
  393. // message: "请输入所属租户",
  394. // trigger: "click"
  395. // }],
  396. // span: 24,
  397. // },
  398. {
  399. label: "登录账号",
  400. prop: "account",
  401. rules: [{
  402. required: true,
  403. message: "请输入登录账号",
  404. trigger: "blur"
  405. }],
  406. },
  407. // {
  408. // label: "用户平台",
  409. // type: "select",
  410. // dicUrl: "/api/kd-system/dict/dictionary?code=user_type",
  411. // props: {
  412. // label: "dictValue",
  413. // value: "dictKey"
  414. // },
  415. // dataType: "number",
  416. // slot: true,
  417. // prop: "userType",
  418. // rules: [{
  419. // required: true,
  420. // message: "请选择用户平台",
  421. // trigger: "blur"
  422. // }]
  423. // },
  424. {
  425. label: '密码',
  426. prop: 'password',
  427. hide: true,
  428. editDisplay: false,
  429. viewDisplay: false,
  430. rules: [{required: true, validator: validatePass, trigger: 'blur'}]
  431. },
  432. {
  433. label: '确认密码',
  434. prop: 'password2',
  435. hide: true,
  436. editDisplay: false,
  437. viewDisplay: false,
  438. rules: [{required: true, validator: validatePass2, trigger: 'blur'}]
  439. },
  440. ]
  441. },
  442. {
  443. label: '详细信息',
  444. prop: 'detailInfo',
  445. icon: 'el-icon-s-order',
  446. column: [
  447. {
  448. label: "用户昵称",
  449. prop: "name",
  450. hide: true,
  451. rules: [{
  452. required: true,
  453. message: "请输入用户昵称",
  454. trigger: "blur"
  455. }]
  456. },
  457. {
  458. label: "用户姓名",
  459. prop: "realName",
  460. rules: [{
  461. required: true,
  462. message: "请输入用户姓名",
  463. trigger: "blur"
  464. }, {
  465. min: 2,
  466. max: 10,
  467. message: '姓名长度在2到5个字符'
  468. }]
  469. },
  470. {
  471. label: "手机号码",
  472. prop: "phone",
  473. overHidden: true
  474. },
  475. // {
  476. // label: "电子邮箱",
  477. // prop: "email",
  478. // hide: true,
  479. // overHidden: true
  480. // },
  481. {
  482. label: "用户性别",
  483. prop: "sex",
  484. type: "select",
  485. dicData: [
  486. {
  487. label: "男",
  488. value: 1
  489. },
  490. {
  491. label: "女",
  492. value: 2
  493. },
  494. {
  495. label: "未知",
  496. value: 3
  497. }
  498. ],
  499. hide: true
  500. },
  501. // {
  502. // label: "用户生日",
  503. // type: "date",
  504. // prop: "birthday",
  505. // format: "yyyy-MM-dd hh:mm:ss",
  506. // valueFormat: "yyyy-MM-dd hh:mm:ss",
  507. // hide: true
  508. // },
  509. {
  510. label: "账号状态",
  511. prop: "statusName",
  512. hide: false,
  513. display: true
  514. }
  515. ]
  516. },
  517. {
  518. label: '职责信息',
  519. prop: 'dutyInfo',
  520. icon: 'el-icon-s-custom',
  521. column: [
  522. {
  523. label: "用户编号",
  524. prop: "code",
  525. },
  526. {
  527. label: "所属角色",
  528. prop: "roleId",
  529. multiple: true,
  530. type: "tree",
  531. dicData: [],
  532. props: {
  533. label: "title"
  534. },
  535. checkStrictly: true,
  536. slot: true,
  537. rules: [{
  538. required: true,
  539. message: "请选择所属角色",
  540. trigger: "click"
  541. }]
  542. },
  543. {
  544. label: "所属部门",
  545. prop: "deptId",
  546. type: "tree",
  547. multiple: true,
  548. dicData: [],
  549. props: {
  550. label: "title"
  551. },
  552. checkStrictly: true,
  553. slot: true,
  554. rules: [{
  555. required: true,
  556. message: "请选择所属部门",
  557. trigger: "click"
  558. }]
  559. },
  560. {
  561. label: "所属岗位",
  562. prop: "postId",
  563. type: "tree",
  564. multiple: true,
  565. dicData: [],
  566. props: {
  567. label: "postName",
  568. value: "id"
  569. },
  570. rules: [{
  571. required: true,
  572. message: "请选择所属岗位",
  573. trigger: "click"
  574. }],
  575. },
  576. ]
  577. },
  578. ]
  579. },
  580. data: [],
  581. platformQuery: {},
  582. platformSelectionList: [],
  583. platformData: [],
  584. platformForm: {},
  585. platformOption: {
  586. tip: false,
  587. searchShow: true,
  588. searchMenuSpan: 6,
  589. border: true,
  590. index: true,
  591. selection: true,
  592. viewBtn: true,
  593. dialogClickModal: false,
  594. menuWidth: 120,
  595. editBtnText: '配置',
  596. column: [
  597. {
  598. label: "登录账号",
  599. prop: "account",
  600. search: true,
  601. display: false
  602. },
  603. {
  604. label: "所属租户",
  605. prop: "tenantName",
  606. slot: true,
  607. display: false
  608. },
  609. {
  610. label: "用户姓名",
  611. prop: "realName",
  612. search: true,
  613. display: false
  614. },
  615. {
  616. label: "用户平台",
  617. prop: "userTypeName",
  618. slot: true,
  619. display: false
  620. },
  621. {
  622. label: "用户平台",
  623. type: "select",
  624. dicUrl: "/api/kd-system/dict/dictionary?code=user_type",
  625. props: {
  626. label: "dictValue",
  627. value: "dictKey"
  628. },
  629. dataType: "number",
  630. search: true,
  631. hide: true,
  632. display: false,
  633. prop: "userType",
  634. rules: [{
  635. required: true,
  636. message: "请选择用户平台",
  637. trigger: "blur"
  638. }]
  639. },
  640. {
  641. label: "用户拓展",
  642. prop: "userExt",
  643. type: "textarea",
  644. minRows: 8,
  645. span: 24,
  646. overHidden: true,
  647. row: true,
  648. hide: true,
  649. },
  650. ],
  651. },
  652. excelForm: {},
  653. excelOption: {
  654. submitBtn: false,
  655. emptyBtn: false,
  656. column: [
  657. {
  658. label: '模板上传',
  659. prop: 'excelFile',
  660. type: 'upload',
  661. drag: true,
  662. loadText: '模板上传中,请稍等',
  663. span: 24,
  664. propsHttp: {
  665. res: 'data'
  666. },
  667. tip: '请上传 .xls,.xlsx 标准格式文件',
  668. action: "/api/kd-system/user/import-user"
  669. },
  670. {
  671. label: "数据覆盖",
  672. prop: "isCovered",
  673. type: "switch",
  674. align: "center",
  675. width: 80,
  676. dicData: [
  677. {
  678. label: "否",
  679. value: 0
  680. },
  681. {
  682. label: "是",
  683. value: 1
  684. }
  685. ],
  686. value: 0,
  687. slot: true,
  688. rules: [
  689. {
  690. required: true,
  691. message: "请选择是否覆盖",
  692. trigger: "blur"
  693. }
  694. ]
  695. },
  696. {
  697. label: '模板下载',
  698. prop: 'excelTemplate',
  699. formslot: true,
  700. span: 24,
  701. }
  702. ]
  703. }
  704. };
  705. },
  706. watch: {
  707. 'form.tenantId'() {
  708. if (this.form.tenantId !== '' && this.initFlag) {
  709. this.initData(this.form.tenantId);
  710. }
  711. },
  712. 'excelForm.isCovered'() {
  713. if (this.excelForm.isCovered !== '') {
  714. const column = this.findObject(this.excelOption.column, "excelFile");
  715. column.action = `/api/kd-system/user/import-user?isCovered=${this.excelForm.isCovered}`;
  716. }
  717. }
  718. },
  719. computed: {
  720. ...mapGetters(["userInfo", "permission"]),
  721. permissionList() {
  722. return {
  723. addBtn: this.vaildData(this.permission.user_add, false),
  724. viewBtn: this.vaildData(this.permission.user_view, false),
  725. delBtn: this.vaildData(this.permission.user_delete, false),
  726. editBtn: this.vaildData(this.permission.user_edit, false)
  727. };
  728. },
  729. platformPermissionList() {
  730. return {
  731. addBtn: false,
  732. viewBtn: false,
  733. delBtn: false,
  734. editBtn: this.vaildData(this.permission.user_edit, false)
  735. };
  736. },
  737. ids() {
  738. let ids = [];
  739. this.selectionList.forEach(ele => {
  740. ids.push(ele.id);
  741. });
  742. return ids.join(",");
  743. },
  744. },
  745. mounted() {
  746. // 非租户模式默认加载管理组数据
  747. if (!website.tenantMode) {
  748. this.initData(website.tenantId);
  749. }
  750. },
  751. created() {
  752. // 创建脱敏工具实例
  753. this.sensitiveManager = sensitive.create({
  754. fields: ['phone', 'email'], // 配置需要脱敏的字段
  755. });
  756. },
  757. methods: {
  758. nodeClick(data) {
  759. this.treeDeptId = data.id;
  760. this.page.currentPage = 1;
  761. this.onLoad(this.page);
  762. },
  763. initData(tenantId) {
  764. getRoleTree(tenantId).then(res => {
  765. const column = this.findObject(this.option.group, "roleId");
  766. column.dicData = res.data.data;
  767. });
  768. getDeptTree(tenantId).then(res => {
  769. const column = this.findObject(this.option.group, "deptId");
  770. column.dicData = res.data.data;
  771. });
  772. getPostList(tenantId).then(res => {
  773. const column = this.findObject(this.option.group, "postId");
  774. column.dicData = res.data.data;
  775. });
  776. },
  777. submitRole() {
  778. const roleList = this.$refs.treeRole.getCheckedKeys().join(",");
  779. grant(this.ids, roleList).then(() => {
  780. this.roleBox = false;
  781. this.$message({
  782. type: "success",
  783. message: "操作成功!"
  784. });
  785. this.onLoad(this.page);
  786. });
  787. },
  788. rowSave(row, done, loading) {
  789. row.deptId = func.join(row.deptId);
  790. row.roleId = func.join(row.roleId);
  791. row.postId = func.join(row.postId);
  792. add(row).then(() => {
  793. this.initFlag = false;
  794. this.onLoad(this.page);
  795. this.$message({
  796. type: "success",
  797. message: "操作成功!"
  798. });
  799. done();
  800. }, error => {
  801. window.console.log(error);
  802. loading();
  803. });
  804. },
  805. rowUpdate(row, index, done, loading) {
  806. row.deptId = func.join(row.deptId);
  807. row.roleId = func.join(row.roleId);
  808. row.postId = func.join(row.postId);
  809. // 获取需要提交的数据
  810. const submitData = this.sensitiveManager.getSubmitData(row);
  811. update(submitData).then(() => {
  812. this.initFlag = false;
  813. this.onLoad(this.page);
  814. this.$message({
  815. type: "success",
  816. message: "操作成功!"
  817. });
  818. done();
  819. }, error => {
  820. window.console.log(error);
  821. loading();
  822. });
  823. },
  824. rowDel(row) {
  825. this.$confirm("确定将选择数据删除?", {
  826. confirmButtonText: "确定",
  827. cancelButtonText: "取消",
  828. type: "warning"
  829. })
  830. .then(() => {
  831. return remove(row.id);
  832. })
  833. .then(() => {
  834. this.onLoad(this.page);
  835. this.$message({
  836. type: "success",
  837. message: "操作成功!"
  838. });
  839. });
  840. },
  841. searchReset() {
  842. this.query = {};
  843. this.treeDeptId = '';
  844. this.onLoad(this.page);
  845. },
  846. searchChange(params, done) {
  847. this.query = params;
  848. this.page.currentPage = 1;
  849. this.onLoad(this.page, params);
  850. done();
  851. },
  852. selectionChange(list) {
  853. this.selectionList = list;
  854. },
  855. selectionClear() {
  856. this.selectionList = [];
  857. this.$refs.crud.toggleSelection();
  858. },
  859. handleDelete() {
  860. if (this.selectionList.length === 0) {
  861. this.$message.warning("请选择至少一条数据");
  862. return;
  863. }
  864. this.$confirm("确定将选择数据删除?", {
  865. confirmButtonText: "确定",
  866. cancelButtonText: "取消",
  867. type: "warning"
  868. })
  869. .then(() => {
  870. return remove(this.ids);
  871. })
  872. .then(() => {
  873. this.onLoad(this.page);
  874. this.$message({
  875. type: "success",
  876. message: "操作成功!"
  877. });
  878. this.$refs.crud.toggleSelection();
  879. });
  880. },
  881. handleAudit() {
  882. this.auditMode = true;
  883. this.onLoad(this.page, this.query);
  884. },
  885. handleAuditPass() {
  886. if (this.selectionList.length === 0) {
  887. this.$message.warning('请选择至少一条数据');
  888. return;
  889. }
  890. this.$confirm('确定将选择数据通过审核?', {
  891. confirmButtonText: '确定',
  892. cancelButtonText: '取消',
  893. type: 'warning',
  894. })
  895. .then(() => {
  896. return auditPass(this.ids);
  897. })
  898. .then(() => {
  899. this.onLoad(this.page);
  900. this.$message({
  901. type: 'success',
  902. message: '操作成功!',
  903. });
  904. this.$refs.crud.toggleSelection();
  905. });
  906. },
  907. handleAuditRefuse() {
  908. if (this.selectionList.length === 0) {
  909. this.$message.warning('请选择至少一条数据');
  910. return;
  911. }
  912. this.$confirm('确定将选择数据拒绝审核?', {
  913. confirmButtonText: '确定',
  914. cancelButtonText: '取消',
  915. type: 'warning',
  916. })
  917. .then(() => {
  918. return auditRefuse(this.ids);
  919. })
  920. .then(() => {
  921. this.onLoad(this.page);
  922. this.$message({
  923. type: 'success',
  924. message: '操作成功!',
  925. });
  926. this.$refs.crud.toggleSelection();
  927. });
  928. },
  929. handleAuditBack() {
  930. this.auditMode = false;
  931. this.onLoad(this.page, this.query);
  932. },
  933. handleReset() {
  934. if (this.selectionList.length === 0) {
  935. this.$message.warning("请选择至少一条数据");
  936. return;
  937. }
  938. this.$confirm("确定将选择账号密码重置为kd2025!?", {
  939. confirmButtonText: "确定",
  940. cancelButtonText: "取消",
  941. type: "warning"
  942. })
  943. .then(() => {
  944. return resetPassword(this.ids);
  945. })
  946. .then(() => {
  947. this.$message({
  948. type: "success",
  949. message: "操作成功!"
  950. });
  951. this.$refs.crud.toggleSelection();
  952. });
  953. },
  954. handleGrant() {
  955. if (this.selectionList.length === 0) {
  956. this.$message.warning("请选择至少一条数据");
  957. return;
  958. }
  959. this.roleTreeObj = [];
  960. if (this.selectionList.length === 1) {
  961. this.roleTreeObj = this.selectionList[0].roleId.split(",");
  962. }
  963. getRoleTree().then(res => {
  964. this.roleGrantList = res.data.data;
  965. this.roleBox = true;
  966. });
  967. },
  968. handlePlatform() {
  969. this.platformBox = true;
  970. },
  971. handleLock() {
  972. if (this.selectionList.length === 0) {
  973. this.$message.warning("请选择至少一条数据");
  974. return;
  975. }
  976. this.$confirm("确定将选择账号解封?", {
  977. confirmButtonText: "确定",
  978. cancelButtonText: "取消",
  979. type: "warning"
  980. })
  981. .then(() => {
  982. return unlock(this.ids);
  983. })
  984. .then(() => {
  985. this.$message({
  986. type: "success",
  987. message: "操作成功!"
  988. });
  989. });
  990. },
  991. handleImport() {
  992. this.excelBox = true;
  993. },
  994. uploadAfter(res, done, loading, column) {
  995. window.console.log(column);
  996. this.excelBox = false;
  997. this.refreshChange();
  998. done();
  999. },
  1000. handleExport() {
  1001. const account = func.toStr(this.search.account);
  1002. const realName = func.toStr(this.search.realName);
  1003. this.$confirm("是否导出用户数据?", "提示", {
  1004. confirmButtonText: "确定",
  1005. cancelButtonText: "取消",
  1006. type: "warning"
  1007. }).then(() => {
  1008. NProgress.start();
  1009. exportBlob(`/api/kd-system/user/export-user?${this.website.tokenHeader}=${getToken()}&account=${account}&realName=${realName}`).then(res => {
  1010. downloadXls(res.data, `用户数据表${dateNow()}.xlsx`);
  1011. NProgress.done();
  1012. })
  1013. });
  1014. },
  1015. handleTemplate() {
  1016. exportBlob(`/api/kd-system/user/export-template?${this.website.tokenHeader}=${getToken()}`).then(res => {
  1017. downloadXls(res.data, "用户数据模板.xlsx");
  1018. })
  1019. },
  1020. beforeOpen(done, type) {
  1021. if (["edit", "view"].includes(type)) {
  1022. getUser(this.form.id).then(res => {
  1023. this.form = res.data.data;
  1024. if (this.form.hasOwnProperty('deptId')) {
  1025. this.form.deptId = func.split(this.form.deptId);
  1026. }
  1027. if (this.form.hasOwnProperty('roleId')) {
  1028. this.form.roleId = func.split(this.form.roleId);
  1029. }
  1030. if (this.form.hasOwnProperty('postId')) {
  1031. this.form.postId = func.split(this.form.postId);
  1032. }
  1033. // 保存初始脱敏数据
  1034. this.sensitiveManager.saveInitialData(this.form);
  1035. });
  1036. }
  1037. this.initFlag = true;
  1038. done();
  1039. },
  1040. currentChange(currentPage) {
  1041. this.page.currentPage = currentPage;
  1042. },
  1043. sizeChange(pageSize) {
  1044. this.page.pageSize = pageSize;
  1045. },
  1046. refreshChange() {
  1047. this.onLoad(this.page, this.query);
  1048. },
  1049. onLoad(page, params = {}) {
  1050. this.loading = true;
  1051. getList(
  1052. page.currentPage,
  1053. page.pageSize,
  1054. Object.assign(params, this.query, { status: this.auditMode ? 0 : 1 }),
  1055. this.treeDeptId
  1056. ).then(res => {
  1057. const data = res.data.data;
  1058. this.page.total = data.total;
  1059. this.data = data.records;
  1060. this.loading = false;
  1061. this.selectionClear();
  1062. });
  1063. },
  1064. platformRowUpdate(row, index, done, loading) {
  1065. updatePlatform(row.id, row.userType, row.userExt).then(() => {
  1066. this.platformOnLoad(this.platformPage);
  1067. this.$message({
  1068. type: "success",
  1069. message: "操作成功!"
  1070. });
  1071. done();
  1072. }, error => {
  1073. window.console.log(error);
  1074. loading();
  1075. });
  1076. },
  1077. platformBeforeOpen(done, type) {
  1078. if (["edit", "view"].includes(type)) {
  1079. getUserPlatform(this.platformForm.id).then(res => {
  1080. this.platformForm = res.data.data;
  1081. });
  1082. }
  1083. done();
  1084. },
  1085. platformSearchReset() {
  1086. this.platformQuery = {};
  1087. this.platformOnLoad(this.platformPage);
  1088. },
  1089. platformSearchChange(params, done) {
  1090. this.platformQuery = params;
  1091. this.platformPage.currentPage = 1;
  1092. this.platformOnLoad(this.platformPage, params);
  1093. done();
  1094. },
  1095. platformSelectionChange(list) {
  1096. this.platformSelectionList = list;
  1097. },
  1098. platformSelectionClear() {
  1099. this.platformSelectionList = [];
  1100. this.$refs.platformCrud.toggleSelection();
  1101. },
  1102. platformCurrentChange(currentPage) {
  1103. this.platformPage.currentPage = currentPage;
  1104. },
  1105. platformSizeChange(pageSize) {
  1106. this.platformPage.pageSize = pageSize;
  1107. },
  1108. platformRefreshChange() {
  1109. this.platformOnLoad(this.platformPage, this.platformQuery);
  1110. },
  1111. platformOnLoad(page, params = {}) {
  1112. this.platformLoading = true;
  1113. getList(page.currentPage, page.pageSize, Object.assign(params, this.query), this.treeDeptId).then(res => {
  1114. const data = res.data.data;
  1115. this.platformPage.total = data.total;
  1116. this.platformData = data.records;
  1117. this.platformLoading = false;
  1118. this.selectionClear();
  1119. });
  1120. }
  1121. }
  1122. };
  1123. </script>
  1124. <style>
  1125. .box {
  1126. height: 800px;
  1127. }
  1128. .el-scrollbar {
  1129. height: 100%;
  1130. }
  1131. .box .el-scrollbar__wrap {
  1132. overflow: scroll;
  1133. }
  1134. </style>