Просмотр исходного кода

花掌柜设置,金刚区默认图标设置优化

ouyang 10 часов назад
Родитель
Сommit
033c90510e

+ 36 - 39
hdApp/src/admin/homePageConfig/navGrid.vue

@@ -37,7 +37,12 @@
         >
           <view class="list-num">{{ index + 1 }}</view>
           <view class="item-icon">
-            <text v-if="isPresetIcon(item.icon)" class="icon-emoji">{{ getPresetEmoji(item.icon) }}</text>
+            <image
+              v-if="isPresetIcon(item.icon)"
+              class="icon-img"
+              :src="presetIconFullUrl(item.icon)"
+              mode="aspectFill"
+            />
             <image v-else class="icon-img" :src="iconFullUrl(item.icon)" mode="aspectFill" />
           </view>
           <!-- 小程序 data-event-opts 不能可靠序列化对象参数,改为传 index -->
@@ -89,7 +94,12 @@
         <view v-else class="preview-grid" :class="'cols-' + form.cols">
           <view v-for="item in previewList" :key="item.id" class="preview-item">
             <view class="preview-icon-wrap">
-              <text v-if="isPresetIcon(item.icon)" class="preview-emoji">{{ getPresetEmoji(item.icon) }}</text>
+              <image
+                v-if="isPresetIcon(item.icon)"
+                class="preview-icon-img"
+                :src="presetIconFullUrl(item.icon)"
+                mode="aspectFill"
+              />
               <image v-else class="preview-icon-img" :src="iconFullUrl(item.icon)" mode="aspectFill" />
             </view>
             <text class="preview-name">{{ item.name }}</text>
@@ -112,20 +122,16 @@ import { getNavGrid, saveNavGrid } from '@/api/home-page-config'
 const DRAFT_KEY = 'navGridDraft'
 const MAX_NAV_COUNT = 20
 
-/** 预设图标 key → emoji,与编辑页 preset 列表一致 */
-const PRESET_EMOJI_MAP = {
-  'preset:1': '🌸',
-  'preset:2': '💐',
-  'preset:3': '🌹',
-  'preset:4': '🌻',
-  'preset:5': '🌺',
-  'preset:6': '🪴',
-  'preset:7': '🎂',
-  'preset:8': '💒',
-  'preset:9': '🎁',
-  'preset:10': '❤️',
-  'preset:11': '🏠',
-  'preset:12': '⭐'
+/** 默认图标库:preset:N → OSS 路径,与编辑页一致 */
+const PRESET_ICON_PATH_PREFIX = 'hhb/images/navGrid-default/navGrid-default'
+
+/** 由 preset:N 解析出静态图相对路径;非法则返回空 */
+function getPresetIconPath(icon) {
+  const m = String(icon || '').match(/^preset:(\d+)$/)
+  if (!m) return ''
+  const n = parseInt(m[1], 10)
+  if (n < 1 || n > 12) return ''
+  return `${PRESET_ICON_PATH_PREFIX}${n}.png`
 }
 
 export default {
@@ -239,8 +245,9 @@ export default {
     isPresetIcon(icon) {
       return icon && String(icon).indexOf('preset:') === 0
     },
-    getPresetEmoji(icon) {
-      return PRESET_EMOJI_MAP[icon] || '📦'
+    /** 默认图标库完整 URL */
+    presetIconFullUrl(icon) {
+      return this.iconFullUrl(getPresetIconPath(icon))
     },
     iconFullUrl(path) {
       if (!path) return ''
@@ -494,7 +501,7 @@ export default {
 
 .list-item {
   @include disFlex(center, flex-start);
-  height: 120upx;
+  height: 145upx;
   padding: 0 24upx;
   border-bottom: 1px solid $borderColor;
   background: #fff;
@@ -517,22 +524,17 @@ export default {
 }
 
 .item-icon {
-  width: 64upx;
-  height: 64upx;
+  width: 117upx;
+  height: 117upx;
   flex-shrink: 0;
   margin-right: 16upx;
   @include disFlex(center, center);
 }
 
-.icon-emoji {
-  font-size: 44upx;
-  line-height: 1;
-}
-
 .icon-img {
-  width: 64upx;
-  height: 64upx;
-  border-radius: 12upx;
+  width: 117upx;
+  height: 117upx;
+  border-radius: 50%;
 }
 
 .list-main {
@@ -646,21 +648,16 @@ export default {
 }
 
 .preview-icon-wrap {
-  width: 80upx;
-  height: 80upx;
+  width: 117upx;
+  height: 117upx;
   @include disFlex(center, center);
   margin-bottom: 8upx;
 }
 
-.preview-emoji {
-  font-size: 52upx;
-  line-height: 1;
-}
-
 .preview-icon-img {
-  width: 72upx;
-  height: 72upx;
-  border-radius: 16upx;
+  width: 117upx;
+  height: 117upx;
+  border-radius: 50%;
 }
 
 .preview-name {

+ 17 - 22
hdApp/src/admin/homePageConfig/navGridEdit.vue

@@ -1,6 +1,6 @@
 <!--
   分类金刚区导航项编辑页
-  新增/编辑单个导航:名称、图标(预设 emoji 或上传)、关联分类/场景;保存回写列表页草稿后返回。
+  新增/编辑单个导航:名称、图标(默认图库 PNG 或上传)、关联分类/场景;保存回写列表页草稿后返回。
 -->
 <template>
   <view class="page-container">
@@ -32,7 +32,7 @@
           >上传图片</view>
         </view>
 
-        <!-- 预设 emoji 图标库 -->
+        <!-- 默认图标库:OSS 静态图 hhb/images/navGrid-default/navGrid-defaultN.png -->
         <view v-if="iconTab === 'preset'" class="preset-grid">
           <view
             v-for="preset in presetIcons"
@@ -41,7 +41,7 @@
             :class="{ active: form.icon === preset.key && form.iconType === 1 }"
             @click="selectPreset(preset)"
           >
-            <text class="preset-emoji">{{ preset.emoji }}</text>
+            <image class="preset-img" :src="iconFullUrl(preset.path)" mode="aspectFill" />
           </view>
         </view>
 
@@ -148,21 +148,14 @@ import { useCaseList } from '@/api/goods'
 
 const DRAFT_KEY = 'navGridDraft'
 
-/** 预设图标:icon 存 preset:N,iconType=1 */
-const PRESET_ICONS = [
-  { key: 'preset:1', emoji: '🌸' },
-  { key: 'preset:2', emoji: '💐' },
-  { key: 'preset:3', emoji: '🌹' },
-  { key: 'preset:4', emoji: '🌻' },
-  { key: 'preset:5', emoji: '🌺' },
-  { key: 'preset:6', emoji: '🪴' },
-  { key: 'preset:7', emoji: '🎂' },
-  { key: 'preset:8', emoji: '💒' },
-  { key: 'preset:9', emoji: '🎁' },
-  { key: 'preset:10', emoji: '❤️' },
-  { key: 'preset:11', emoji: '🏠' },
-  { key: 'preset:12', emoji: '⭐' }
-]
+/** 默认图标库:icon 仍存 preset:N(iconType=1),展示对应 OSS 静态图 */
+const PRESET_ICONS = Array.from({ length: 12 }, (_, i) => {
+  const n = i + 1
+  return {
+    key: `preset:${n}`,
+    path: `hhb/images/navGrid-default/navGrid-default${n}.png`
+  }
+})
 
 const EMPTY_FORM = () => ({
   id: '',
@@ -533,12 +526,13 @@ export default {
 
 .preset-item {
   width: 20%;
-  height: 100upx;
+  height: 140upx;
   @include disFlex(center, center);
   box-sizing: border-box;
   border: 2upx solid transparent;
   border-radius: 12upx;
   margin-bottom: 12upx;
+  padding: 8upx;
 
   &.active {
     border-color: #09C567;
@@ -546,9 +540,10 @@ export default {
   }
 }
 
-.preset-emoji {
-  font-size: 52upx;
-  line-height: 1;
+.preset-img {
+  width: 117upx;
+  height: 117upx;
+  border-radius: 50%;
 }
 
 .upload-area {

+ 32 - 27
hdApp/src/admin/homePageConfig/previewParts/navGrid.vue

@@ -1,13 +1,13 @@
 <!--
   首页预览-分类金刚区导航
-  只读展示:按 cols(4/5) 渲染图标网格,预设图标本地映射为 emoji,上传图标用后端返回的完整URL
+  只读展示:按 cols(4/5) 渲染图标网格;
+  默认图标库 preset:N → hhb/images/navGrid-default/navGrid-defaultN.png,上传图标用后端完整 URL
 -->
 <template>
   <view v-if="data && data.enabled == 1 && data.list && data.list.length" class="pv-nav-grid" :class="'cols-' + (data.cols || 5)">
     <view v-for="item in data.list" :key="item.id" class="pv-nav-item">
       <view class="pv-nav-icon-wrap">
-        <text v-if="isPresetIcon(item.icon)" class="pv-nav-emoji">{{ getPresetEmoji(item.icon) }}</text>
-        <image v-else class="pv-nav-icon-img" :src="item.iconUrl" mode="aspectFill" />
+        <image class="pv-nav-icon-img" :src="resolveIconSrc(item)" mode="aspectFill" />
       </view>
       <text class="pv-nav-name">{{ item.name }}</text>
     </view>
@@ -15,20 +15,16 @@
 </template>
 
 <script>
-/** 预设图标 key → emoji,与后台 navGrid 编辑页 preset 列表一致 */
-const PRESET_EMOJI_MAP = {
-  'preset:1': '🌸',
-  'preset:2': '💐',
-  'preset:3': '🌹',
-  'preset:4': '🌻',
-  'preset:5': '🌺',
-  'preset:6': '🪴',
-  'preset:7': '🎂',
-  'preset:8': '💒',
-  'preset:9': '🎁',
-  'preset:10': '❤️',
-  'preset:11': '🏠',
-  'preset:12': '⭐'
+/** 默认图标库相对路径前缀,与后台编辑页一致 */
+const PRESET_ICON_PATH_PREFIX = 'hhb/images/navGrid-default/navGrid-default'
+
+/** 由 preset:N 解析 OSS 相对路径 */
+function getPresetIconPath(icon) {
+  const m = String(icon || '').match(/^preset:(\d+)$/)
+  if (!m) return ''
+  const n = parseInt(m[1], 10)
+  if (n < 1 || n > 12) return ''
+  return `${PRESET_ICON_PATH_PREFIX}${n}.png`
 }
 
 export default {
@@ -43,8 +39,19 @@ export default {
     isPresetIcon(icon) {
       return icon && String(icon).indexOf('preset:') === 0
     },
-    getPresetEmoji(icon) {
-      return PRESET_EMOJI_MAP[icon] || '📦'
+    iconFullUrl(path) {
+      if (!path) return ''
+      if (String(path).indexOf('http') === 0) return path
+      const base = (this.constant.imgUrl || '').replace(/\/$/, '')
+      return `${base}/${String(path).replace(/^\//, '')}`
+    },
+    /** 预设走静态图;上传优先用后端 iconUrl */
+    resolveIconSrc(item) {
+      if (!item) return ''
+      if (this.isPresetIcon(item.icon)) {
+        return this.iconFullUrl(getPresetIconPath(item.icon))
+      }
+      return item.iconUrl || this.iconFullUrl(item.icon)
     }
   }
 }
@@ -52,10 +59,10 @@ export default {
 
 <style lang="scss" scoped>
 .pv-nav-grid {
-  display: flex;
+  @include disFlex(flex-start, flex-start);
   flex-wrap: wrap;
-  padding: 20upx 12upx;
   background: #fff;
+  padding: 16upx 8upx 0;
 }
 .pv-nav-grid.cols-4 .pv-nav-item {
   width: 25%;
@@ -74,16 +81,14 @@ export default {
   width: 88upx;
   height: 88upx;
   border-radius: 50%;
-  background: #FFF3F5;
+  overflow: hidden;
   @include disFlex(center, center);
   margin-bottom: 10upx;
 }
-.pv-nav-emoji {
-  font-size: 40upx;
-}
 .pv-nav-icon-img {
-  width: 60upx;
-  height: 60upx;
+  width: 88upx;
+  height: 88upx;
+  border-radius: 50%;
 }
 .pv-nav-name {
   font-size: 24upx;

+ 33 - 23
mallApp/src/components/home/navGrid.vue

@@ -1,15 +1,13 @@
 <!--
   店铺首页-分类金刚区导航
-  按 cols(4/5) 渲染图标网格;预设图标本地映射为 emoji,上传图标使用后端返回完整URL
+  按 cols(4/5) 渲染图标网格;默认图标库 preset:N 映射 OSS 静态图,上传图标用后端 iconUrl
   点击导航项跳转商品列表页,并按关联类型(分类/场景)带上初始筛选条件
 -->
 <template>
   <view v-if="data && data.enabled == 1 && data.list && data.list.length" class="home-nav-grid" :class="'cols-' + (data.cols || 5)">
     <view v-for="item in data.list" :key="item.id" class="nav-item" @click="onTap(item)">
       <view class="nav-icon-wrap">
-        <text v-if="isPresetIcon(item.icon)" class="nav-emoji">{{ getPresetEmoji(item.icon) }}</text>
-        <!-- 上传图标只显示 80upx,按 120px 取缩略图,不再拉取商家上传原图 -->
-        <app-lazy-img v-else class="nav-icon-img" :src="item.iconUrl" :thumb-width="120" mode="aspectFill" />
+        <app-lazy-img class="nav-icon-img" :src="resolveIconSrc(item)" :thumb-width="120" mode="aspectFill" />
       </view>
       <text class="nav-name">{{ item.name }}</text>
     </view>
@@ -20,20 +18,16 @@
 import { parseFilterIds, encodeFilterValue, stashGoodsListFilter } from '@/utils/goodsListFilter'
 import AppLazyImg from '@/components/app-lazy-img.vue'
 
-/** 预设图标 key → emoji,与 hdApp 后台 navGrid 编辑页 preset 列表一致 */
-const PRESET_EMOJI_MAP = {
-  'preset:1': '🌸',
-  'preset:2': '💐',
-  'preset:3': '🌹',
-  'preset:4': '🌻',
-  'preset:5': '🌺',
-  'preset:6': '🪴',
-  'preset:7': '🎂',
-  'preset:8': '💒',
-  'preset:9': '🎁',
-  'preset:10': '❤️',
-  'preset:11': '🏠',
-  'preset:12': '⭐'
+/** 默认图标库相对路径前缀,与 hdApp 后台 navGrid 编辑页一致 */
+const PRESET_ICON_PATH_PREFIX = 'hhb/images/navGrid-default/navGrid-default'
+
+/** 由 preset:N 解析 OSS 相对路径;非法返回空 */
+function getPresetIconPath(icon) {
+  const m = String(icon || '').match(/^preset:(\d+)$/)
+  if (!m) return ''
+  const n = parseInt(m[1], 10)
+  if (n < 1 || n > 12) return ''
+  return `${PRESET_ICON_PATH_PREFIX}${n}.png`
 }
 
 export default {
@@ -57,8 +51,27 @@ export default {
     isPresetIcon(icon) {
       return icon && String(icon).indexOf('preset:') === 0
     },
-    getPresetEmoji(icon) {
-      return PRESET_EMOJI_MAP[icon] || '📦'
+    iconFullUrl(path) {
+      if (!path) return ''
+      if (String(path).indexOf('http') === 0) return path
+      const base = (this.constant.imgUrl || '').replace(/\/$/, '')
+      return `${base}/${String(path).replace(/^\//, '')}`
+    },
+    /**
+     * 解析金刚区图标地址:预设用静态图;否则优先后端 iconUrl
+     * @param {Object} item
+     * @returns {string}
+     */
+    resolveIconSrc(item) {
+      if (!item) return ''
+      if (this.isPresetIcon(item.icon)) {
+        // 后端已组装完整 URL 时直接用,否则前端拼接 CDN
+        if (item.iconUrl && String(item.iconUrl).indexOf('http') === 0) {
+          return item.iconUrl
+        }
+        return this.iconFullUrl(getPresetIconPath(item.icon))
+      }
+      return item.iconUrl || this.iconFullUrl(item.icon)
     },
     /**
      * 点击金刚区项:跳转商品列表,并按关联类型带上初始筛选
@@ -114,9 +127,6 @@ export default {
   justify-content: center;
   margin-bottom: 13upx;
 }
-.nav-emoji {
-  font-size: 53upx;
-}
 /* display:block 保证小程序端自定义组件包裹节点能接受宽高,否则内部图片会塌陷 */
 .nav-icon-img {
   width: 117upx;

+ 10 - 98
mallApp/src/pages/home/shop-category.vue

@@ -100,7 +100,7 @@
           </view>
         </block>
 
-        <!-- 花束分类(category/list,平铺展示) -->
+        <!-- 花束分类(category/list 平铺):无图标,名称水平+垂直居中 -->
         <view
           v-for="cat in bouquetCategories"
           :key="cat.id"
@@ -109,22 +109,7 @@
           :data-id="cat.id"
           @tap.stop="onBouquetNavTapByEvent"
         >
-          <image
-            v-if="getBouquetIcon(cat)"
-            class="bouquet-cate-icon"
-            :src="getBouquetIcon(cat)"
-            mode="aspectFill"
-          />
-          <view
-            class="bouquet-cate-name-wrap"
-            :id="'bouquet-name-wrap-' + cat.id"
-          >
-            <text
-              class="bouquet-cate-name"
-              :class="{ 'bouquet-cate-name--fill': bouquetNameFillMap[cat.id] }"
-              :id="'bouquet-name-' + cat.id"
-            >{{ cat.categoryName }}</text>
-          </view>
+          <text class="bouquet-cate-name">{{ cat.categoryName }}</text>
         </view>
 
         <!-- 花材置底(默认收起) -->
@@ -411,8 +396,6 @@ export default {
       },
       itemExpanded: false,
       bouquetCategories: [],
-      /** 花束分类名是否占满行:true 居中,false 靠左 */
-      bouquetNameFillMap: {},
       itemClassList: [],
       activeNav: { type: '', id: '' },
       noticeList: [],
@@ -613,10 +596,8 @@ export default {
         } else {
           this.bouquetCategories = []
         }
-        this.syncBouquetNameAlign()
       }).catch(() => {
         this.bouquetCategories = []
-        this.bouquetNameFillMap = {}
       })
     },
     /** 花材分类与商品:item/index(与 pages/item/item 同源) */
@@ -721,55 +702,6 @@ export default {
       if (id === undefined || id === null || id === '') return
       this.selectNav('bouquet', id)
     },
-    /** 花束分类名单行高度(px),用于判断是否换行 */
-    getBouquetNameLineHeightPx() {
-      const sys = uni.getSystemInfoSync()
-      return (26 * 1.3 / 750) * sys.windowWidth
-    },
-    /**
-     * 测量花束分类名:占满一行或换行时居中,短文本靠左
-     * 先按靠左渲染,再根据文字区域与容器宽度比较切换样式
-     */
-    syncBouquetNameAlign() {
-      const cats = this.bouquetCategories
-      if (!cats.length) {
-        this.bouquetNameFillMap = {}
-        return
-      }
-      this.bouquetNameFillMap = {}
-      this.$nextTick(() => {
-        const query = uni.createSelectorQuery().in(this)
-        cats.forEach((cat) => {
-          query.select(`#bouquet-name-wrap-${cat.id}`).boundingClientRect()
-          query.select(`#bouquet-name-${cat.id}`).boundingClientRect()
-        })
-        query.exec((res) => {
-          if (!res || !res.length) return
-          const map = {}
-          const lineH = this.getBouquetNameLineHeightPx()
-          cats.forEach((cat, index) => {
-            const wrap = res[index * 2]
-            const text = res[index * 2 + 1]
-            if (!wrap || !text || !wrap.width) {
-              map[cat.id] = false
-              return
-            }
-            const fillsWidth = text.width >= wrap.width - 4
-            const isMultiLine = text.height > lineH * 1.35
-            map[cat.id] = fillsWidth || isMultiLine
-          })
-          this.bouquetNameFillMap = map
-        })
-      })
-    },
-    /** 花束分类图标地址 */
-    getBouquetIcon(cat) {
-      const img = cat.img || cat.cover || cat.smallCover || ''
-      if (!img) return ''
-      if (img.indexOf('http') === 0) return img
-      const base = (this.constant.imgUrl || '').replace(/\/$/, '')
-      return `${base}/${String(img).replace(/^\//, '')}`
-    },
     selectNav(type, id) {
       if (this.activeNav.type === type && String(this.activeNav.id) === String(id)) {
         return
@@ -1338,56 +1270,36 @@ export default {
   background: #fff;
 }
 
-/* 花束分类项(category/list 平铺) */
+/* 花束分类项:无图标,名称水平+垂直居中 */
 .nav-item {
   display: flex;
   flex-direction: row;
   align-items: center;
+  justify-content: center;
   min-height: 96upx;
-  padding: 16upx 12upx 16upx 14upx;
+  padding: 16upx 12upx;
   font-size: 26upx;
   color: #333;
+  box-sizing: border-box;
 }
 
 .nav-item--bouquet {
   flex-direction: row;
-  justify-content: flex-start;
+  justify-content: center;
   align-items: center;
-  padding: 16upx 8upx 16upx 14upx;
+  padding: 16upx 12upx;
   background: #fff;
   border-top: 1upx solid #f5f5f5;
   border-right: 1upx solid #f5f5f5;
 }
 
-.bouquet-cate-icon {
-  width: 44upx;
-  height: 44upx;
-  border-radius: 8upx;
-  flex-shrink: 0;
-}
-
-.bouquet-cate-name-wrap {
-  flex: 1;
-  width: 0;
-  min-width: 0;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-}
-
 .bouquet-cate-name {
+  width: 100%;
   max-width: 100%;
   font-size: 26upx;
   line-height: 1.3;
-  text-align: left;
-  word-break: break-all;
-}
-
-/* 占满一行或换行时:名称区域拉满并居中 */
-.bouquet-cate-name--fill {
-  width: 100%;
   text-align: center;
+  word-break: break-all;
   overflow: hidden;
   text-overflow: ellipsis;
   display: -webkit-box;

+ 1 - 1
mallApp/src/pages/login/index.vue

@@ -339,7 +339,7 @@ export default {
   padding: 10upx 20upx;
   
   &.reject {
-    color: #999999;
+    color: #346efd;
   }
   
   &.account {