| | |
| | | <el-form-item label="手机"> |
| | | <el-input v-model="createForm.mobile" /> |
| | | </el-form-item> |
| | | <el-form-item label="头像URL"> |
| | | <el-input v-model="createForm.avatarUrl" placeholder="可选" /> |
| | | <el-form-item label="头像"> |
| | | <div class="avatar-upload-row"> |
| | | <el-avatar v-if="createForm.avatarUrl" :size="64" :src="createForm.avatarUrl" /> |
| | | <el-avatar v-else :size="64">{{ (createForm.realName || createForm.username || "?").slice(0, 1) }}</el-avatar> |
| | | <div class="avatar-upload-actions"> |
| | | <el-upload |
| | | :show-file-list="false" |
| | | accept=".jpg,.jpeg,.png,.webp,.gif" |
| | | :http-request="(opt) => uploadAvatar(opt, 'create')" |
| | | > |
| | | <el-button :loading="avatarUploading === 'create'">上传头像</el-button> |
| | | </el-upload> |
| | | <el-button v-if="createForm.avatarUrl" link type="danger" @click="createForm.avatarUrl = ''">清除</el-button> |
| | | <div class="avatar-upload-tip">支持 jpg、png、webp、gif,大小不超过 5MB</div> |
| | | </div> |
| | | </div> |
| | | </el-form-item> |
| | | <el-form-item label="角色" required> |
| | | <el-select v-model="createForm.roleIds" multiple placeholder="必选,可多选" style="width: 100%"> |
| | |
| | | <el-form-item label="手机"> |
| | | <el-input v-model="editForm.mobile" /> |
| | | </el-form-item> |
| | | <el-form-item label="头像URL"> |
| | | <el-input v-model="editForm.avatarUrl" /> |
| | | <el-form-item label="头像"> |
| | | <div class="avatar-upload-row"> |
| | | <el-avatar v-if="editForm.avatarUrl" :size="64" :src="editForm.avatarUrl" /> |
| | | <el-avatar v-else :size="64">{{ (editForm.realName || editForm.username || "?").slice(0, 1) }}</el-avatar> |
| | | <div class="avatar-upload-actions"> |
| | | <el-upload |
| | | :show-file-list="false" |
| | | accept=".jpg,.jpeg,.png,.webp,.gif" |
| | | :http-request="(opt) => uploadAvatar(opt, 'edit')" |
| | | > |
| | | <el-button :loading="avatarUploading === 'edit'">上传头像</el-button> |
| | | </el-upload> |
| | | <el-button v-if="editForm.avatarUrl" link type="danger" @click="editForm.avatarUrl = ''">清除</el-button> |
| | | <div class="avatar-upload-tip">支持 jpg、png、webp、gif,大小不超过 5MB</div> |
| | | </div> |
| | | </div> |
| | | </el-form-item> |
| | | <el-form-item label="角色" required> |
| | | <el-select v-model="editForm.roleIds" multiple placeholder="必选" style="width: 100%"> |
| | |
| | | <script setup lang="ts"> |
| | | import { onMounted, reactive, ref } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import type { UploadRequestOptions } from "element-plus"; |
| | | import http from "../api/http"; |
| | | |
| | | type RoleRow = { id: number; roleCode: string; roleName: string }; |
| | |
| | | |
| | | const loading = ref(false); |
| | | const saving = ref(false); |
| | | const avatarUploading = ref<"create" | "edit" | "">(""); |
| | | const rows = ref<UserRow[]>([]); |
| | | const page = ref(1); |
| | | const size = ref(10); |
| | |
| | | } |
| | | } |
| | | |
| | | async function uploadAvatar(opt: UploadRequestOptions, target: "create" | "edit") { |
| | | const fd = new FormData(); |
| | | fd.append("file", opt.file as File); |
| | | avatarUploading.value = target; |
| | | try { |
| | | const { data } = await http.post("/common/upload/image", fd, { |
| | | headers: { "Content-Type": "multipart/form-data" }, |
| | | }); |
| | | const url = String(data.result?.url || ""); |
| | | if (!url) { |
| | | throw new Error("上传结果缺少图片地址"); |
| | | } |
| | | if (target === "create") { |
| | | createForm.avatarUrl = url; |
| | | } else { |
| | | editForm.avatarUrl = url; |
| | | } |
| | | ElMessage.success("头像上传成功"); |
| | | } catch (e: unknown) { |
| | | ElMessage.error(e instanceof Error ? e.message : "头像上传失败"); |
| | | } finally { |
| | | avatarUploading.value = ""; |
| | | } |
| | | } |
| | | |
| | | function openResetPwd(row: UserRow) { |
| | | pwdUserId.value = row.id; |
| | | pwdUserUuid.value = row.uuid; |
| | |
| | | margin-top: 12px; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .avatar-upload-row { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 14px; |
| | | } |
| | | |
| | | .avatar-upload-actions { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .avatar-upload-tip { |
| | | color: #8a97b3; |
| | | font-size: 12px; |
| | | line-height: 1.4; |
| | | } |
| | | </style> |