From 25df88d0ab9d7444ed1d162b9efa1259ac2f6f66 Mon Sep 17 00:00:00 2001
From: longz <longzhaoz@qq.com>
Date: 星期一, 27 四月 2026 10:13:53 +0800
Subject: [PATCH] 小程序对接finish

---
 frontend-admin/src/views/UsersView.vue |   82 +++++++++++++++++++++++++++++++++++++++--
 1 files changed, 78 insertions(+), 4 deletions(-)

diff --git a/frontend-admin/src/views/UsersView.vue b/frontend-admin/src/views/UsersView.vue
index 41aca17..d4037e9 100644
--- a/frontend-admin/src/views/UsersView.vue
+++ b/frontend-admin/src/views/UsersView.vue
@@ -101,8 +101,22 @@
         <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%">
@@ -133,8 +147,22 @@
         <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%">
@@ -174,6 +202,7 @@
 <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 };
@@ -191,6 +220,7 @@
 
 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);
@@ -377,6 +407,31 @@
   }
 }
 
+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;
@@ -489,4 +544,23 @@
   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>

--
Gitblit v1.7.1