index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. <template>
  2. <div id="usermanagement">
  3. <el-row :gutter="20">
  4. <el-col :span="4">
  5. <el-input
  6. v-model="filterText"
  7. size="small"
  8. placeholder="请输入内容"
  9. clearable
  10. prefix-icon="el-icon-search"
  11. ></el-input>
  12. <el-tree
  13. class="filter-tree"
  14. :data="dataDs"
  15. :props="defaultProps"
  16. default-expand-all
  17. :filter-node-method="filterNode"
  18. ref="tree"
  19. :expand-on-click-node="false"
  20. @node-click="getTreeDepart"
  21. >
  22. </el-tree>
  23. </el-col>
  24. <el-col :span="20">
  25. <search-box :formList="formList" @search="search" @init="init" />
  26. <table-list
  27. :tableSets="tableSet"
  28. :tableData="tableData"
  29. :navText="navText"
  30. @addClick="addClick"
  31. :loading="loading"
  32. >
  33. <template slot="btn" slot-scope="props">
  34. <!-- <el-button type="text" @click="addClick(props.scope.row, 2)"
  35. >详情</el-button
  36. > -->
  37. <el-button type="text" @click="addClick(props.scope.row, 0)"
  38. >修改</el-button
  39. >
  40. <el-button type="text" @click="del(props.scope.row)"
  41. >删除</el-button
  42. >
  43. <el-button type="text" @click="Reset(props.scope.row)"
  44. >重置</el-button
  45. >
  46. </template>
  47. </table-list>
  48. <pagination
  49. :total="total"
  50. :pageSize="pageSize"
  51. :currentPage="currentPage"
  52. @handleSizeChange="handleSizeChange"
  53. @handleCurrentChange="handleCurrentChange"
  54. />
  55. <el-dialog
  56. :visible.sync="dialogVisible"
  57. width="560px"
  58. :show-close="false"
  59. :close-on-click-modal="false"
  60. >
  61. <div slot="title" class="hearders">
  62. <div class="leftTitle">
  63. {{ statusPop === 1 ? "添加" : statusPop === 0 ? "修改" : "详情" }}
  64. </div>
  65. <div class="rightBoxs">
  66. <img src="@/assets/images/Close@2x.png" alt="" @click="close" />
  67. </div>
  68. </div>
  69. <div>
  70. <el-form
  71. label-position="right"
  72. label-width="80px"
  73. :model="listData"
  74. :rules="rules"
  75. ref="listData"
  76. >
  77. <el-form-item
  78. v-for="(items, indexs) in listitem"
  79. :key="indexs"
  80. :label="items.label"
  81. :prop="items.prop"
  82. >
  83. <el-radio-group
  84. v-if="items.scope === 'status'"
  85. v-model="listData[items.prop]"
  86. >
  87. <el-radio
  88. v-for="(item, index) in items.options"
  89. :key="index"
  90. :label="item.value"
  91. :disabled="statusPop === 2"
  92. >{{ item.label }}</el-radio
  93. >
  94. </el-radio-group>
  95. <treeselect
  96. v-else-if="items.scope === 'selectMore'"
  97. v-model="listData[items.prop]"
  98. :options="dataDs"
  99. :show-count="true"
  100. placeholder="选择上级菜单"
  101. />
  102. <el-input
  103. :disabled="statusPop === 2"
  104. v-else-if="items.scope === 'textarea'"
  105. type="textarea"
  106. v-model="listData[items.prop]"
  107. ></el-input>
  108. <el-select
  109. v-else-if="items.scope === 'moreSelect'"
  110. v-model="listData[items.prop]"
  111. multiple
  112. placeholder="请选择"
  113. >
  114. <el-option
  115. v-for="item in items.options"
  116. :key="item[items.option.value]"
  117. :label="item[items.option.label]"
  118. :value="item[items.option.value]"
  119. >
  120. </el-option>
  121. </el-select>
  122. <el-select
  123. v-else-if="items.scope === 'select'"
  124. v-model="listData[items.prop]"
  125. placeholder="请选择"
  126. >
  127. <el-option
  128. v-for="item in items.options"
  129. :key="item[items.option.value]"
  130. :label="item[items.option.label]"
  131. :value="item[items.option.value]"
  132. >
  133. </el-option>
  134. </el-select>
  135. <el-input
  136. :disabled="statusPop === 2 || statusPop === 0"
  137. v-else-if="items.scope === 'userNames'"
  138. v-model="listData[items.prop]"
  139. ><template slot="append">登入账号</template></el-input
  140. >
  141. <el-input
  142. :disabled="statusPop === 2"
  143. v-else
  144. v-model="listData[items.prop]"
  145. ></el-input>
  146. </el-form-item>
  147. </el-form>
  148. </div>
  149. <span slot="footer" class="dialog-footer">
  150. <el-button @click="close">取 消</el-button>
  151. <el-button
  152. type="primary"
  153. v-if="statusPop !== 2"
  154. @click="submit('listData')"
  155. >确 定</el-button
  156. >
  157. </span>
  158. </el-dialog>
  159. </el-col>
  160. </el-row>
  161. </div>
  162. </template>
  163. <script>
  164. import Treeselect from "@riophae/vue-treeselect";
  165. import "@riophae/vue-treeselect/dist/vue-treeselect.css";
  166. import searchBox from "@/components/searchBox";
  167. import tableList from "@/components/tableList";
  168. import pagination from "@/components/pagination";
  169. export default {
  170. components: { Treeselect, searchBox, tableList, pagination },
  171. data() {
  172. return {
  173. loading: false, //当前表单加载是否加载动画
  174. navText: {
  175. title: "用户信息",
  176. index: 0,
  177. ch: "条",
  178. num: false,
  179. choice: true,
  180. addHide: false,
  181. backFatherBtn: {
  182. status: false,
  183. title: "未定义",
  184. },
  185. },
  186. filterText: "",
  187. dataDs: [],
  188. defaultProps: {
  189. children: "children",
  190. label: "label",
  191. },
  192. deptId: "",
  193. //搜索
  194. formList: [
  195. {
  196. label: "用户名称",
  197. prop: "userName",
  198. placeholder: "请输入用户名称",
  199. },
  200. {
  201. label: "手机号码",
  202. prop: "phonenumber",
  203. placeholder: "请输入手机号码",
  204. },
  205. {
  206. label: "状态",
  207. prop: "status",
  208. placeholder: "请选择状态",
  209. scope: "select",
  210. options: [
  211. {
  212. label: "启用",
  213. value: 1,
  214. },
  215. {
  216. label: "停用",
  217. value: 0,
  218. },
  219. ],
  220. },
  221. ],
  222. // 表单
  223. tableSet: [
  224. {
  225. label: "用户编号",
  226. prop: "userId",
  227. hidden: true,
  228. },
  229. {
  230. label: "用户名称",
  231. prop: "userName",
  232. hidden: true,
  233. },
  234. {
  235. label: "用户昵称",
  236. prop: "nickName",
  237. hidden: true,
  238. },
  239. {
  240. label: "部门",
  241. prop: "deptName",
  242. hidden: true,
  243. },
  244. {
  245. label: "手机号码",
  246. prop: "phonenumber",
  247. hidden: true,
  248. },
  249. {
  250. label: "状态",
  251. prop: "status",
  252. hidden: true,
  253. scope: "status",
  254. },
  255. ],
  256. tableData: [], //表单数据
  257. optionsCascader: [], //弹窗分类数据
  258. total: 0, //一共多少条
  259. pageSize: 10, //每页多少条数据
  260. currentPage: 1, //当前页码
  261. // 弹窗字段
  262. listitem: [
  263. {
  264. label: "归属部门",
  265. prop: "deptId",
  266. scope: "selectMore",
  267. },
  268. {
  269. label: "用户名称",
  270. prop: "userName",
  271. scope: "userNames",
  272. },
  273. {
  274. label: "用户昵称",
  275. prop: "nickName",
  276. },
  277. {
  278. label: "手机号码",
  279. prop: "phonenumber",
  280. },
  281. {
  282. label: "邮箱",
  283. prop: "email",
  284. },
  285. {
  286. label: "用户性别",
  287. prop: "sex",
  288. scope: "select",
  289. option: {
  290. label: "dictLabel",
  291. value: "dictCode",
  292. },
  293. options: [],
  294. },
  295. {
  296. label: "状态",
  297. prop: "status",
  298. scope: "status",
  299. options: [
  300. {
  301. label: "启用",
  302. value: "1",
  303. },
  304. {
  305. label: "关闭",
  306. value: "0",
  307. },
  308. ],
  309. },
  310. {
  311. label: "岗位",
  312. prop: "postIds",
  313. option: {
  314. label: "postName",
  315. value: "postId",
  316. },
  317. options: [],
  318. scope: "moreSelect",
  319. show: true,
  320. },
  321. {
  322. label: "角色",
  323. prop: "roleIds",
  324. option: {
  325. label: "roleName",
  326. value: "roleId",
  327. },
  328. options: [],
  329. scope: "moreSelect",
  330. show: true,
  331. },
  332. {
  333. label: "备注",
  334. prop: "remark",
  335. scope: "textarea",
  336. },
  337. ],
  338. listData: {},
  339. statusPop: -1,
  340. dialogVisible: false,
  341. //表单验证
  342. rules: {
  343. deptId: [
  344. { required: true, message: "请选择归属部门", trigger: "blur" },
  345. ],
  346. userName: [
  347. { required: true, message: "请输入用户名称", trigger: "blur" },
  348. ],
  349. nickName: [
  350. { required: true, message: "请输入用户昵称", trigger: "blur" },
  351. ],
  352. phonenumber: [
  353. { required: true, message: "请输入手机号码", trigger: "blur" },
  354. ],
  355. email: [{ required: true, message: "请输入邮箱", trigger: "blur" }],
  356. sex: [{ required: true, message: "请选择性别", trigger: "change" }],
  357. status: [{ required: true, message: "请选择状态", trigger: "change" }],
  358. postIds: [{ required: true, message: "请选择岗位", trigger: "change" }],
  359. roleIds: [{ required: true, message: "请选择角色", trigger: "change" }],
  360. remark: [{ required: true, message: "请填写备注", trigger: "blur" }],
  361. },
  362. };
  363. },
  364. watch: {
  365. filterText(val) {
  366. this.$refs.tree.filter(val);
  367. },
  368. },
  369. mounted() {
  370. this.search();
  371. this.initTree();
  372. },
  373. methods: {
  374. //重置密码
  375. Reset(v) {
  376. this.$prompt("请输入新密码", "提示", {
  377. confirmButtonText: "确定",
  378. cancelButtonText: "取消",
  379. })
  380. .then(({ value }) => {
  381. var data = {
  382. deptId: v.deptId,
  383. userName: v.userName,
  384. nickName: v.nickName,
  385. userId: v.userId,
  386. password: value,
  387. };
  388. this.$api.editUser(data).then((res) => {
  389. if (res.code === 200) {
  390. this.$message({
  391. type: "success",
  392. message: "密码已重置",
  393. });
  394. this.search();
  395. }
  396. });
  397. })
  398. .catch(() => {
  399. this.$message({
  400. type: "info",
  401. message: "取消输入",
  402. });
  403. });
  404. },
  405. // 获取部门
  406. initTree() {
  407. var data = {
  408. statusArray: "0,1",
  409. };
  410. this.$api.obtainDeptTreeselect(data).then((res) => {
  411. this.dataDs = res.data;
  412. });
  413. },
  414. // 对树节点进行筛选时执行的方法
  415. filterNode(value, data) {
  416. if (!value) return true;
  417. return data.label.indexOf(value) !== -1;
  418. },
  419. //点击菜单栏
  420. getTreeDepart(options) {
  421. this.deptId = options.id;
  422. this.search();
  423. },
  424. //搜索
  425. search(v) {
  426. this.loading = true;
  427. if (v === undefined) {
  428. v = {
  429. statusArray: "0,1",
  430. pageSize: this.pageSize,
  431. pageNum: this.currentPage,
  432. };
  433. }
  434. var data = {
  435. deptId: this.deptId || "",
  436. userName: v.userName || "",
  437. phonenumber: v.phonenumber || "",
  438. statusArray: v.status === undefined ? "0,1" : v.status,
  439. pageSize: this.pageSize,
  440. pageNum: this.currentPage,
  441. };
  442. this.$api.obtainUserList(data).then((res) => {
  443. this.tableData = res.rows;
  444. this.total = res.total;
  445. this.navText.index = res.total;
  446. res.rows.forEach((item, index) => {
  447. if (item.dept) {
  448. this.tableData[index].deptName = item.dept.deptName;
  449. }
  450. });
  451. });
  452. this.loading = false;
  453. },
  454. //重置
  455. init() {
  456. this.search();
  457. },
  458. //删除用户信息
  459. del(v) {
  460. this.$confirm("此操作将删除该用户信息, 是否继续?", "提示", {
  461. confirmButtonText: "确定",
  462. cancelButtonText: "取消",
  463. type: "warning",
  464. })
  465. .then(() => {
  466. var data = {
  467. deptId: v.deptId,
  468. userName: v.userName,
  469. nickName: v.nickName,
  470. userId: v.userId,
  471. status: "-1",
  472. };
  473. this.$api.editUser(data).then((res) => {
  474. if (res.code === 200) {
  475. this.$message.success("删除成功");
  476. this.search();
  477. }
  478. });
  479. })
  480. .catch(() => {
  481. this.$message({
  482. type: "info",
  483. message: "已取消删除",
  484. });
  485. });
  486. },
  487. //初始数据
  488. getOptionsRole() {
  489. var data = {
  490. statusArray: "0,1",
  491. };
  492. this.$api.inquiresystempostList(data).then((res) => {
  493. this.listitem.forEach((item, index) => {
  494. if (item.prop === "postIds") {
  495. item.options = res.rows;
  496. }
  497. });
  498. });
  499. this.$api.obtainRoleList(data).then((res) => {
  500. this.listitem.forEach((item, index) => {
  501. if (item.prop === "roleIds") {
  502. item.options = res.rows;
  503. }
  504. });
  505. });
  506. var arays = [];
  507. arays = this.$store.state.UserDict.filter((item, index) => {
  508. return item.dictType == "sys_user_sex";
  509. });
  510. this.listitem.forEach((item, index) => {
  511. if (item.label === "用户性别") {
  512. item.options = arays;
  513. }
  514. });
  515. },
  516. //开启窗口
  517. addClick(v, int) {
  518. this.getOptionsRole();
  519. if (v === undefined) {
  520. this.statusPop = 1;
  521. this.listData = {};
  522. } else {
  523. this.statusPop = int;
  524. var data = v.userId;
  525. this.$api.obtainUserDetails(data).then((res) => {
  526. this.listData = res.data;
  527. this.listData.roleIds = res.roleIds;
  528. this.listData.postIds = res.postIds;
  529. this.listData.sex = Number(res.data.sex);
  530. });
  531. }
  532. this.$nextTick(()=>{
  533. this.$refs.listData.clearValidate();
  534. })
  535. this.dialogVisible = true;
  536. },
  537. //表单验证
  538. submit(formName) {
  539. this.$refs[formName].validate((valid) => {
  540. if (valid) {
  541. this.rulesTableSumbit();
  542. } else {
  543. return false;
  544. }
  545. });
  546. },
  547. //提交表单
  548. rulesTableSumbit() {
  549. if (this.statusPop === 1) {
  550. this.$api.addUser(this.listData).then((res) => {
  551. if (res.code === 200) {
  552. this.search();
  553. this.$message.success("新增成功");
  554. this.dialogVisible = false;
  555. this.resetForm();
  556. }
  557. });
  558. }
  559. if (this.statusPop === 0) {
  560. this.$api.editUser(this.listData).then((res) => {
  561. if (res.code === 200) {
  562. this.search();
  563. this.$message.success("修改成功");
  564. this.dialogVisible = false;
  565. this.resetForm();
  566. }
  567. });
  568. }
  569. },
  570. // 关闭窗口
  571. close() {
  572. this.dialogVisible = false;
  573. this.resetForm();
  574. },
  575. //重置表单验证
  576. resetForm() {
  577. this.$refs["listData"].resetFields();
  578. },
  579. handleSizeChange(v) {
  580. this.pageSize = v;
  581. this.currentPage = 1;
  582. this.search();
  583. },
  584. handleCurrentChange(v) {
  585. this.currentPage = v;
  586. this.search();
  587. },
  588. },
  589. };
  590. </script>
  591. <style lang="less" scoped>
  592. /deep/.el-button {
  593. border-radius: 8px;
  594. }
  595. /deep/.el-dialog {
  596. border-radius: 8px;
  597. .el-dialog__header {
  598. padding: 0;
  599. .hearders {
  600. height: 40px;
  601. display: flex;
  602. align-items: center;
  603. justify-content: space-between;
  604. padding: 0px 18px 0px 20px;
  605. border-bottom: 1px solid #e2e2e2;
  606. .leftTitle {
  607. font-size: 14px;
  608. font-weight: bold;
  609. color: #2f4378;
  610. }
  611. .rightBoxs {
  612. display: flex;
  613. align-items: center;
  614. img {
  615. width: 14px;
  616. height: 14px;
  617. margin-left: 13px;
  618. cursor: pointer;
  619. }
  620. }
  621. }
  622. }
  623. .el-dialog__footer {
  624. padding: 0;
  625. .dialog-footer {
  626. padding: 0px 40px;
  627. height: 70px;
  628. border-top: 1px solid #e2e2e2;
  629. display: flex;
  630. align-items: center;
  631. justify-content: flex-end;
  632. }
  633. }
  634. }
  635. .imgBox {
  636. width: 100%;
  637. // height: 210px;
  638. border: 1px solid #e2e2e2;
  639. border-radius: 8px;
  640. padding: 8px 8px 3px;
  641. display: flex;
  642. flex-direction: column;
  643. align-items: center;
  644. .imgLabel {
  645. flex: 1;
  646. width: 100%;
  647. border: 1px dotted #e2e2e2;
  648. color: #999;
  649. font-size: 14px;
  650. cursor: pointer;
  651. border-radius: 8px;
  652. .msPhoto {
  653. display: flex;
  654. justify-content: center;
  655. align-items: center;
  656. max-width: 100%;
  657. max-height: 270px;
  658. img {
  659. max-width: 100%;
  660. max-height: 270px;
  661. }
  662. }
  663. .imgbbx {
  664. display: flex;
  665. flex-direction: column;
  666. align-items: center;
  667. justify-content: center;
  668. width: 100%;
  669. height: 100%;
  670. i {
  671. font-weight: bold;
  672. margin: 14px 0;
  673. font-size: 24px;
  674. }
  675. }
  676. }
  677. p {
  678. margin: 5px 0px;
  679. }
  680. }
  681. </style>