|
|
@@ -1,10 +1,10 @@
|
|
|
<!--
|
|
|
商品分类列表页(新版)
|
|
|
- 用途:花束/花材分类列表展示;花束编辑跳转 category-edit,花材在本页弹窗编辑;分类广告见独立页 category-ad
|
|
|
+ 用途:花束/花材分类列表 + 分类广告三表编辑;花束编辑跳转 category-edit,花材在本页弹窗编辑;分类广告用组件不跳新页
|
|
|
-->
|
|
|
<template>
|
|
|
<view class="page-container">
|
|
|
- <!-- Tabs:花束 / 花材;分类广告已独立为 category-ad 页 -->
|
|
|
+ <!-- Tabs:花束 / 花材 / 分类广告(广告在本页组件内编辑) -->
|
|
|
<view class="tabs">
|
|
|
<view class="tab-item" :class="{active: currentTab === 0}" @click="switchTab(0)">
|
|
|
<text>花束分类</text>
|
|
|
@@ -14,10 +14,18 @@
|
|
|
<text>花材分类</text>
|
|
|
<view class="tab-line" v-if="currentTab === 1"></view>
|
|
|
</view>
|
|
|
+ <view class="tab-item" :class="{active: currentTab === 2}" @click="switchTab(2)">
|
|
|
+ <text>分类广告</text>
|
|
|
+ <view class="tab-line" v-if="currentTab === 2"></view>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
|
|
|
+ <!-- 分类广告:3 个广告位表格,组件内完成设置 -->
|
|
|
+ <category-ad-setting v-if="currentTab === 2" ref="categoryAdSetting" />
|
|
|
+
|
|
|
<!-- 列表头部 -->
|
|
|
<view
|
|
|
+ v-if="currentTab !== 2"
|
|
|
class="list-header"
|
|
|
:class="{ 'layout-item-class': currentTab === 1 }"
|
|
|
>
|
|
|
@@ -29,6 +37,7 @@
|
|
|
|
|
|
<!-- 分类列表:不用 scroll-view,避免小程序内点击事件被拦截 -->
|
|
|
<view
|
|
|
+ v-if="currentTab !== 2"
|
|
|
class="list-container"
|
|
|
:class="{ 'layout-item-class': currentTab === 1 }"
|
|
|
>
|
|
|
@@ -36,11 +45,17 @@
|
|
|
<view
|
|
|
class="list-item"
|
|
|
:class="{'is-disabled': item.status != 1}"
|
|
|
- v-for="(item, index) in filteredList"
|
|
|
- :key="item.id || index"
|
|
|
+ v-for="item in filteredList"
|
|
|
+ :key="item.listKey"
|
|
|
>
|
|
|
<view class="col-name item-name">
|
|
|
- <image :src="item.img" mode="aspectFit" class="cat-img"></image>
|
|
|
+ <!-- 花束分类名称只展示文字,去掉封面图标,避免挤占操作列 -->
|
|
|
+ <image
|
|
|
+ v-if="currentTab === 1 && item.img"
|
|
|
+ :src="item.img"
|
|
|
+ mode="aspectFit"
|
|
|
+ class="cat-img"
|
|
|
+ ></image>
|
|
|
<text class="cat-text">{{ item.categoryName }}</text>
|
|
|
</view>
|
|
|
|
|
|
@@ -55,10 +70,8 @@
|
|
|
:data-pic-text-id="item.picTextId"
|
|
|
@click.stop="selectPicText"
|
|
|
>
|
|
|
+ <!-- 图文列只保留文字状态,去掉图标,整块可点 -->
|
|
|
<view class="pic-tag" :class="item.picTextId > 0 ? 'is-set' : 'no-set'">
|
|
|
- <view class="pic-icon-box">
|
|
|
- <view class="pic-icon-inner"></view>
|
|
|
- </view>
|
|
|
<text>{{ item.picTextId > 0 ? '已设置' : '未设置' }}</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
@@ -75,8 +88,8 @@
|
|
|
</block>
|
|
|
</view>
|
|
|
|
|
|
- <!-- 底部操作栏 -->
|
|
|
- <view class="bottom-toolbar">
|
|
|
+ <!-- 底部操作栏:分类广告 Tab 用组件自己的预览/保存栏 -->
|
|
|
+ <view class="bottom-toolbar" v-if="currentTab !== 2">
|
|
|
<button
|
|
|
class="toolbar-btn outline-btn"
|
|
|
hover-class="none"
|
|
|
@@ -229,6 +242,7 @@
|
|
|
<script>
|
|
|
import AppWrapperEmpty from '@/components/app-wrapper-empty';
|
|
|
import htzImageUpload from '@/components/htz-image-upload/htz-image-upload.vue';
|
|
|
+import CategoryAdSetting from '@/admin/goods/components/category-ad-setting.vue';
|
|
|
import { mapGetters } from 'vuex';
|
|
|
import { categoryListInfo, categoryDelB } from '@/api/goods';
|
|
|
import { getAllItemClass, delClass, addClass, updateClass } from '@/api/item-class';
|
|
|
@@ -238,7 +252,8 @@ export default {
|
|
|
name: 'categoryV2',
|
|
|
components: {
|
|
|
AppWrapperEmpty,
|
|
|
- htzImageUpload
|
|
|
+ htzImageUpload,
|
|
|
+ CategoryAdSetting
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
@@ -278,10 +293,14 @@ export default {
|
|
|
},
|
|
|
/** 当前 Tab 对应分类列表,字段统一后供模板渲染 */
|
|
|
filteredList() {
|
|
|
- const source = this.currentTab === 1 ? this.itemClassList : this.bouquetList;
|
|
|
- const list = (source || []).map((item) => (
|
|
|
- this.currentTab === 1 ? this.normalizeItemClassRow(item) : this.normalizeBouquetRow(item)
|
|
|
- ));
|
|
|
+ const tab = this.currentTab;
|
|
|
+ const source = tab === 1 ? this.itemClassList : this.bouquetList;
|
|
|
+ const list = (source || []).map((item, index) => {
|
|
|
+ const row = tab === 1 ? this.normalizeItemClassRow(item) : this.normalizeBouquetRow(item);
|
|
|
+ // 小程序 wx:key 只能绑 item 上的字段,表达式 item.id || index 编不出 wx:key
|
|
|
+ row.listKey = `${tab}-${row.id || index}`;
|
|
|
+ return row;
|
|
|
+ });
|
|
|
return list.slice().sort((a, b) => {
|
|
|
const aDisabled = a.status == 1 ? 0 : 1;
|
|
|
const bDisabled = b.status == 1 ? 0 : 1;
|
|
|
@@ -304,13 +323,9 @@ export default {
|
|
|
},
|
|
|
onLoad(options) {
|
|
|
if (options && options.tab !== undefined) {
|
|
|
- // 仅保留花束(0)/花材(1);旧链 tab=2(分类广告)改走独立页
|
|
|
- const tab = parseInt(options.tab) || 0;
|
|
|
- this.currentTab = tab === 1 ? 1 : 0;
|
|
|
- if (parseInt(options.tab) === 2) {
|
|
|
- uni.redirectTo({ url: '/admin/goods/category-ad' });
|
|
|
- return;
|
|
|
- }
|
|
|
+ // 0花束 1花材 2分类广告;广告在本页组件编辑,不再跳独立页
|
|
|
+ const tab = parseInt(options.tab, 10) || 0;
|
|
|
+ this.currentTab = tab === 1 || tab === 2 ? tab : 0;
|
|
|
}
|
|
|
this.uploadHeaders.token = uni.getStorageSync('token') || '';
|
|
|
this.init();
|
|
|
@@ -324,13 +339,24 @@ export default {
|
|
|
init() {
|
|
|
this.loadCurrentTabList();
|
|
|
},
|
|
|
- /** 按当前 Tab 拉取对应表数据 */
|
|
|
+ /** 按当前 Tab 拉取对应表数据;广告 Tab 走组件 reload */
|
|
|
loadCurrentTabList() {
|
|
|
+ if (this.currentTab === 2) {
|
|
|
+ return this.reloadCategoryAd();
|
|
|
+ }
|
|
|
if (this.currentTab === 1) {
|
|
|
return this.loadItemClassList();
|
|
|
}
|
|
|
return this.loadBouquetList();
|
|
|
},
|
|
|
+ /** 下拉刷新时重拉广告;首次切 Tab 时组件尚未挂上,由组件 mounted 自行加载 */
|
|
|
+ reloadCategoryAd() {
|
|
|
+ const panel = this.$refs.categoryAdSetting;
|
|
|
+ if (panel && panel.reload) {
|
|
|
+ return panel.reload();
|
|
|
+ }
|
|
|
+ return Promise.resolve();
|
|
|
+ },
|
|
|
/** 花束分类:xhCategory */
|
|
|
loadBouquetList() {
|
|
|
this.listLoading = true;
|
|
|
@@ -656,19 +682,19 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-.col-name { flex: 3; min-width: 0; text-align: left !important; }
|
|
|
-.col-num { flex: 1.5; flex-shrink: 0; }
|
|
|
-.col-pic { flex: 2; flex-shrink: 0; }
|
|
|
-.col-action { flex: 2; flex-shrink: 0; }
|
|
|
+.col-name { flex: 2.6; min-width: 0; text-align: left !important; }
|
|
|
+.col-num { flex: 1.4; flex-shrink: 0; }
|
|
|
+.col-pic { flex: 1.6; flex-shrink: 0; }
|
|
|
+.col-action { flex: 2.8; flex-shrink: 0; }
|
|
|
|
|
|
-/* 花材分类无商品数量、图文列,加宽名称与操作区 */
|
|
|
+/* 花材分类无商品数量、图文列,加宽名称与操作区便于点按 */
|
|
|
.layout-item-class {
|
|
|
.col-name {
|
|
|
- flex: 4;
|
|
|
+ flex: 3.6;
|
|
|
}
|
|
|
|
|
|
.col-action {
|
|
|
- flex: 2.2;
|
|
|
+ flex: 3;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -714,14 +740,6 @@ export default {
|
|
|
&.no-set,
|
|
|
&.is-set {
|
|
|
color: #d0d0d0;
|
|
|
-
|
|
|
- .pic-icon-box {
|
|
|
- border-color: #ddd;
|
|
|
-
|
|
|
- .pic-icon-inner {
|
|
|
- background: #ddd;
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -771,40 +789,19 @@ export default {
|
|
|
.pic-tag {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
- font-size: 22upx;
|
|
|
- padding: 4upx 10upx;
|
|
|
- border-radius: 6upx;
|
|
|
+ justify-content: center;
|
|
|
+ min-height: 64upx;
|
|
|
+ padding: 8upx 12upx;
|
|
|
+ border-radius: 8upx;
|
|
|
+ font-size: 28upx;
|
|
|
+ font-weight: 600;
|
|
|
|
|
|
&.no-set {
|
|
|
color: #999;
|
|
|
- .pic-icon-box {
|
|
|
- border: 2upx solid #ccc;
|
|
|
- .pic-icon-inner { background: #ccc; }
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
&.is-set {
|
|
|
color: #52c41a;
|
|
|
- .pic-icon-box {
|
|
|
- border: 2upx solid #52c41a;
|
|
|
- .pic-icon-inner { background: #52c41a; }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .pic-icon-box {
|
|
|
- width: 24upx;
|
|
|
- height: 20upx;
|
|
|
- border-radius: 4upx;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- margin-right: 8upx;
|
|
|
-
|
|
|
- .pic-icon-inner {
|
|
|
- width: 12upx;
|
|
|
- height: 10upx;
|
|
|
- clip-path: polygon(0 100%, 40% 40%, 60% 70%, 80% 20%, 100% 100%);
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -813,7 +810,7 @@ export default {
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
|
- font-size: 26upx;
|
|
|
+ font-size: 32upx;
|
|
|
white-space: nowrap;
|
|
|
|
|
|
.action-btn {
|
|
|
@@ -821,16 +818,16 @@ export default {
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
width: auto;
|
|
|
- min-width: 0;
|
|
|
+ min-width: 72upx;
|
|
|
height: auto;
|
|
|
- min-height: 0;
|
|
|
- padding: 0;
|
|
|
+ min-height: 72upx;
|
|
|
+ padding: 12upx 10upx;
|
|
|
margin: 0;
|
|
|
background: transparent;
|
|
|
border: none;
|
|
|
line-height: 1.4;
|
|
|
- font-size: 26upx;
|
|
|
- font-weight: normal;
|
|
|
+ font-size: 32upx;
|
|
|
+ font-weight: 600;
|
|
|
}
|
|
|
|
|
|
.action-btn::after {
|
|
|
@@ -842,7 +839,7 @@ export default {
|
|
|
}
|
|
|
.action-divider {
|
|
|
color: #eee;
|
|
|
- margin: 0 16upx;
|
|
|
+ margin: 0 8upx;
|
|
|
}
|
|
|
.delete-btn {
|
|
|
color: #FF3B30;
|