index.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. <script setup name="User" lang="ts">
  2. import {
  3. changeUserStatus,
  4. listUser,
  5. resetUserPwd,
  6. delUser,
  7. getUser,
  8. updateUser,
  9. addUser,
  10. deptTreeSelect
  11. } from "@/api/system/user"
  12. import { UserForm, UserQuery, UserVO } from '@/api/system/user/types';
  13. import { ComponentInternalInstance } from "vue";
  14. import { getToken } from "@/utils/auth";
  15. import { treeselect } from "@/api/system/dept";
  16. import { DeptVO } from "@/api/system/dept/types";
  17. import { RoleVO } from "@/api/system/role/types";
  18. import { PostVO } from "@/api/system/post/types";
  19. import { DateModelType, ElTree, ElUpload, UploadFile, UploadFiles, ElForm } from 'element-plus';
  20. import { to } from "await-to-js";
  21. const router = useRouter();
  22. const { proxy } = getCurrentInstance() as ComponentInternalInstance
  23. const { sys_normal_disable, sys_user_sex } = toRefs<any>(proxy?.useDict('sys_normal_disable', 'sys_user_sex'));
  24. const userList = ref<UserVO[]>();
  25. const loading = ref(true);
  26. const showSearch = ref(true)
  27. const ids = ref<Array<number | string>>([]);
  28. const single = ref(true);
  29. const multiple = ref(true);
  30. const total = ref(0);
  31. const dateRange = ref<[DateModelType, DateModelType]>(['','']);
  32. const deptName = ref('');
  33. const deptOptions = ref<DeptVO[]>([]);
  34. const initPassword = ref('123456');
  35. const postOptions = ref<PostVO[]>([]);
  36. const roleOptions = ref<RoleVO[]>([]);
  37. /*** 用户导入参数 */
  38. const upload = reactive<ImportOption>({
  39. // 是否显示弹出层(用户导入)
  40. open: false,
  41. // 弹出层标题(用户导入)
  42. title: "",
  43. // 是否禁用上传
  44. isUploading: false,
  45. // 是否更新已经存在的用户数据
  46. updateSupport: 0,
  47. // 设置上传的请求头部
  48. headers: { Authorization: "Bearer " + getToken() },
  49. // 上传的地址
  50. url: import.meta.env.VITE_APP_BASE_API + "/system/user/importData"
  51. })
  52. // 列显隐信息
  53. const columns = ref<FieldOption[]>([
  54. { key: 0, label: `用户编号`, visible: true },
  55. { key: 1, label: `用户名称`, visible: true },
  56. { key: 2, label: `用户昵称`, visible: true },
  57. { key: 3, label: `部门`, visible: true },
  58. { key: 4, label: `手机号码`, visible: true },
  59. { key: 5, label: `状态`, visible: true },
  60. { key: 6, label: `创建时间`, visible: true }
  61. ])
  62. const deptTreeRef = ref(ElTree);
  63. const queryFormRef = ref(ElForm);
  64. const userFormRef = ref(ElForm);
  65. const uploadRef = ref(ElUpload);
  66. const dialog = reactive<DialogOption>({
  67. visible: false,
  68. title: ''
  69. });
  70. const initFormData: UserForm = {
  71. userId: undefined,
  72. deptId: undefined,
  73. userName: '',
  74. nickName: undefined,
  75. password: '',
  76. phonenumber: undefined,
  77. email: undefined,
  78. sex: undefined,
  79. status: "0",
  80. remark: '',
  81. postIds: [],
  82. roleIds: []
  83. }
  84. const data = reactive<PageData<UserForm, UserQuery>>({
  85. form: { ...initFormData },
  86. queryParams: {
  87. pageNum: 1,
  88. pageSize: 10,
  89. userName: '',
  90. phonenumber: '',
  91. status: '',
  92. deptId: ''
  93. },
  94. rules: {
  95. userName: [{ required: true, message: "用户名称不能为空", trigger: "blur" }, { min: 2, max: 20, message: "用户名称长度必须介于 2 和 20 之间", trigger: "blur" }],
  96. nickName: [{ required: true, message: "用户昵称不能为空", trigger: "blur" }],
  97. password: [{ required: true, message: "用户密码不能为空", trigger: "blur" }, { min: 5, max: 20, message: "用户密码长度必须介于 5 和 20 之间", trigger: "blur" }],
  98. email: [{ type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }],
  99. phonenumber: [{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur" }]
  100. }
  101. })
  102. const { queryParams, form, rules } = toRefs<PageData<UserForm, UserQuery>>(data)
  103. /** 通过条件过滤节点 */
  104. const filterNode = (value: string, data: any) => {
  105. if (!value) return true
  106. return data.label.indexOf(value) !== -1
  107. }
  108. /** 根据名称筛选部门树 */
  109. watchEffect(
  110. () => {deptTreeRef.value.filter(deptName.value);},
  111. {
  112. flush: 'post' // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行
  113. }
  114. );
  115. /** 查询部门下拉树结构 */
  116. const getTreeSelect = async () => {
  117. const res = await deptTreeSelect();
  118. deptOptions.value = res.data;
  119. };
  120. /** 查询用户列表 */
  121. const getList = async () => {
  122. loading.value = true;
  123. const res = await listUser(proxy?.addDateRange(queryParams.value, dateRange.value));
  124. loading.value = false;
  125. userList.value = res.rows;
  126. total.value = res.total;
  127. }
  128. /** 节点单击事件 */
  129. const handleNodeClick = (data: DeptVO) => {
  130. queryParams.value.deptId = data.id;
  131. handleQuery()
  132. }
  133. /** 搜索按钮操作 */
  134. const handleQuery = () => {
  135. queryParams.value.pageNum = 1
  136. getList()
  137. }
  138. /** 重置按钮操作 */
  139. const resetQuery = () => {
  140. dateRange.value = ['','']
  141. queryFormRef.value.resetFields();
  142. queryParams.value.pageNum = 1;
  143. handleQuery();
  144. }
  145. /** 删除按钮操作 */
  146. const handleDelete = async (row?: UserVO) => {
  147. const userIds = row?.userId || ids.value;
  148. const [err] = await to(proxy?.$modal.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?') as any);
  149. if (!err) {
  150. await delUser(userIds);
  151. await getList();
  152. proxy?.$modal.msgSuccess("删除成功");
  153. }
  154. }
  155. /** 用户状态修改 */
  156. const handleStatusChange = async (row: UserVO) => {
  157. let text = row.status === "0" ? "启用" : "停用"
  158. const [err] = await to(proxy?.$modal.confirm('确认要"' + text + '""' + row.userName + '"用户吗?') as any)
  159. if(err) {
  160. row.status = row.status === "0" ? "1" : "0";
  161. } else {
  162. await changeUserStatus(row.userId, row.status);
  163. proxy?.$modal.msgSuccess(text + "成功");
  164. }
  165. }
  166. /** 跳转角色分配 */
  167. const handleAuthRole = (row: UserVO) => {
  168. const userId = row.userId;
  169. router.push("/system/user-auth/role/" + userId);
  170. }
  171. /** 重置密码按钮操作 */
  172. const handleResetPwd = async (row: UserVO) => {
  173. const [err, res] = await to(ElMessageBox.prompt('请输入"' + row.userName + '"的新密码', "提示", {
  174. confirmButtonText: "确定",
  175. cancelButtonText: "取消",
  176. closeOnClickModal: false,
  177. inputPattern: /^.{5,20}$/,
  178. inputErrorMessage: "用户密码长度必须介于 5 和 20 之间",
  179. }))
  180. if (!err) {
  181. await resetUserPwd(row.userId, res.value);
  182. proxy?.$modal.msgSuccess("修改成功,新密码是:" + res.value);
  183. }
  184. }
  185. /** 选择条数 */
  186. const handleSelectionChange = (selection: UserVO[]) => {
  187. ids.value = selection.map((item) => item.userId);
  188. single.value = selection.length != 1;
  189. multiple.value = !selection.length;
  190. }
  191. /** 导入按钮操作 */
  192. const handleImport = () => {
  193. upload.title = "用户导入";
  194. upload.open = true;
  195. }
  196. /** 导出按钮操作 */
  197. const handleExport = () => {
  198. proxy?.download("system/user/export", {
  199. ...queryParams.value,
  200. }, `user_${new Date().getTime()}.xlsx`);
  201. };
  202. /** 下载模板操作 */
  203. const importTemplate = () => {
  204. proxy?.download("system/user/importTemplate", {
  205. }, `user_template_${new Date().getTime()}.xlsx`);
  206. }
  207. /**文件上传中处理 */
  208. const handleFileUploadProgress = () => {
  209. upload.isUploading = true;
  210. }
  211. /** 文件上传成功处理 */
  212. const handleFileSuccess = (response: any, file: UploadFile, fileList: UploadFiles) => {
  213. upload.open = false;
  214. upload.isUploading = false;
  215. uploadRef.value.handleRemove(file);
  216. ElMessageBox.alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
  217. getList();
  218. }
  219. /** 提交上传文件 */
  220. function submitFileForm() {
  221. uploadRef.value.submit();
  222. }
  223. /** 初始化部门数据 */
  224. const initTreeData = async () => {
  225. // 判断部门的数据是否存在,存在不获取,不存在则获取
  226. if (deptOptions.value === undefined) {
  227. const { data } = await treeselect();
  228. deptOptions.value = data;
  229. }
  230. }
  231. /** 重置操作表单 */
  232. const reset = () => {
  233. form.value = { ...initFormData };
  234. userFormRef.value.resetFields();
  235. }
  236. /** 取消按钮 */
  237. const cancel = () => {
  238. reset();
  239. dialog.visible = false;
  240. }
  241. /** 新增按钮操作 */
  242. const handleAdd = () => {
  243. dialog.visible = true;
  244. dialog.title = "新增用户";
  245. nextTick(async () => {
  246. reset();
  247. await initTreeData();
  248. const { data } = await getUser();
  249. postOptions.value = data.posts;
  250. roleOptions.value = data.roles;
  251. form.value.password = initPassword.value;
  252. })
  253. }
  254. /** 修改按钮操作 */
  255. const handleUpdate = (row?: UserForm) => {
  256. dialog.visible = true;
  257. dialog.title = "修改用户";
  258. nextTick(async () => {
  259. reset();
  260. await initTreeData();
  261. const userId = row?.userId || ids.value[0]
  262. const { data } = await getUser(userId)
  263. Object.assign(form.value, data.user);
  264. postOptions.value = data.posts;
  265. roleOptions.value = data.roles;
  266. form.value.postIds = data.postIds;
  267. form.value.roleIds = data.roleIds;
  268. form.value.password = "";
  269. })
  270. }
  271. /** 提交按钮 */
  272. const submitForm = () => {
  273. userFormRef.value.validate(async (valid: boolean) => {
  274. if (valid) {
  275. form.value.userId ? await updateUser(form.value) : await addUser(form.value);
  276. proxy?.$modal.msgSuccess("操作成功");
  277. dialog.visible = false;
  278. await getList();
  279. }
  280. })
  281. }
  282. /**
  283. * 关闭用户弹窗
  284. */
  285. const closeDialog = () => {
  286. dialog.visible = false;
  287. resetForm();
  288. }
  289. /**
  290. * 重置表单
  291. */
  292. const resetForm = () => {
  293. userFormRef.value.resetFields();
  294. userFormRef.value.clearValidate();
  295. form.value.id = undefined;
  296. form.value.status = '1';
  297. }
  298. onMounted(() => {
  299. getTreeSelect() // 初始化部门数据
  300. getList() // 初始化列表数据
  301. });
  302. </script>
  303. <template>
  304. <div class="p-2">
  305. <el-row :gutter="20">
  306. <!-- 部门树 -->
  307. <el-col :lg="4" :xs="24" style="">
  308. <el-card shadow="never">
  309. <el-input v-model="deptName" placeholder="请输入部门名称" prefix-icon="Search" clearable />
  310. <el-tree
  311. class="mt-2"
  312. ref="deptTreeRef"
  313. :data="deptOptions"
  314. :props="{ label: 'label', children: 'children' }"
  315. :expand-on-click-node="false"
  316. :filter-node-method="filterNode"
  317. highlight-current
  318. default-expand-all
  319. @node-click="handleNodeClick"
  320. ></el-tree>
  321. </el-card>
  322. </el-col>
  323. <el-col :lg="20" :xs="24">
  324. <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
  325. <div class="search" v-show="showSearch">
  326. <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px">
  327. <el-form-item label="用户名称" prop="userName">
  328. <el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable style="width: 240px" @keyup.enter="handleQuery" />
  329. </el-form-item>
  330. <el-form-item label="手机号码" prop="phonenumber">
  331. <el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable style="width: 240px" @keyup.enter="handleQuery" />
  332. </el-form-item>
  333. <el-form-item label="状态" prop="status">
  334. <el-select v-model="queryParams.status" placeholder="用户状态" clearable style="width: 240px">
  335. <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
  336. </el-select>
  337. </el-form-item>
  338. <el-form-item label="创建时间" style="width: 308px;">
  339. <el-date-picker
  340. v-model="dateRange"
  341. value-format="YYYY-MM-DD"
  342. type="daterange"
  343. range-separator="-"
  344. start-placeholder="开始日期"
  345. end-placeholder="结束日期"
  346. ></el-date-picker>
  347. </el-form-item>
  348. <el-form-item>
  349. <el-button type="primary" @click="handleQuery" icon="Search">搜索</el-button>
  350. <el-button @click="resetQuery" icon="Refresh">重置</el-button>
  351. </el-form-item>
  352. </el-form>
  353. </div>
  354. </transition>
  355. <el-card shadow="never">
  356. <template #header>
  357. <el-row :gutter="10">
  358. <el-col :span="1.5">
  359. <el-button type="primary" plain @click="handleAdd()" v-has-permi="['sys:user:add']" icon="Plus">新增</el-button>
  360. </el-col>
  361. <el-col :span="1.5">
  362. <el-button type="success" plain @click="handleUpdate()" :disabled="single" v-has-permi="['sys:user:add']" icon="Edit">修改</el-button>
  363. </el-col>
  364. <el-col :span="1.5">
  365. <el-button type="danger" plain @click="handleDelete()" :disabled="multiple" v-has-permi="['sys:user:delete']" icon="Delete">
  366. 删除
  367. </el-button>
  368. </el-col>
  369. <el-col :span="1.5">
  370. <el-dropdown class="mt-[1px]">
  371. <el-button plain type="info">
  372. 更多
  373. <el-icon class="el-icon--right"><arrow-down /></el-icon
  374. ></el-button>
  375. <template #dropdown>
  376. <el-dropdown-menu>
  377. <el-dropdown-item @click="importTemplate" icon="Download">下载模板</el-dropdown-item>
  378. <el-dropdown-item @click="handleImport" icon="Top"> 导入数据</el-dropdown-item>
  379. <el-dropdown-item @click="handleExport" icon="Download"> 导出数据</el-dropdown-item>
  380. </el-dropdown-menu>
  381. </template>
  382. </el-dropdown>
  383. </el-col>
  384. <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns" :search="true"></right-toolbar>
  385. </el-row>
  386. </template>
  387. <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
  388. <el-table-column type="selection" width="50" align="center" />
  389. <el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
  390. <el-table-column label="用户名称" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
  391. <el-table-column label="用户昵称" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" />
  392. <el-table-column
  393. label="部门"
  394. align="center"
  395. key="deptName"
  396. prop="dept.deptName"
  397. v-if="columns[3].visible"
  398. :show-overflow-tooltip="true"
  399. />
  400. <el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" />
  401. <el-table-column label="状态" align="center" key="status" v-if="columns[5].visible">
  402. <template #default="scope">
  403. <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
  404. </template>
  405. </el-table-column>
  406. <el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[6].visible" width="160">
  407. <template #default="scope">
  408. <span>{{ scope.row.createTime }}</span>
  409. </template>
  410. </el-table-column>
  411. <el-table-column label="操作" fixed="right" width="180" class-name="small-padding fixed-width">
  412. <template #default="scope">
  413. <el-tooltip content="修改" placement="top" v-if="scope.row.userId !== 1">
  414. <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:user:edit']"></el-button>
  415. </el-tooltip>
  416. <el-tooltip content="删除" placement="top" v-if="scope.row.userId !== 1">
  417. <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:user:remove']"></el-button>
  418. </el-tooltip>
  419. <el-tooltip content="重置密码" placement="top" v-if="scope.row.userId !== 1">
  420. <el-button link type="primary" icon="Key" @click="handleResetPwd(scope.row)" v-hasPermi="['system:user:resetPwd']"></el-button>
  421. </el-tooltip>
  422. <el-tooltip content="分配角色" placement="top" v-if="scope.row.userId !== 1">
  423. <el-button link type="primary" icon="CircleCheck" @click="handleAuthRole(scope.row)" v-hasPermi="['system:user:edit']"></el-button>
  424. </el-tooltip>
  425. </template>
  426. </el-table-column>
  427. </el-table>
  428. <pagination
  429. v-show="total > 0"
  430. :total="total"
  431. v-model:page="queryParams.pageNum"
  432. v-model:limit="queryParams.pageSize"
  433. @pagination="handleQuery"
  434. />
  435. </el-card>
  436. </el-col>
  437. </el-row>
  438. <!-- 添加或修改用户配置对话框 -->
  439. <el-dialog :title="dialog.title" v-model="dialog.visible" width="600px" append-to-body @close="closeDialog">
  440. <el-form :model="form" :rules="rules" ref="userFormRef" label-width="80px">
  441. <el-row>
  442. <el-col :span="12">
  443. <el-form-item label="用户昵称" prop="nickName">
  444. <el-input v-model="form.nickName" placeholder="请输入用户昵称" maxlength="30" />
  445. </el-form-item>
  446. </el-col>
  447. <el-col :span="12">
  448. <el-form-item label="归属部门" prop="deptId">
  449. <el-tree-select
  450. v-model="form.deptId"
  451. :data="deptOptions"
  452. :props="{ value: 'id', label: 'label', children: 'children' }"
  453. value-key="id"
  454. placeholder="请选择归属部门"
  455. check-strictly
  456. />
  457. </el-form-item>
  458. </el-col>
  459. </el-row>
  460. <el-row>
  461. <el-col :span="12">
  462. <el-form-item label="手机号码" prop="phonenumber">
  463. <el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11" />
  464. </el-form-item>
  465. </el-col>
  466. <el-col :span="12">
  467. <el-form-item label="邮箱" prop="email">
  468. <el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
  469. </el-form-item>
  470. </el-col>
  471. </el-row>
  472. <el-row>
  473. <el-col :span="12">
  474. <el-form-item v-if="form.userId == undefined" label="用户名称" prop="userName">
  475. <el-input v-model="form.userName" placeholder="请输入用户名称" maxlength="30" />
  476. </el-form-item>
  477. </el-col>
  478. <el-col :span="12">
  479. <el-form-item v-if="form.userId == undefined" label="用户密码" prop="password">
  480. <el-input v-model="form.password" placeholder="请输入用户密码" type="password" maxlength="20" show-password />
  481. </el-form-item>
  482. </el-col>
  483. </el-row>
  484. <el-row>
  485. <el-col :span="12">
  486. <el-form-item label="用户性别">
  487. <el-select v-model="form.sex" placeholder="请选择">
  488. <el-option v-for="dict in sys_user_sex" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
  489. </el-select>
  490. </el-form-item>
  491. </el-col>
  492. <el-col :span="12">
  493. <el-form-item label="状态">
  494. <el-radio-group v-model="form.status">
  495. <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.value">{{
  496. dict.label }}</el-radio>
  497. </el-radio-group>
  498. </el-form-item>
  499. </el-col>
  500. </el-row>
  501. <el-row>
  502. <el-col :span="12">
  503. <el-form-item label="岗位">
  504. <el-select v-model="form.postIds" multiple placeholder="请选择">
  505. <el-option
  506. v-for="item in postOptions"
  507. :key="item.postId"
  508. :label="item.postName"
  509. :value="item.postId"
  510. :disabled="item.status == '1'"
  511. ></el-option>
  512. </el-select>
  513. </el-form-item>
  514. </el-col>
  515. <el-col :span="12">
  516. <el-form-item label="角色">
  517. <el-select v-model="form.roleIds" multiple placeholder="请选择">
  518. <el-option
  519. v-for="item in roleOptions"
  520. :key="item.roleId"
  521. :label="item.roleName"
  522. :value="item.roleId"
  523. :disabled="item.status == '1'"
  524. ></el-option>
  525. </el-select>
  526. </el-form-item>
  527. </el-col>
  528. </el-row>
  529. <el-row>
  530. <el-col :span="24">
  531. <el-form-item label="备注">
  532. <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
  533. </el-form-item>
  534. </el-col>
  535. </el-row>
  536. </el-form>
  537. <template #footer>
  538. <div class="dialog-footer">
  539. <el-button type="primary" @click="submitForm">确 定</el-button>
  540. <el-button @click="cancel()">取 消</el-button>
  541. </div>
  542. </template>
  543. </el-dialog>
  544. <!-- 用户导入对话框 -->
  545. <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
  546. <el-upload
  547. ref="uploadRef"
  548. :limit="1"
  549. accept=".xlsx, .xls"
  550. :headers="upload.headers"
  551. :action="upload.url + '?updateSupport=' + upload.updateSupport"
  552. :disabled="upload.isUploading"
  553. :on-progress="handleFileUploadProgress"
  554. :on-success="handleFileSuccess"
  555. :auto-upload="false"
  556. drag
  557. >
  558. <el-icon class="el-icon--upload">
  559. <i-ep-upload-filled />
  560. </el-icon>
  561. <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
  562. <template #tip>
  563. <div class="text-center el-upload__tip">
  564. <div class="el-upload__tip"><el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据</div>
  565. <span>仅允许导入xls、xlsx格式文件。</span>
  566. <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
  567. </div>
  568. </template>
  569. </el-upload>
  570. <template #footer>
  571. <div class="dialog-footer">
  572. <el-button type="primary" @click="submitFileForm">确 定</el-button>
  573. <el-button @click="upload.open = false">取 消</el-button>
  574. </div>
  575. </template>
  576. </el-dialog>
  577. </div>
  578. </template>
  579. <style lang="scss" scoped></style>