UserManagement.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. <template>
  2. <div>
  3. <div class="tw-bg-white tw-p-5 tw-rounded-xl tw-mb-5">
  4. <RootOrgSelect v-if="store.isSuperAdmin" v-model:value="rootOrgId" />
  5. <span class="tw-mr-4"></span>
  6. <a-input
  7. v-model:value="name"
  8. class="tw-mr-4"
  9. style="width: 178px"
  10. placeholder="姓名"
  11. allowClear
  12. ></a-input>
  13. <span class="tw-mr-4"></span>
  14. <a-input
  15. v-model:value="loginName"
  16. style="width: 178px"
  17. placeholder="登录名"
  18. allowClear
  19. ></a-input>
  20. <span class="tw-mr-4"></span>
  21. <RoleSelect v-model:value="roleId" :root-org-id="rootOrgId" />
  22. <StateSelect v-model:value="enable" />
  23. <span class="tw-mr-4"></span>
  24. <a-button @click="search">查询</a-button>
  25. <div class="tw-mt-4">
  26. <a-button @click="newUser">新增</a-button>
  27. <a-button @click="importModalVisible = true">批量导入</a-button>
  28. <a-button @click="handleExport">批量导出</a-button>
  29. <a-button @click="handleToggleUsers(true, selectIds)"
  30. >批量启用</a-button
  31. >
  32. <a-button @click="handleToggleUsers(false, selectIds)"
  33. >批量禁用</a-button
  34. >
  35. <a-button @click="handleResetUsers(selectIds)">批量重置密码</a-button>
  36. </div>
  37. </div>
  38. <div class="tw-bg-white tw-p-5 tw-rounded-xl">
  39. <a-table
  40. row-key="id"
  41. :columns="columns"
  42. :data-source="data"
  43. :row-selection="rowSelection"
  44. :pagination="{
  45. pageSize: pageSize,
  46. current: pageNo,
  47. total: totalElements,
  48. showTotal: (total: number) => `总数:${total}`,
  49. onChange: (pageNoChanged: number, pageSizeChanged: number) => {
  50. pageNo = pageNoChanged;
  51. pageSize = pageSizeChanged;
  52. }
  53. }"
  54. >
  55. <template #rootOrgName="{ record }">
  56. <a>{{ record.rootOrgName }}({{ record.rootOrgCode }})</a>
  57. </template>
  58. <template #enable="{ text }">
  59. <a>{{ $filters.booleanEnableDisableFilter(text) }}</a>
  60. </template>
  61. <template #action="{ record }">
  62. <span>
  63. <a-button @click="showModal(record)">编辑</a-button>
  64. <a-button @click="handleToggleUsers(!record.enable, [record.id])">
  65. {{ record.enable ? "禁用" : "启用" }}
  66. </a-button>
  67. <a-button @click="handleResetUsers([record.id])">重置密码</a-button>
  68. </span>
  69. </template>
  70. </a-table>
  71. </div>
  72. <a-modal
  73. v-model:visible="visible"
  74. title="用户信息页"
  75. @ok="handleOk"
  76. ok-text="确定"
  77. cancel-text="取消"
  78. >
  79. <a-form>
  80. <a-form-item v-show="store.isSuperAdmin" label="顶级机构">
  81. <RootOrgSelect
  82. :disabled="!!userObj.id"
  83. v-model:value="userObj.rootOrgId"
  84. />
  85. </a-form-item>
  86. <a-form-item label="姓名">
  87. <a-input v-model:value="userObj.name"></a-input>
  88. </a-form-item>
  89. <a-form-item label="登录名">
  90. <a-input
  91. :disabled="!!userObj.id"
  92. v-model:value="userObj.loginName"
  93. ></a-input>
  94. </a-form-item>
  95. <a-form-item label="登录密码">
  96. <a-input
  97. :disabled="!!userObj.id"
  98. v-model:value="userObj.password"
  99. ></a-input>
  100. </a-form-item>
  101. <a-form-item label="角色">
  102. <RoleSelect
  103. :root-org-id="userObj.rootOrgId"
  104. v-model:value="userObj.roleId"
  105. />
  106. </a-form-item>
  107. <a-form-item label="状态">
  108. <a-radio-group v-model:value="userObj.enable">
  109. <a-radio :value="true">启用</a-radio>
  110. <a-radio :value="false">禁用</a-radio>
  111. </a-radio-group>
  112. </a-form-item>
  113. </a-form>
  114. </a-modal>
  115. <a-modal
  116. v-model:visible="importModalVisible"
  117. title="批量用户导入"
  118. @ok="handleImport"
  119. ok-text="确定"
  120. cancel-text="取消"
  121. >
  122. <a-form>
  123. <a-form-item label="顶级机构">
  124. <RootOrgSelect
  125. v-show="store.isSuperAdmin"
  126. v-model:value="userObj.rootOrgId"
  127. />
  128. </a-form-item>
  129. <a-form-item label="文件地址">
  130. <input id="file-input" :multiple="false" type="file" />
  131. </a-form-item>
  132. <a-form-item label="下载模板">
  133. <a-button @click="downloadTpl">下载模板</a-button>
  134. </a-form-item>
  135. </a-form>
  136. </a-modal>
  137. </div>
  138. </template>
  139. <script setup lang="ts">
  140. import {
  141. exportUsers,
  142. getUserList,
  143. importUsers,
  144. resetPasswords,
  145. toggleUsers,
  146. updateUser,
  147. } from "@/api/userManagementPage";
  148. import { useMainStore } from "@/store";
  149. import { downloadFileURL } from "@/utils/utils";
  150. import { message, Modal } from "ant-design-vue";
  151. import { watch, onMounted, ref, reactive, toRaw } from "vue-demi";
  152. const store = useMainStore();
  153. store.currentLocation = "基础管理 / 用户管理";
  154. let rootOrgId = $ref(undefined as unknown as number);
  155. let roleId = $ref(undefined as unknown as number);
  156. let loginName = $ref("");
  157. let name = $ref("");
  158. let enable = $ref(undefined as undefined | boolean);
  159. let data = $ref([]);
  160. let pageSize = $ref(10);
  161. let pageNo = $ref(1);
  162. let totalElements = $ref(0);
  163. async function search() {
  164. await fetchData();
  165. }
  166. watch(() => [pageNo, pageSize], fetchData);
  167. async function fetchData() {
  168. const res = await getUserList({
  169. loginName,
  170. name,
  171. enable,
  172. roleId,
  173. rootOrgId,
  174. pageSize,
  175. pageNo,
  176. });
  177. // console.log(res);
  178. data = res.data.content;
  179. pageNo = res.data.pageNo;
  180. pageSize = res.data.pageSize;
  181. totalElements = res.data.totalElements;
  182. }
  183. const columns = [
  184. {
  185. title: "顶级机构",
  186. dataIndex: "rootOrgName",
  187. width: 150,
  188. slots: { customRender: "rootOrgName" },
  189. },
  190. {
  191. title: "姓名",
  192. dataIndex: "name",
  193. width: 150,
  194. },
  195. {
  196. title: "登录名",
  197. dataIndex: "loginName",
  198. width: 150,
  199. },
  200. {
  201. title: "角色",
  202. dataIndex: "roleName",
  203. },
  204. {
  205. title: "状态",
  206. dataIndex: "enable",
  207. slots: { customRender: "enable" },
  208. },
  209. {
  210. title: "创建时间",
  211. dataIndex: "createTime",
  212. },
  213. {
  214. title: "创建人",
  215. dataIndex: "creator",
  216. },
  217. {
  218. title: "更新时间",
  219. dataIndex: "updateTime",
  220. },
  221. {
  222. title: "更新人",
  223. dataIndex: "updater",
  224. },
  225. {
  226. title: "Action",
  227. key: "action",
  228. slots: { customRender: "action" },
  229. },
  230. ];
  231. onMounted(async () => {
  232. rootOrgId = store.userInfo.rootOrgId;
  233. await search();
  234. });
  235. const visible = ref<boolean>(false);
  236. const showModal = (record: any) => {
  237. Object.assign(userObj, record);
  238. visible.value = true;
  239. };
  240. const handleOk = async (e: MouseEvent) => {
  241. await updateUser(toRaw(userObj));
  242. visible.value = false;
  243. await search();
  244. };
  245. const initUser = {
  246. id: undefined,
  247. code: "",
  248. name: "",
  249. loginName: "",
  250. password: "",
  251. enable: true,
  252. roleId,
  253. rootOrgId: store.userInfo.rootOrgId,
  254. };
  255. const userObj = reactive({ ...initUser });
  256. const newUser = async () => {
  257. Object.assign(userObj, initUser);
  258. showModal(userObj);
  259. };
  260. function checkEmpty(): boolean {
  261. if (selectIds && selectIds.length > 0) {
  262. return false;
  263. } else {
  264. message.warn({ content: "请先选择行" });
  265. return true;
  266. }
  267. }
  268. async function handleToggleUsers(enable: boolean, ids: number[]) {
  269. if (checkEmpty()) return;
  270. await toggleUsers(enable, ids);
  271. await search();
  272. }
  273. async function handleResetUsers(ids: number[]) {
  274. if (checkEmpty()) return;
  275. Modal.confirm({
  276. title: "提示",
  277. content: "确认重置?",
  278. cancelText: "取消",
  279. okText: "确定",
  280. onOk: async () => {
  281. await resetPasswords(ids);
  282. await search();
  283. },
  284. });
  285. }
  286. /** <handleImport> */
  287. let importModalVisible = ref<boolean>(false);
  288. async function handleImport() {
  289. const files = (document.querySelector("#file-input") as HTMLInputElement)
  290. .files;
  291. const fileToImport = files && files[0];
  292. if (!fileToImport) {
  293. message.warn({ content: "请选择文件" });
  294. return;
  295. }
  296. await importUsers(rootOrgId, fileToImport);
  297. message.success({ content: "导入成功" });
  298. }
  299. /** </handleImport> */
  300. async function handleExport() {
  301. await exportUsers({ rootOrgId, name, loginName, roleId, enable });
  302. message.success({ content: "导出成功" });
  303. }
  304. let selectIds = $ref<number[]>([]);
  305. const rowSelection = {
  306. onChange: (selectedRowKeys: (string | number)[]) => {
  307. console.log(`selectedRowKeys: ${selectedRowKeys}`);
  308. selectIds = selectedRowKeys as number[];
  309. },
  310. };
  311. async function downloadTpl() {
  312. downloadFileURL("/api/ess/org/template");
  313. }
  314. </script>