index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. <template>
  2. <div class="tenant">
  3. <byTable
  4. :source="sourceList.data"
  5. :pagination="sourceList.pagination"
  6. :config="config"
  7. :loading="loading"
  8. highlight-current-row
  9. :action-list="[
  10. {
  11. text: '添加用户',
  12. action: () => openModal(),
  13. },
  14. ]"
  15. @get-list="getList">
  16. </byTable>
  17. <el-dialog :title="modalType == 'add' ? '添加用户' : '编辑用户'" v-if="dialogVisible" v-model="dialogVisible" width="600" v-loading="loadingDialog">
  18. <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="submit">
  19. <template #deptId>
  20. <div style="width: 100%">
  21. <el-tree-select
  22. v-model="formData.data.deptId"
  23. :data="deptList.data"
  24. check-strictly
  25. :render-after-expand="false"
  26. node-key="deptId"
  27. :props="defaultProps" />
  28. </div>
  29. </template>
  30. <template #account>
  31. <el-input style="width: 150px; margin-right: 10px" v-model="formData.data.userName" @change="changeUserName" placeholder="请输入用户名"></el-input>
  32. <el-input style="width: 150px; margin-right: 10px" v-model="formData.data.password" @change="changePassword" placeholder="密码"></el-input>
  33. <span style="color: #409eff; cursor: pointer" @click="newPassword">随机生成</span>
  34. </template>
  35. </byForm>
  36. <template #footer>
  37. <el-button @click="dialogVisible = false" size="large">取 消</el-button>
  38. <el-button type="primary" @click="submitForm()" size="large">确 定</el-button>
  39. </template>
  40. </el-dialog>
  41. <el-dialog title="修改密码" v-if="roomDialogVisible" v-model="roomDialogVisible" width="300" v-loading="loading">
  42. <template #footer>
  43. <el-input v-model="password" placeholder="请输入新密码" @change="changePassword2" style="margin-bottom: 20px" />
  44. <el-button @click="roomDialogVisible = false" size="large">取 消</el-button>
  45. <el-button type="primary" @click="submitPassword(password)" size="large" :loading="submitLoading"> 确 定 </el-button>
  46. </template>
  47. </el-dialog>
  48. </div>
  49. </template>
  50. <script setup>
  51. import { computed, ref } from "vue";
  52. import byTable from "@/components/byTable/index";
  53. import { ElMessage, ElMessageBox } from "element-plus";
  54. import byForm from "@/components/byForm/index";
  55. import useUserStore from "@/store/modules/user";
  56. const { proxy } = getCurrentInstance();
  57. const defaultProps = {
  58. children: "children",
  59. label: "deptName",
  60. };
  61. const deptList = ref([]);
  62. const sourceList = ref({
  63. data: [],
  64. pagination: {
  65. total: 0,
  66. pageNum: 1,
  67. pageSize: 10,
  68. keyword: "",
  69. tenantId: useUserStore().user.tenantId,
  70. },
  71. });
  72. const loading = ref(false);
  73. const config = computed(() => {
  74. return [
  75. {
  76. attrs: {
  77. label: "部门",
  78. prop: "deptName",
  79. },
  80. },
  81. {
  82. attrs: {
  83. label: "姓名",
  84. prop: "nickName",
  85. align: "left",
  86. },
  87. },
  88. {
  89. attrs: {
  90. label: "用户名",
  91. prop: "userName",
  92. },
  93. },
  94. {
  95. attrs: {
  96. label: "系统用户",
  97. prop: "userType",
  98. },
  99. render(userType) {
  100. return userType == 1 ? "是" : "否";
  101. },
  102. },
  103. {
  104. attrs: {
  105. label: "手机号",
  106. prop: "phonenumber",
  107. },
  108. },
  109. {
  110. attrs: {
  111. label: "工号",
  112. prop: "jobNumber",
  113. },
  114. },
  115. {
  116. attrs: {
  117. label: "操作",
  118. width: "200",
  119. align: "right",
  120. },
  121. renderHTML(row) {
  122. return [
  123. {
  124. attrs: {
  125. label: "修改密码",
  126. type: "primary",
  127. text: true,
  128. },
  129. el: "button",
  130. click() {
  131. userId.value = row.userId;
  132. password.value = "";
  133. roomDialogVisible.value = true;
  134. },
  135. },
  136. {
  137. attrs: {
  138. label: "修改",
  139. type: "primary",
  140. text: true,
  141. },
  142. el: "button",
  143. click() {
  144. if (!sourceList.value.pagination.tenantId) {
  145. ElMessage({
  146. message: "请选择租户",
  147. type: "warning",
  148. });
  149. return;
  150. }
  151. getDtl(row);
  152. },
  153. },
  154. {
  155. attrs: {
  156. label: "删除",
  157. type: "danger",
  158. text: true,
  159. },
  160. el: "button",
  161. click() {
  162. ElMessageBox.confirm("此操作将永久删除该数据, 是否继续?", "提示", {
  163. confirmButtonText: "确定",
  164. cancelButtonText: "取消",
  165. type: "warning",
  166. }).then(() => {
  167. proxy
  168. .post(
  169. "/tenantUser/" + row.userId,
  170. {
  171. id: row.userId,
  172. },
  173. "delete"
  174. )
  175. .then(() => {
  176. ElMessage({
  177. message: "删除成功",
  178. type: "success",
  179. });
  180. getList();
  181. });
  182. });
  183. },
  184. },
  185. ];
  186. },
  187. },
  188. ];
  189. });
  190. const getDict = () => {
  191. proxy.get("/tenantDept/list", { pageNum: 1, pageSize: 10000, tenantId: useUserStore().user.tenantId }).then((res) => {
  192. deptList.value.data = proxy.handleTree(res.data, "deptId");
  193. setTimeout(() => {
  194. loading.value = false;
  195. }, 200);
  196. });
  197. };
  198. const getList = async (req) => {
  199. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  200. loading.value = true;
  201. proxy.get("/tenantUser/list", sourceList.value.pagination).then((res) => {
  202. res.rows.map((item) => {
  203. item.deptName = item.dept ? item.dept.deptName : item.dept;
  204. });
  205. sourceList.value.data = res.rows;
  206. sourceList.value.pagination.total = res.total;
  207. setTimeout(() => {
  208. loading.value = false;
  209. }, 200);
  210. });
  211. };
  212. getDict();
  213. getList();
  214. const modalType = ref("add");
  215. const dialogVisible = ref(false);
  216. const loadingDialog = ref(false);
  217. const submit = ref(null);
  218. const formOption = reactive({
  219. inline: true,
  220. labelWidth: 100,
  221. itemWidth: 100,
  222. rules: [],
  223. });
  224. const formData = reactive({
  225. data: {},
  226. });
  227. const formConfig = computed(() => {
  228. return [
  229. {
  230. type: "slot",
  231. prop: "deptId",
  232. slotName: "deptId",
  233. label: "部门名称",
  234. },
  235. {
  236. type: "input",
  237. prop: "nickName",
  238. label: "姓名",
  239. },
  240. {
  241. type: "slot",
  242. prop: "userName",
  243. slotName: "account",
  244. label: "账户信息",
  245. },
  246. {
  247. type: "radio",
  248. prop: "userType",
  249. label: "系统用户",
  250. required: true,
  251. disabled: true,
  252. border: true,
  253. data: [
  254. {
  255. label: "是",
  256. id: 1,
  257. },
  258. {
  259. label: "否",
  260. id: 0,
  261. },
  262. ],
  263. },
  264. {
  265. type: "select",
  266. label: "角色",
  267. prop: "roleIds",
  268. multiple: true,
  269. data: [],
  270. isLoad: {
  271. url: `/tenantRole/list?pageNum=1&pageSize=10000&tenantId=${sourceList.value.pagination.tenantId}`,
  272. labelKey: "roleName",
  273. labelVal: "roleId",
  274. method: "get",
  275. resUrl: "rows",
  276. },
  277. },
  278. {
  279. type: "input",
  280. prop: "phonenumber",
  281. label: "手机号",
  282. required: true,
  283. itemWidth: 50,
  284. itemType: "text",
  285. },
  286. {
  287. type: "input",
  288. prop: "jobNumber",
  289. label: "工号",
  290. required: true,
  291. itemWidth: 50,
  292. itemType: "text",
  293. },
  294. ];
  295. });
  296. const rules = ref({
  297. deptId: [{ required: true, message: "请选择部门名称", trigger: "change" }],
  298. nickName: [{ required: true, message: "请输入姓名", trigger: "blur" }],
  299. userName: [{ required: true, message: "请输入用户名", trigger: "blur" }],
  300. roleIds: [{ required: true, message: "请选择角色", trigger: "change" }],
  301. phonenumber: [{ required: true, message: "请输入手机号", trigger: "blur" }],
  302. });
  303. const openModal = () => {
  304. modalType.value = "add";
  305. formData.data = {
  306. userType: 1,
  307. tenantId: useUserStore().user.tenantId,
  308. };
  309. loadingDialog.value = false;
  310. dialogVisible.value = true;
  311. };
  312. const submitForm = () => {
  313. submit.value.handleSubmit(() => {
  314. if (formData.data.password && formData.data.password.length < 5) {
  315. return ElMessage("密码长度不得低于五位");
  316. }
  317. const method = modalType.value == "add" ? "POST" : "PUT";
  318. proxy.post("/tenantUser", formData.data, method).then(() => {
  319. if (formData.data.password && formData.data.userId) {
  320. proxy.post("/tenantUser/resetPwd", { password: formData.data.password, userId: formData.data.userId }, "PUT").then();
  321. }
  322. ElMessage({
  323. message: modalType.value == "add" ? "添加成功" : "编辑成功",
  324. type: "success",
  325. });
  326. dialogVisible.value = false;
  327. getList();
  328. });
  329. });
  330. };
  331. const getDtl = (row) => {
  332. formData.data = { ...row };
  333. modalType.value = "edit";
  334. dialogVisible.value = true;
  335. };
  336. const newPassword = () => {
  337. formData.data.password = generatePassword();
  338. };
  339. const generatePassword = () => {
  340. var length = 12,
  341. charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
  342. password = "";
  343. for (var i = 0, n = charset.length; i < length; ++i) {
  344. password += charset.charAt(Math.floor(Math.random() * n));
  345. }
  346. return password;
  347. };
  348. const userId = ref("");
  349. const password = ref("");
  350. const roomDialogVisible = ref(false);
  351. const submitPassword = (password1) => {
  352. if (!password1) {
  353. ElMessage({
  354. message: "请输入新密码",
  355. type: "warning",
  356. });
  357. return;
  358. }
  359. if (password1.length < 5) {
  360. return ElMessage("密码长度不得低于五位");
  361. }
  362. proxy
  363. .post(
  364. "/tenantUser/resetPwd",
  365. {
  366. password: password1,
  367. userId: userId.value,
  368. },
  369. "PUT"
  370. )
  371. .then(() => {
  372. ElMessage({
  373. message: "重置成功",
  374. type: "success",
  375. });
  376. roomDialogVisible.value = false;
  377. password.value = "";
  378. });
  379. };
  380. const changeUserName = (val) => {
  381. formData.data.userName = val.trim();
  382. };
  383. const changePassword = (val) => {
  384. formData.data.password = val.trim();
  385. };
  386. const changePassword2 = (val) => {
  387. password.value = val.trim();
  388. };
  389. </script>
  390. <style lang="scss" scoped>
  391. .tenant {
  392. padding: 20px;
  393. }
  394. ::v-deep(.el-input-number .el-input__inner) {
  395. text-align: left;
  396. }
  397. </style>