Przeglądaj źródła

Merge branch 'development' of http://8.152.195.41:3000/alien/group_web_merchant into development

LuTong 22 godzin temu
rodzic
commit
55fe7d238d

+ 27 - 26
src/assets/json/authMenuList.json

@@ -880,7 +880,7 @@
       "name": "dynamicManagement",
       "redirect": "/dynamicManagement/index",
       "meta": {
-        "icon": "Operation", 
+        "icon": "Operation",
         "title": "动态",
         "isLink": "",
         "isHide": false,
@@ -1267,7 +1267,7 @@
       "component": "/appoinmentManagement",
       "meta": {
         "icon": "ChatDotSquare",
-        "title": "预服务",
+        "title": "预服务",
         "isLink": "",
         "isHide": false,
         "isFull": false,
@@ -1279,7 +1279,7 @@
           "path": "/appoinmentManagement/classifyManagement",
           "name": "classifyManagement",
           "component": "/appoinmentManagement/classifyManagement",
-          "meta":{
+          "meta": {
             "icon": "ChatDotSquare",
             "title": "分类管理",
             "isLink": "",
@@ -1293,7 +1293,7 @@
           "path": "/appoinmentManagement/tableManagement",
           "name": "tableManagement",
           "component": "/appoinmentManagement/tableManagement",
-          "meta":{
+          "meta": {
             "icon": "ChatDotSquare",
             "title": "桌号管理",
             "isLink": "",
@@ -1307,7 +1307,7 @@
           "path": "/appoinmentManagement/infoManagement",
           "name": "infoManagement",
           "component": "/appoinmentManagement/infoManagement",
-          "meta":{
+          "meta": {
             "icon": "ChatDotSquare",
             "title": "信息设置",
             "isLink": "",
@@ -1319,24 +1319,25 @@
         }
       ]
     },
-      {
+    {
       "path": "/appoinmentManagement/appoinmentInfo",
       "name": "appoinmentInfo",
       "component": "/appoinmentManagement/appoinmentInfo",
-      "meta":{
+      "meta": {
         "icon": "ChatDotSquare",
-        "title": "预信息",
+        "title": "预信息",
         "isLink": "",
         "isHide": false,
         "isFull": false,
         "isAffix": false,
         "isKeepAlive": false
       }
-    },{
+    },
+    {
       "path": "/businessInfo",
       "name": "businessInfo",
       "component": "/businessInfo",
-      "meta":{
+      "meta": {
         "icon": "ChatDotSquare",
         "title": "设置收款账号",
         "isLink": "",
@@ -1350,7 +1351,7 @@
           "path": "/businessInfo/weChartIndex",
           "name": "/businessInfo/weChartIndex",
           "component": "/businessInfo/weChartIndex",
-          "meta":{
+          "meta": {
             "icon": "ChatDotSquare",
             "title": "绑定微信账号",
             "isLink": "",
@@ -1364,7 +1365,7 @@
           "path": "/businessInfo/weChartExamine",
           "name": "/businessInfo/weChartExamine",
           "component": "/businessInfo/weChartExamine",
-          "meta":{
+          "meta": {
             "icon": "ChatDotSquare",
             "title": "查看微信审核状态",
             "isLink": "",
@@ -1378,7 +1379,7 @@
           "path": "/businessInfo/createApply",
           "name": "/businessInfo/createApply",
           "component": "/businessInfo/createApply",
-          "meta":{
+          "meta": {
             "icon": "Document",
             "title": "选择主体类型",
             "isLink": "",
@@ -1387,11 +1388,12 @@
             "isAffix": false,
             "isKeepAlive": false
           }
-        },{
+        },
+        {
           "path": "/businessInfo/dataEntry",
           "name": "/businessInfo/dataEntry",
           "component": "/businessInfo/dataEntry",
-          "meta":{
+          "meta": {
             "icon": "Document",
             "title": "选择主体类型",
             "isLink": "",
@@ -1405,7 +1407,7 @@
           "path": "/businessInfo/subjectInfo",
           "name": "/businessInfo/subjectInfo",
           "component": "/businessInfo/subjectInfo",
-          "meta":{
+          "meta": {
             "icon": "User",
             "title": "主体信息",
             "isLink": "",
@@ -1419,7 +1421,7 @@
           "path": "/businessInfo/manageInfo",
           "name": "/businessInfo/manageInfo",
           "component": "/businessInfo/manageInfo",
-          "meta":{
+          "meta": {
             "icon": "OfficeBuilding",
             "title": "经营信息",
             "isLink": "",
@@ -1433,7 +1435,7 @@
           "path": "/businessInfo/industryQualifications",
           "name": "/businessInfo/industryQualifications",
           "component": "/businessInfo/industryQualifications",
-          "meta":{
+          "meta": {
             "icon": "Document",
             "title": "行业资质",
             "isLink": "",
@@ -1447,7 +1449,7 @@
           "path": "/businessInfo/accountInfo",
           "name": "/businessInfo/accountInfo",
           "component": "/businessInfo/accountInfo",
-          "meta":{
+          "meta": {
             "icon": "Wallet",
             "title": "结算账户",
             "isLink": "",
@@ -1461,7 +1463,7 @@
           "path": "/businessInfo/adminInfo",
           "name": "/businessInfo/adminInfo",
           "component": "/businessInfo/adminInfo",
-          "meta":{
+          "meta": {
             "icon": "UserFilled",
             "title": "超级管理员",
             "isLink": "",
@@ -1471,11 +1473,11 @@
             "isKeepAlive": false
           }
         },
-         {
+        {
           "path": "/businessInfo/zfbIndex",
           "name": "/businessInfo/zfbIndex",
           "component": "/businessInfo/zfbIndex",
-          "meta":{
+          "meta": {
             "icon": "ChatDotSquare",
             "title": "绑定支付宝账号",
             "isLink": "",
@@ -1485,11 +1487,11 @@
             "isKeepAlive": false
           }
         },
-       {
+        {
           "path": "/businessInfo/zfbIndexTwo",
           "name": "/businessInfo/zfbIndexTwo",
           "component": "/businessInfo/zfbIndexTwo",
-          "meta":{
+          "meta": {
             "icon": "ChatDotSquare",
             "title": "完善结算信息",
             "isLink": "",
@@ -1503,7 +1505,7 @@
           "path": "/businessInfo/zfbExamine",
           "name": "/businessInfo/zfbExamine",
           "component": "/businessInfo/zfbExamine",
-          "meta":{
+          "meta": {
             "icon": "ChatDotSquare",
             "title": "查看支付宝审核状态",
             "isLink": "",
@@ -1518,4 +1520,3 @@
   ],
   "msg": "成功"
 }
-

+ 8 - 1
src/layouts/components/Header/components/InfoDialog.vue

@@ -73,12 +73,18 @@ const imageViewerVisible = ref(false);
 const imageViewerUrlList = ref<string[]>([]);
 const imageViewerInitialIndex = ref(0);
 
+/** 与 ToolBarRight 右上角用户名一致:优先 name,否则 nickName */
+function displayNameLikeHeader(data: Record<string, any> | null | undefined): string {
+  if (!data) return "";
+  return data.name != null ? String(data.name) : String(data.nickName ?? "");
+}
+
 const getUserInfo = async () => {
   const res: any = await getMerchantByPhone({ phone: userInfo.phone });
   if (res.code == 200) {
     // 保存用户ID
     userId.value = res.data.id || res.data.userId || "";
-    form.nickname = res.data.nickName || "";
+    form.nickname = displayNameLikeHeader(res.data);
     form.intro = res.data.accountBlurb || "";
     // 设置头像
     const headImg = res.data.headImg;
@@ -158,6 +164,7 @@ const getSaveUserInfo = async () => {
 
     const res: any = await updateMerchantUserInfo({
       id: userId.value,
+      name: form.nickname,
       nickName: form.nickname,
       headImg: avatarUrl || "",
       accountBlurb: form.intro

+ 2 - 2
src/views/appoinmentManagement/classifyManagement.vue

@@ -319,7 +319,7 @@ async function handleEdit(row: CategoryRow) {
   try {
     const has = await categoryHasReservation(row.id);
     if (has) {
-      ElMessage.warning("此分类所属桌号有预信息,不可修改");
+      ElMessage.warning("此分类所属桌号有预信息,不可修改");
       return;
     }
   } catch (e: any) {
@@ -369,7 +369,7 @@ async function handleDelete(row: CategoryRow) {
   try {
     const has = await categoryHasReservation(row.id);
     if (has) {
-      ElMessage.warning("此分类所属桌号有预信息,不可修改");
+      ElMessage.warning("此分类所属桌号有预信息,不可修改");
       return;
     }
   } catch (e: any) {

+ 13 - 10
src/views/appoinmentManagement/tableManagement.vue

@@ -43,7 +43,7 @@
         v-loading="detailLoading"
         require-asterisk-position="right"
       >
-        <el-form-item label="选择分类" prop="categoryId" required>
+        <el-form-item label="选择分类" prop="categoryId">
           <el-select v-model="form.categoryId" placeholder="请选择分类" clearable>
             <el-option v-for="item in categoryOptions" :key="item.id" :label="item.name" :value="item.id" />
           </el-select>
@@ -55,7 +55,7 @@
             <el-button type="primary" link @click="addTableRow"> 添加 </el-button>
           </div>
           <template v-for="(row, index) in form.tableRows" :key="index">
-            <el-form-item label="桌号" :prop="'tableRows.' + index + '.tableNo'" :rules="tableNoFieldRules" required>
+            <el-form-item label="桌号" :prop="'tableRows.' + index + '.tableNo'" :rules="tableNoFieldRules">
               <el-input
                 :model-value="row.tableNo"
                 placeholder="如 A01"
@@ -63,7 +63,7 @@
                 @update:model-value="(val: string) => onTableNumberInput(row, val)"
               />
             </el-form-item>
-            <el-form-item label="座位数" :prop="'tableRows.' + index + '.seatCount'" :rules="seatCountFieldRulesRow" required>
+            <el-form-item label="座位数" :prop="'tableRows.' + index + '.seatCount'" :rules="seatCountFieldRulesRow">
               <el-input
                 :model-value="row.seatCount"
                 placeholder="请输入"
@@ -81,7 +81,7 @@
 
         <!-- 编辑:单条 -->
         <template v-else>
-          <el-form-item label="桌号" prop="tableNo" required>
+          <el-form-item label="桌号" prop="tableNo">
             <el-input
               :model-value="form.tableNo"
               placeholder="如 A01"
@@ -90,7 +90,7 @@
               @update:model-value="onTableNumberInputEdit"
             />
           </el-form-item>
-          <el-form-item label="座位数" prop="seatCount" required>
+          <el-form-item label="座位数" prop="seatCount">
             <el-input
               :model-value="seatCountEditDisplay"
               placeholder="请输入"
@@ -281,12 +281,14 @@ const form = reactive<{
 /** 与 group_merchant/pages/scheduledService/addTableNumber.vue 一致 */
 const TABLE_NUMBER_REG = /^[A-Z][0-9]{2}$/;
 
+/** 勿在 el-form-item 上写 required:会注入无 message 的必填规则,嵌套 prop 会报英文「tableRows.0.xxx is required」 */
 const tableNoFieldRules: FormItemRule[] = [
+  { required: true, message: "请输入桌号", trigger: ["blur", "change"] },
   {
     validator: (_rule, value, callback) => {
       const num = String(value ?? "").trim();
       if (!num) {
-        callback(new Error("请输入桌号"));
+        callback();
         return;
       }
       if (!TABLE_NUMBER_REG.test(num)) {
@@ -300,11 +302,12 @@ const tableNoFieldRules: FormItemRule[] = [
 ];
 
 const seatCountFieldRulesRow: FormItemRule[] = [
+  { required: true, message: "请输入座位数", trigger: ["blur", "change"] },
   {
     validator: (_rule, value, callback) => {
       const seat = String(value ?? "").trim();
       if (!seat) {
-        callback(new Error("请输入座位数"));
+        callback();
         return;
       }
       const n = parseInt(seat, 10);
@@ -391,7 +394,7 @@ function onSeatCountInputEdit(val: string) {
 /** 新建只校验分类 + 各行(行规则在 el-form-item 上);编辑校验分类 + 单条桌号/座位数 */
 const formRules = computed<FormRules>(() => {
   const base: FormRules = {
-    categoryId: [{ required: true, message: "请选择位置", trigger: "change" }]
+    categoryId: [{ required: true, message: "请选择分类", trigger: "change" }]
   };
   if (editId.value != null) {
     base.tableNo = tableNoFieldRules;
@@ -422,7 +425,7 @@ async function handleEdit(row: TableRow) {
   try {
     const has = await tableHasReservation(row.id);
     if (has) {
-      ElMessage.warning("此分类所属桌号有预信息,不可修改");
+      ElMessage.warning("此分类所属桌号有预信息,不可修改");
       return;
     }
   } catch (e: any) {
@@ -462,7 +465,7 @@ async function handleDelete(row: TableRow) {
   try {
     const has = await tableHasReservation(row.id);
     if (has) {
-      ElMessage.warning("此分类所属桌号有预信息,不可修改");
+      ElMessage.warning("此分类所属桌号有预信息,不可修改");
       return;
     }
   } catch (e: any) {

+ 1 - 1
src/views/home/components/go-flow.vue

@@ -219,7 +219,7 @@
                   <el-input v-model="step2Form.storePj[2]" placeholder="请输入" maxlength="2" clearable class="store-pj-input" />
                 </div>
               </el-form-item>
-              <el-form-item label="预服务">
+              <el-form-item label="预服务">
                 <el-radio-group v-model="step2Form.appointment">
                   <el-radio label="提供"> 提供 </el-radio>
                   <el-radio label="不提供"> 不提供 </el-radio>

+ 61 - 28
src/views/storeDecoration/decorationChat.vue

@@ -16,9 +16,25 @@
       </div>
       <div v-else class="message-list">
         <div v-for="(msg, index) in messages" :key="msg.id || index" :class="['message-item', isMine(msg) ? 'mine' : 'other']">
-          <el-avatar class="msg-avatar" :src="isMine(msg) ? myAvatar : ownerAvatar" :size="40">
-            <!-- <span class="avatar-fallback">{{ (isMine(msg) ? myName : ownerName).slice(0, 1) }}</span> -->
-          </el-avatar>
+          <!-- 与 dynamicManagement/myDynamic 一致:有图用 headImg 链,无图用灰底 + Avatar 图标(勿用 localhost 假地址) -->
+          <div class="msg-avatar">
+            <template v-if="isMine(msg)">
+              <img v-if="myAvatarUrl" :src="myAvatarUrl" class="msg-avatar-img" alt="" />
+              <div v-else class="msg-avatar-fallback" aria-hidden="true">
+                <el-icon :size="22">
+                  <Avatar />
+                </el-icon>
+              </div>
+            </template>
+            <template v-else>
+              <img v-if="ownerAvatarDisplay" :src="ownerAvatarDisplay" class="msg-avatar-img" alt="" />
+              <div v-else class="msg-avatar-fallback" aria-hidden="true">
+                <el-icon :size="22">
+                  <Avatar />
+                </el-icon>
+              </div>
+            </template>
+          </div>
           <div class="msg-body">
             <div class="msg-time">
               {{ msg.createdTime }}
@@ -96,7 +112,7 @@
 import { ref, computed, onMounted, onBeforeUnmount, nextTick, watch } from "vue";
 import { useRoute, useRouter } from "vue-router";
 import { ElMessage } from "element-plus";
-import { ArrowLeft, Loading, Picture, VideoPlay } from "@element-plus/icons-vue";
+import { ArrowLeft, Avatar, Loading, Picture, VideoPlay } from "@element-plus/icons-vue";
 import { useWebSocketStore } from "@/stores/modules/websocket";
 import { getChatRecord, messageRead, socketStatus, uploadChatFile } from "@/api/modules/storeDecoration";
 import { localGet } from "@/utils";
@@ -128,14 +144,23 @@ let statusTimer: ReturnType<typeof setInterval> | null = null;
 
 const userInfo = computed(() => localGet("geeker-user")?.userInfo || {});
 
-// 自己头像与名称(用于气泡旁头像)
-const myAvatar = computed(
-  () =>
-    userInfo.value?.headImg ||
-    userInfo.value?.avatar ||
-    userInfo.value?.userImage ||
-    "http://localhost:5173/static/activity/avatar.svg"
-);
+/** 与 myDynamic.vue「cachedHeadImg」一致:geeker-user 的 headImg → avatar;无有效地址则空串走图标占位 */
+function pickUserHeadUrl(u: Record<string, any> | undefined): string {
+  if (!u) return "";
+  const raw = u.headImg || u.avatar || u.userImage || "";
+  const s = String(raw).trim();
+  return s;
+}
+
+const myAvatarUrl = computed(() => pickUserHeadUrl(userInfo.value as Record<string, any>));
+
+const ownerAvatarDisplay = computed(() => {
+  const s = String(ownerAvatar.value ?? "").trim();
+  if (!s) return "";
+  // 历史占位:无效本地路径,与 myDynamic 无头像态一致改用语义占位
+  if (s.includes("localhost:5173/static/activity/avatar.svg")) return "";
+  return s;
+});
 
 const isMine = (msg: any) => String(msg.senderId || "") === String(sendId.value);
 
@@ -435,9 +460,7 @@ watch(
     if (q?.receiverId) {
       receiverId.value = String(q.receiverId);
       ownerName.value = decodeURIComponent(String(q.uName || q.ownerName || "业主"));
-      ownerAvatar.value = q.userImage
-        ? decodeURIComponent(String(q.userImage))
-        : "http://localhost:5173/static/activity/avatar.svg";
+      ownerAvatar.value = q.userImage ? decodeURIComponent(String(q.userImage)) : "";
       requirementId.value = String(q.id || q.requirementId || "");
       loadChatRecord();
     }
@@ -448,9 +471,7 @@ watch(
 onMounted(async () => {
   receiverId.value = String(route.query.receiverId || "");
   ownerName.value = decodeURIComponent(String(route.query.uName || route.query.ownerName || "业主"));
-  ownerAvatar.value = route.query.userImage
-    ? decodeURIComponent(String(route.query.userImage))
-    : "http://localhost:5173/static/activity/avatar.svg";
+  ownerAvatar.value = route.query.userImage ? decodeURIComponent(String(route.query.userImage)) : "";
   requirementId.value = String(route.query.id || route.query.requirementId || "");
 
   if (!receiverId.value) {
@@ -520,17 +541,29 @@ onBeforeUnmount(() => {
     align-items: flex-start;
     .msg-avatar {
       flex-shrink: 0;
+      width: 40px;
+      height: 40px;
       overflow: hidden;
-      .avatar-fallback {
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        width: 100%;
-        height: 100%;
-        font-size: 16px;
-        color: #ffffff;
-        background: #c0c4cc;
-      }
+      border-radius: 50%;
+    }
+    .msg-avatar-img {
+      display: block;
+      width: 40px;
+      height: 40px;
+      object-fit: cover;
+      border-radius: 50%;
+    }
+
+    /* 与 myDynamic .user-avatar-large 无图态一致:浅灰圆底 + User 轮廓图标 */
+    .msg-avatar-fallback {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      width: 40px;
+      height: 40px;
+      color: #909399;
+      background: #f5f7fa;
+      border-radius: 50%;
     }
     &.mine {
       flex-direction: row-reverse;