index.vue 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999
  1. <template>
  2. <div class="user">
  3. <div class="tree">
  4. <div class="treeList">
  5. <div class="title commons-title">
  6. 组织架构
  7. </div>
  8. <div class="search">
  9. <el-input v-model="search" placeholder="请输入搜索内容" clearable @clear="search = ''" @keyup.enter="searchChange"></el-input>
  10. </div>
  11. <div class="box">
  12. <el-tree :data="treeData" ref="tree" node-key="deptId" @node-click="treeChange" default-expand-all :expand-on-click-node="false"
  13. :filter-node-method="filterNode">
  14. <template #default="{ node, data }">
  15. <div>{{data.deptName}}</div>
  16. </template>
  17. </el-tree>
  18. </div>
  19. </div>
  20. </div>
  21. <div class="content">
  22. <byTable :source="sourceList.data" :pagination="sourceList.pagination" :config="config" :loading="loading" highlight-current-row :action-list="[
  23. {
  24. text: '添加用户',
  25. action: () => openModal(),
  26. },
  27. ]" @get-list="getList">
  28. <template #deptName="{ item }">
  29. <div style="width: 100%">
  30. <span v-for="(name,index) in item.deptNameList" :key="index">
  31. {{name}}
  32. <span v-if="index < item.deptNameList.length-1">=></span>
  33. </span>
  34. </div>
  35. </template>
  36. <template #roles="{ item }">
  37. <div style="width: 100%">
  38. <span v-for="(role,index) in item.sysRoleList" :key="role.roleId">
  39. {{role.roleName}}
  40. <span v-if="index < item.sysRoleList.length-1">,</span>
  41. </span>
  42. </div>
  43. </template>
  44. <template #status="{item}">
  45. <div style="width:100%">
  46. <span :style="{color:item.status==1?'red':''}">{{item.status==1?'停用':'启用'}}</span>
  47. </div>
  48. </template>
  49. </byTable>
  50. </div>
  51. <el-dialog :title="modalType == 'add' ? '添加用户' : '编辑用户'" v-if="dialogVisible" v-model="dialogVisible" width="50%" v-loading="loadingDialog">
  52. <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="submit">
  53. <template #deptId>
  54. <div style="width: 100%">
  55. <el-tree-select v-model="formData.data.deptId" :data="deptList" check-strictly :render-after-expand="false" node-key="deptId"
  56. :props="defaultProps" style="width:100%" @change="handleDeptIdChange" />
  57. </div>
  58. </template>
  59. <template #account>
  60. <el-input style="width: 42%; margin-right: 10px" v-model="formData.data.userName" @change="changeUserName" placeholder="请输入用户名"></el-input>
  61. <el-input style="width: 42%; margin-right: 10px" v-model="formData.data.password" @change="changePassword" placeholder="密码"></el-input>
  62. <span style="color: #409eff; cursor: pointer" @click="newPassword">随机生成</span>
  63. </template>
  64. <template #purchaseScope>
  65. <div style="width:100%">
  66. <el-tree :data="productTreeData" show-checkbox node-key="id" :default-checked-keys="formData.data.purchaseRangeOne"
  67. :props="defaultPropsOne" ref="productTree">
  68. </el-tree>
  69. </div>
  70. </template>
  71. <template #detail>
  72. <div style="width:100%;padding-left:25px">
  73. <el-button type="primary" @click="handleAdd()" plain style="margin-bottom: 16px">添加</el-button>
  74. <el-table :data="formData.data.identityList" style="width: 100%;">
  75. <el-table-column label="职级" prop="identity">
  76. <template #default="{ row, $index }">
  77. <div style="width: 100%">
  78. <el-form-item :prop="'identityList.' + $index + '.identity'" :rules="rules.identity" :inline-message="true"
  79. class="margin-b-0 wid100">
  80. <el-select v-model="row.identity" placeholder="请选择" style="width: 100%">
  81. <el-option v-for="item in rankData" :key="item.value" :label="item.label" :value="item.value" />
  82. </el-select>
  83. </el-form-item>
  84. </div>
  85. </template>
  86. </el-table-column>
  87. <el-table-column label="部门" prop="deptId">
  88. <template #default="{ row, $index }">
  89. <div style="width: 100%">
  90. <el-form-item :prop="'identityList.' + $index + '.deptId'" :rules="rules.deptId" :inline-message="true" class="margin-b-0 wid100">
  91. <el-tree-select v-model="row.deptId" :data="deptListOne" check-strictly :render-after-expand="false" node-key="deptId"
  92. :props="defaultProps" style="width:100%" />
  93. </el-form-item>
  94. </div>
  95. </template>
  96. </el-table-column>
  97. <el-table-column label="操作" width="60" align="center" fixed="right">
  98. <template #default="{ $index }">
  99. <el-button type="primary" link @click="handleRemove($index)">删除</el-button>
  100. </template>
  101. </el-table-column>
  102. </el-table>
  103. </div>
  104. </template>
  105. </byForm>
  106. <template #footer>
  107. <el-button @click="dialogVisible = false" size="default">取 消</el-button>
  108. <el-button type="primary" @click="submitForm()" size="default">确 定</el-button>
  109. </template>
  110. </el-dialog>
  111. <el-dialog title="修改密码" v-if="roomDialogVisible" v-model="roomDialogVisible" width="500" v-loading="loading">
  112. <div>
  113. <el-input v-model="password" placeholder="请输入新密码" @change="changePassword2" />
  114. </div>
  115. <template #footer>
  116. <el-button @click="roomDialogVisible = false" size="default">取 消</el-button>
  117. <el-button type="primary" @click="submitPassword(password)" size="default" :loading="submitLoading">确 定</el-button>
  118. </template>
  119. </el-dialog>
  120. </div>
  121. </template>
  122. <script setup>
  123. import { computed, ref } from "vue";
  124. import byTable from "@/components/byTable/index";
  125. import { ElMessage, ElMessageBox } from "element-plus";
  126. import byForm from "@/components/byForm/index";
  127. import useUserStore from "@/store/modules/user";
  128. const { proxy } = getCurrentInstance();
  129. const defaultProps = {
  130. children: "children",
  131. label: "deptName",
  132. disabled: "disabled",
  133. };
  134. const defaultPropsOne = {
  135. children: "children",
  136. label: "name",
  137. };
  138. const deptList = ref([]);
  139. const deptListOne = ref([]);
  140. const rankData = ref([
  141. {
  142. label: "员工",
  143. value: 10,
  144. },
  145. {
  146. label: "主管",
  147. value: 20,
  148. },
  149. {
  150. label: "经理",
  151. value: 30,
  152. },
  153. {
  154. label: "总监",
  155. value: 40,
  156. },
  157. ]);
  158. const sourceList = ref({
  159. data: [],
  160. pagination: {
  161. total: 0,
  162. pageNum: 1,
  163. pageSize: 10,
  164. keyword: "",
  165. tenantId: proxy.useUserStore().user.tenantId,
  166. deptId: "",
  167. },
  168. });
  169. const loading = ref(false);
  170. const config = computed(() => {
  171. return [
  172. {
  173. attrs: {
  174. label: "部门",
  175. prop: "deptName",
  176. slot: "deptName",
  177. width: 250,
  178. },
  179. },
  180. {
  181. attrs: {
  182. label: "姓名",
  183. prop: "nickName",
  184. align: "left",
  185. width: 120,
  186. },
  187. },
  188. // {
  189. // attrs: {
  190. // label: "英文名",
  191. // prop: "nickNameEn",
  192. // align: "left",
  193. // width: 150,
  194. // },
  195. // },
  196. {
  197. attrs: {
  198. label: "用户名",
  199. prop: "userName",
  200. width: 120,
  201. },
  202. },
  203. {
  204. attrs: {
  205. label: "角色",
  206. slot: "roles",
  207. "min-width": 120,
  208. },
  209. },
  210. {
  211. attrs: {
  212. label: "系统用户",
  213. prop: "userType",
  214. width: 80,
  215. },
  216. render(userType) {
  217. return userType == 1 ? "是" : "否";
  218. },
  219. },
  220. {
  221. attrs: {
  222. label: "账号状态",
  223. prop: "status",
  224. slot: "status",
  225. width: 80,
  226. },
  227. render(status) {
  228. return status == 1 ? "停用" : "启用";
  229. },
  230. },
  231. {
  232. attrs: {
  233. label: "手机号",
  234. prop: "phonenumber",
  235. width: 150,
  236. },
  237. },
  238. {
  239. attrs: {
  240. label: "工号",
  241. prop: "jobNumber",
  242. width: 120,
  243. },
  244. },
  245. {
  246. attrs: {
  247. label: "操作",
  248. width: "180",
  249. align: "center",
  250. },
  251. renderHTML(row) {
  252. return [
  253. {
  254. attrs: {
  255. label: "修改密码",
  256. type: "primary",
  257. text: true,
  258. },
  259. el: "button",
  260. click() {
  261. userId.value = row.userId;
  262. password.value = "";
  263. roomDialogVisible.value = true;
  264. },
  265. },
  266. {
  267. attrs: {
  268. label: "修改",
  269. type: "primary",
  270. text: true,
  271. },
  272. el: "button",
  273. click() {
  274. getDtl(row);
  275. },
  276. },
  277. {
  278. attrs: {
  279. label: "删除",
  280. type: "danger",
  281. text: true,
  282. },
  283. el: "button",
  284. click() {
  285. ElMessageBox.confirm(
  286. "此操作将永久删除该数据, 是否继续?",
  287. "提示",
  288. {
  289. confirmButtonText: "确定",
  290. cancelButtonText: "取消",
  291. type: "warning",
  292. }
  293. ).then(() => {
  294. proxy
  295. .post(
  296. "/tenantUser/" + row.userId,
  297. {
  298. id: row.userId,
  299. },
  300. "delete"
  301. )
  302. .then(() => {
  303. ElMessage({
  304. message: "删除成功",
  305. type: "success",
  306. });
  307. getList();
  308. });
  309. });
  310. },
  311. },
  312. ];
  313. },
  314. },
  315. ];
  316. });
  317. const getList = async (req) => {
  318. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  319. loading.value = true;
  320. proxy.get("/tenantUser/list", sourceList.value.pagination).then((res) => {
  321. res.rows.map((item) => {
  322. item.deptName = item.dept ? item.dept.deptName : item.dept;
  323. });
  324. sourceList.value.data = res.rows;
  325. sourceList.value.pagination.total = res.total;
  326. setTimeout(() => {
  327. loading.value = false;
  328. }, 200);
  329. });
  330. };
  331. getList();
  332. const modalType = ref("add");
  333. const dialogVisible = ref(false);
  334. const loadingDialog = ref(false);
  335. const roleData = ref([]);
  336. const productTree = ref(null);
  337. const productTreeData = ref([]);
  338. const companyData = ref([]);
  339. const submit = ref(null);
  340. const isShowPurchaseAtt = ref(false);
  341. const formOption = reactive({
  342. inline: true,
  343. labelWidth: 100,
  344. itemWidth: 100,
  345. rules: [],
  346. });
  347. const formData = reactive({
  348. data: {},
  349. });
  350. const formConfig = computed(() => {
  351. return [
  352. {
  353. type: "title1",
  354. title: "基本信息",
  355. },
  356. {
  357. type: "slot",
  358. prop: "deptId",
  359. slotName: "deptId",
  360. label: "部门名称",
  361. },
  362. {
  363. type: "input",
  364. prop: "nickName",
  365. label: "姓名",
  366. itemWidth: 50,
  367. },
  368. {
  369. type: "input",
  370. prop: "nickNameEn",
  371. label: "英文名",
  372. itemWidth: 50,
  373. },
  374. {
  375. type: "slot",
  376. prop: "userName",
  377. slotName: "account",
  378. label: "账户信息",
  379. },
  380. {
  381. type: "select",
  382. label: "角色",
  383. prop: "roleIds",
  384. multiple: true,
  385. data: roleData.value,
  386. fn: (val) => {
  387. changeRoleId(val);
  388. },
  389. },
  390. {
  391. type: "select",
  392. label: "关联公司",
  393. prop: "companySet",
  394. multiple: true,
  395. clearable: false,
  396. data: companyData.value,
  397. },
  398. {
  399. type: "radio",
  400. prop: "userType",
  401. label: "系统用户",
  402. required: true,
  403. disabled: true,
  404. border: true,
  405. data: [
  406. {
  407. label: "是",
  408. id: 1,
  409. },
  410. {
  411. label: "否",
  412. id: 0,
  413. },
  414. ],
  415. itemWidth: 50,
  416. },
  417. {
  418. type: "select",
  419. label: "账号状态",
  420. prop: "status",
  421. multiple: false,
  422. data: [
  423. {
  424. label: "启用",
  425. value: "0",
  426. },
  427. {
  428. label: "停用",
  429. value: "1",
  430. },
  431. ],
  432. },
  433. {
  434. type: "select",
  435. label: "身份",
  436. prop: "identity",
  437. multiple: false,
  438. data: [
  439. {
  440. label: "职员",
  441. value: 10,
  442. },
  443. {
  444. label: "股东",
  445. value: 20,
  446. },
  447. ],
  448. itemWidth: 100,
  449. },
  450. {
  451. type: "input",
  452. prop: "phonenumber",
  453. label: "手机号",
  454. required: true,
  455. itemWidth: 50,
  456. itemType: "text",
  457. },
  458. {
  459. type: "input",
  460. prop: "jobNumber",
  461. label: "工号",
  462. required: true,
  463. itemWidth: 50,
  464. itemType: "text",
  465. },
  466. {
  467. type: "input",
  468. prop: "jdSubjectCode",
  469. label: "金蝶核算项目编号",
  470. itemWidth: 50,
  471. },
  472. {
  473. type: "input",
  474. prop: "jdSubjectName",
  475. label: "金蝶核算项目名称",
  476. itemWidth: 50,
  477. },
  478. {
  479. type: "input",
  480. prop: "accountBank",
  481. label: "开户行",
  482. placeholder: "请输入开户行",
  483. itemWidth: 100,
  484. },
  485. {
  486. type: "input",
  487. prop: "accountName",
  488. label: "开户名",
  489. placeholder: "请输入开户名",
  490. itemWidth: 100,
  491. },
  492. {
  493. type: "input",
  494. prop: "accountNumber",
  495. label: "账号",
  496. placeholder: "请输入账号",
  497. itemWidth: 100,
  498. },
  499. {
  500. type: "slot",
  501. slotName: "purchaseScope",
  502. label: "采购范围",
  503. // placeholder: "请输入账号",
  504. itemWidth: 100,
  505. isShow: isShowPurchaseAtt.value,
  506. },
  507. {
  508. type: "title1",
  509. title: "职级明细",
  510. },
  511. {
  512. type: "slot",
  513. slotName: "detail",
  514. label: "",
  515. },
  516. ];
  517. });
  518. const rules = ref({
  519. deptId: [{ required: true, message: "请选择部门", trigger: "change" }],
  520. nickName: [{ required: true, message: "请输入姓名", trigger: "blur" }],
  521. userName: [{ required: true, message: "请输入用户名", trigger: "blur" }],
  522. roleIds: [{ required: true, message: "请选择角色", trigger: "change" }],
  523. phonenumber: [{ required: true, message: "请输入手机号", trigger: "blur" }],
  524. companySet: [
  525. { required: true, message: "请选择关联公司", trigger: "change" },
  526. ],
  527. identity: [{ required: true, message: "请选择", trigger: "change" }],
  528. status: [{ required: true, message: "请选择账号状态", trigger: "change" }],
  529. });
  530. const changeRoleId = (val) => {
  531. if (val && val.length > 0) {
  532. for (let i = 0; i < roleData.value.length; i++) {
  533. const role = roleData.value[i];
  534. for (let j = 0; j < val.length; j++) {
  535. const roleId = val[j];
  536. if (role.id == roleId) {
  537. if (role.label.indexOf("采购") != -1) {
  538. isShowPurchaseAtt.value = true;
  539. return;
  540. }
  541. }
  542. }
  543. }
  544. isShowPurchaseAtt.value = false;
  545. } else {
  546. isShowPurchaseAtt.value = false;
  547. }
  548. };
  549. const arrayRecursion = (arr, definition) => {
  550. arr.forEach((item) => {
  551. item.definition = definition;
  552. if (item.children && item.children.length > 0) {
  553. arrayRecursion(item.children, definition);
  554. }
  555. });
  556. return arr;
  557. };
  558. const allData = ref([]);
  559. const getSubset = (list, data) => {
  560. for (let i = 0; i < list.length; i++) {
  561. if (list[i].children && list[i].children.length > 0) {
  562. getSubset(list[i].children, data);
  563. } else {
  564. data.push(list[i].id);
  565. }
  566. }
  567. return data;
  568. };
  569. const getUserList = () => {
  570. proxy
  571. .get(
  572. `/tenantRole/list?pageNum=1&pageSize=10000&tenantId=${sourceList.value.pagination.tenantId}`
  573. )
  574. .then((message) => {
  575. roleData.value = message.rows.map((item) => {
  576. return {
  577. ...item,
  578. id: item.roleId,
  579. label: item.roleName,
  580. disabled: false,
  581. };
  582. });
  583. });
  584. proxy
  585. .get("/tenantDept/list", {
  586. pageNum: 1,
  587. pageSize: 9999,
  588. keyword: "",
  589. tenantId: proxy.useUserStore().user.tenantId,
  590. type: 0,
  591. })
  592. .then((res) => {
  593. companyData.value = res.data.map((x) => ({
  594. ...x,
  595. label: x.deptName,
  596. value: x.deptId,
  597. }));
  598. });
  599. Promise.all([
  600. proxy.post("/productClassify/tree", {
  601. parentId: "",
  602. name: "",
  603. definition: "1",
  604. }),
  605. proxy.post("/productClassify/tree", {
  606. parentId: "",
  607. name: "",
  608. definition: "2",
  609. }),
  610. ]).then((res) => {
  611. if (res && res.length > 1) {
  612. res[1].forEach((x) => {
  613. x.id = x.id + "";
  614. });
  615. productTreeData.value = [
  616. {
  617. id: "-999",
  618. name: "全部",
  619. parentId: "",
  620. children: [
  621. {
  622. id: "-9",
  623. definition: "2",
  624. name: "物料",
  625. parentId: "-999",
  626. children: arrayRecursion(res[1], "2"),
  627. },
  628. {
  629. id: "-99",
  630. definition: "1",
  631. name: "产品",
  632. parentId: "-999",
  633. children: arrayRecursion(res[0], "1"),
  634. },
  635. ],
  636. },
  637. ];
  638. allData.value = getSubset(productTreeData.value, []);
  639. }
  640. });
  641. };
  642. getUserList();
  643. const openModal = () => {
  644. roleData.value[0].disabled = false;
  645. modalType.value = "add";
  646. formData.data = {
  647. userType: 1,
  648. tenantId: proxy.useUserStore().user.tenantId,
  649. companySet: [],
  650. purchaseRange: [],
  651. purchaseRangeOne: [],
  652. identity: 10,
  653. identityList: [],
  654. };
  655. loadingDialog.value = false;
  656. dialogVisible.value = true;
  657. };
  658. function findNodeById(treeData, nodeId) {
  659. // 遍历当前层级的所有节点
  660. for (let i = 0; i < treeData.length; i++) {
  661. let node = treeData[i];
  662. // 如果当前节点的 ID 匹配目标节点的 ID,则返回当前节点
  663. if (node.deptId === nodeId) {
  664. return node;
  665. }
  666. // 如果当前节点有子节点,则递归调用当前函数继续查找子节点
  667. if (node.children && node.children.length > 0) {
  668. let foundNode = findNodeById(node.children, nodeId);
  669. // 如果在子节点中找到了目标节点,则返回找到的节点
  670. if (foundNode) {
  671. return foundNode;
  672. }
  673. }
  674. }
  675. // 如果遍历完所有节点仍未找到目标节点,则返回 null
  676. return null;
  677. }
  678. const findCompanyType = (val) => {
  679. const current = findNodeById(deptList.value, val);
  680. if (current && current.type == 0) {
  681. formData.data.companySet = [val];
  682. companyData.value = companyData.value.map((x) => ({
  683. ...x,
  684. disabled: val == x.value,
  685. }));
  686. } else {
  687. return findCompanyType(current.parentId);
  688. }
  689. };
  690. const handleDeptIdChange = (val) => {
  691. const current = findNodeById(deptList.value, val);
  692. if (current && current.type == 0) {
  693. formData.data.companySet = [val];
  694. companyData.value = companyData.value.map((x) => ({
  695. ...x,
  696. disabled: val == x.value,
  697. }));
  698. } else {
  699. findCompanyType(current.parentId);
  700. }
  701. };
  702. const noRepeat = (arr) => {
  703. var newArr = [...new Set(arr)];
  704. return newArr;
  705. };
  706. const submitForm = () => {
  707. submit.value.handleSubmit(() => {
  708. if (formData.data.password && formData.data.password.length < 5) {
  709. return ElMessage("密码长度不得低于五位");
  710. }
  711. const method = modalType.value == "add" ? "POST" : "PUT";
  712. if (formData.data.companySet && formData.data.companySet.length > 0) {
  713. formData.data.companySet = formData.data.companySet.join(",");
  714. }
  715. if (isShowPurchaseAtt.value) {
  716. let data = noRepeat(
  717. productTree.value
  718. .getHalfCheckedKeys()
  719. .concat(productTree.value.getCheckedKeys())
  720. );
  721. data = data.filter((x) => !["-999", "-99", "-9"].includes(x));
  722. formData.data.purchaseRange = data.join(",");
  723. } else {
  724. formData.data.purchaseRange = "";
  725. }
  726. proxy.post("/tenantUser", formData.data, method).then(() => {
  727. if (formData.data.password && formData.data.userId) {
  728. proxy
  729. .post(
  730. "/tenantUser/resetPwd",
  731. { password: formData.data.password, userId: formData.data.userId },
  732. "PUT"
  733. )
  734. .then();
  735. }
  736. ElMessage({
  737. message: modalType.value == "add" ? "添加成功" : "编辑成功",
  738. type: "success",
  739. });
  740. // 更新业务公司数据
  741. proxy
  742. .post("/tenantUser/getUserCompanyList", {
  743. pageNum: 1,
  744. pageSize: 9999,
  745. })
  746. .then((res) => {
  747. proxy.useUserStore().allDict["list_company_data"] = res.map((x) => ({
  748. ...x,
  749. label: x.deptName,
  750. value: x.deptId,
  751. }));
  752. proxy.useUserStore().allDict["tree_company_data"] = proxy.handleTree(
  753. res,
  754. "deptId"
  755. );
  756. });
  757. dialogVisible.value = false;
  758. getList();
  759. });
  760. });
  761. };
  762. const getDtl = (row) => {
  763. if (row.userId == "1") {
  764. roleData.value[0].disabled = true;
  765. } else {
  766. roleData.value[0].disabled = false;
  767. }
  768. companyData.value = companyData.value.map((x) => ({
  769. ...x,
  770. disabled: row.companyId == x.value,
  771. }));
  772. dialogVisible.value = true;
  773. proxy.get(`/tenantUser/${row.userId}`).then((res) => {
  774. formData.data = {
  775. ...row,
  776. userType: 1,
  777. roleIds: res.roleIds,
  778. identityList: res.data.identityList,
  779. };
  780. if (res.data && res.data.purchaseRange) {
  781. formData.data.purchaseRange = [];
  782. formData.data.purchaseRangeOne = res.data.purchaseRange.split(",");
  783. formData.data.purchaseRangeOne = formData.data.purchaseRangeOne.filter(
  784. (item) => {
  785. return allData.value.some((i) => item == i);
  786. }
  787. );
  788. } else {
  789. formData.data.purchaseRangeOne = [];
  790. }
  791. if (!(res.data.identityList && res.data.identityList.length > 0)) {
  792. formData.data.identityList = [];
  793. }
  794. changeRoleId(res.roleIds);
  795. let companySetData = formData.data.companySet
  796. ? formData.data.companySet
  797. : "";
  798. if (companySetData) {
  799. formData.data.companySet = [
  800. ...new Set((row.companyId + "," + companySetData).split(",")),
  801. ];
  802. } else {
  803. formData.data.companySet = row.companyId.split(",");
  804. }
  805. modalType.value = "edit";
  806. });
  807. };
  808. const newPassword = () => {
  809. formData.data.password = generatePassword();
  810. };
  811. const generatePassword = () => {
  812. var length = 12,
  813. charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
  814. password = "";
  815. for (var i = 0, n = charset.length; i < length; ++i) {
  816. password += charset.charAt(Math.floor(Math.random() * n));
  817. }
  818. return password;
  819. };
  820. const userId = ref("");
  821. const password = ref("");
  822. const roomDialogVisible = ref(false);
  823. const submitPassword = (password1) => {
  824. if (!password1) {
  825. ElMessage({
  826. message: "请输入新密码",
  827. type: "warning",
  828. });
  829. return;
  830. }
  831. if (password1.length < 5) {
  832. return ElMessage("密码长度不得低于五位");
  833. }
  834. proxy
  835. .post(
  836. "/tenantUser/resetPwd",
  837. {
  838. password: password1,
  839. userId: userId.value,
  840. },
  841. "PUT"
  842. )
  843. .then(() => {
  844. ElMessage({
  845. message: "重置成功",
  846. type: "success",
  847. });
  848. roomDialogVisible.value = false;
  849. password.value = "";
  850. });
  851. };
  852. const changeUserName = (val) => {
  853. formData.data.userName = val.trim();
  854. };
  855. const changePassword = (val) => {
  856. formData.data.password = val.trim();
  857. };
  858. const changePassword2 = (val) => {
  859. password.value = val.trim();
  860. };
  861. const treeData = ref([]);
  862. const search = ref("");
  863. const getTreeData = () => {
  864. proxy
  865. .get("/tenantDept/list", {
  866. pageNum: 1,
  867. pageSize: 9999,
  868. keyword: "",
  869. tenantId: proxy.useUserStore().user.tenantId,
  870. })
  871. .then((res) => {
  872. for (let i = 0; i < res.data.length; i++) {
  873. if (res.data[i] && res.data[i].type == 0) {
  874. res.data[i].disabled = true;
  875. }
  876. }
  877. treeData.value = proxy.handleTree(res.data, "deptId");
  878. deptList.value = proxy.handleTree(res.data, "deptId");
  879. let newData = proxy.deepClone(res.data);
  880. for (let i = 0; i < newData.length; i++) {
  881. if (newData[i] && newData[i].type == 3) {
  882. newData[i].disabled = true;
  883. }
  884. }
  885. deptListOne.value = proxy.handleTree(newData, "deptId");
  886. });
  887. };
  888. getTreeData();
  889. const searchChange = () => {
  890. proxy.$refs.tree.filter(search.value);
  891. };
  892. const getParents = (node, name, key) => {
  893. if (node.parent && node.parent.data[key]) {
  894. name += node.parent.data[key];
  895. return getParents(node.parent, name, key);
  896. }
  897. return name;
  898. };
  899. // 以下可实现搜索显示子节点
  900. const filterNode = (value, data, node) => {
  901. let names = getParents(node, node.data.deptName, "deptName");
  902. let isName = names.indexOf(value) !== -1;
  903. return !value || isName ? true : false;
  904. };
  905. const treeChange = (e, data) => {
  906. sourceList.value.pagination.deptId = e.deptId;
  907. getList();
  908. };
  909. const handleAdd = () => {
  910. formData.data.identityList.push({
  911. identity: "",
  912. deptId: "",
  913. });
  914. };
  915. const handleRemove = (index) => {
  916. formData.data.identityList.splice(index, 1);
  917. };
  918. </script>
  919. <style lang="scss" scoped>
  920. .user {
  921. padding: 10px;
  922. display: flex;
  923. justify-content: space-between;
  924. .tree {
  925. width: 300px;
  926. }
  927. .content {
  928. width: calc(100% - 310px);
  929. }
  930. }
  931. .treeList {
  932. display: block;
  933. height: 100%;
  934. background: #fff;
  935. padding: 10px 15px 15px;
  936. height: calc(100vh - 122px);
  937. .search {
  938. display: flex;
  939. margin-bottom: 20px;
  940. .el-input {
  941. // width: calc(100% - 70px);
  942. margin-right: 10px;
  943. text-align: center;
  944. }
  945. }
  946. // .searh,.title,.box{
  947. // padding-left:20px ;
  948. // }
  949. .box {
  950. padding-right: 0px;
  951. height: calc(100vh - 245px);
  952. overflow-y: auto;
  953. overflow-x: auto;
  954. .el-tree {
  955. // .el-tree-node__content {
  956. // display: block;
  957. // }
  958. .el-tree-node > .el-tree-node__children {
  959. overflow: visible;
  960. }
  961. }
  962. }
  963. }
  964. </style>