|
|
@@ -1,56 +1,116 @@
|
|
|
<template>
|
|
|
<view class="page">
|
|
|
- <u-navbar title="餐盒设置" :autoBack="true" :placeholder="true"></u-navbar>
|
|
|
- <view class="list">
|
|
|
- <view class="card" v-for="item in list" :key="item.id">
|
|
|
- <image class="img" :src="item.image" mode="aspectFill"></image>
|
|
|
- <view class="info">
|
|
|
- <view class="name">{{ item.name }}</view>
|
|
|
- <view class="meta">价格:¥{{ item.price }}</view>
|
|
|
- <view class="meta link" @click="goBind(item)">绑定商品:{{ item.bindCount }}个 ></view>
|
|
|
- </view>
|
|
|
- <view class="ops">
|
|
|
- <text @click="goEdit(item)">编辑</text>
|
|
|
- <text class="danger" @click="onDelete(item)">删除</text>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- <u-empty v-if="!loading && !list.length" text="暂无餐盒" mode="list"></u-empty>
|
|
|
+ <u-navbar title="餐盒设置" :autoBack="true" :placeholder="true" :border-bottom="true"></u-navbar>
|
|
|
+
|
|
|
+ <view class="list-wrap" :style="{ paddingBottom: listCount ? '160rpx' : '0' }">
|
|
|
+ <ListScrollView
|
|
|
+ ref="listScroll"
|
|
|
+ :api="api"
|
|
|
+ :init="initParams"
|
|
|
+ :pageSize="50"
|
|
|
+ emptyText="暂无内容~"
|
|
|
+ emptyBtnText="去新建餐盒"
|
|
|
+ @afterFetch="afterFetch"
|
|
|
+ @emptyclick="goEdit()"
|
|
|
+ >
|
|
|
+ <template v-slot:list="{ data }">
|
|
|
+ <view class="spec-block" v-for="(item, index) in data" :key="item.id">
|
|
|
+ <view class="spec-head">
|
|
|
+ <text class="spec-title">规格{{ index + 1 }}</text>
|
|
|
+ <view class="spec-ops">
|
|
|
+ <view class="op" @click="goEdit(item)">
|
|
|
+ <u-icon name="edit-pen" color="#449AFF" size="28"></u-icon>
|
|
|
+ <text>编辑</text>
|
|
|
+ </view>
|
|
|
+ <view class="op" @click="onDelete(item)">
|
|
|
+ <u-icon name="trash" color="#449AFF" size="28"></u-icon>
|
|
|
+ <text>删除</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="spec-body">
|
|
|
+ <view class="row">
|
|
|
+ <text class="label">餐盒名称</text>
|
|
|
+ <text class="value">{{ item.name || '-' }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="row">
|
|
|
+ <text class="label">餐盒价格</text>
|
|
|
+ <text class="value">{{ item.price != null ? item.price : 0 }} 元</text>
|
|
|
+ </view>
|
|
|
+ <view class="row link" @click="goBind(item)">
|
|
|
+ <text class="label">已绑商品</text>
|
|
|
+ <view class="value-wrap">
|
|
|
+ <text class="value">{{ item.bindCount || 0 }}个</text>
|
|
|
+ <u-icon name="arrow-right" color="#C7C6CA" size="24"></u-icon>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="row last">
|
|
|
+ <text class="label">餐盒图片</text>
|
|
|
+ <image v-if="item.image" class="thumb" :src="item.image" mode="aspectFill"></image>
|
|
|
+ <text v-else class="value muted">暂无图片</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+ </ListScrollView>
|
|
|
</view>
|
|
|
- <view class="footer">
|
|
|
- <u-button type="primary" shape="circle" @click="goEdit()">新增餐盒</u-button>
|
|
|
+
|
|
|
+ <view class="footer" v-if="listCount">
|
|
|
+ <view class="primary-btn" @click="goEdit()">新建餐盒</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import merchantDishApi, { mapMealBoxItem } from '@/api/merchantDish.js';
|
|
|
+import ListScrollView from '@/components/list-scroll-view/index.vue';
|
|
|
+import merchantDishApi, { mapMealBoxItem, getMerchantId } from '@/api/merchantDish.js';
|
|
|
|
|
|
export default {
|
|
|
+ components: {
|
|
|
+ ListScrollView
|
|
|
+ },
|
|
|
data() {
|
|
|
return {
|
|
|
- list: [],
|
|
|
- loading: false
|
|
|
+ api: {
|
|
|
+ url: '/groupmeal/gmMerchantMealBox/list',
|
|
|
+ method: 'GET'
|
|
|
+ },
|
|
|
+ listCount: 0,
|
|
|
+ listReady: false
|
|
|
};
|
|
|
},
|
|
|
+ computed: {
|
|
|
+ initParams() {
|
|
|
+ return {
|
|
|
+ merchantId: getMerchantId()
|
|
|
+ };
|
|
|
+ }
|
|
|
+ },
|
|
|
onShow() {
|
|
|
- this.fetchList();
|
|
|
+ if (this.listReady) {
|
|
|
+ this.reloadList();
|
|
|
+ } else {
|
|
|
+ this.listReady = true;
|
|
|
+ }
|
|
|
},
|
|
|
methods: {
|
|
|
- fetchList() {
|
|
|
- this.loading = true;
|
|
|
- merchantDishApi
|
|
|
- .mealBoxList({ pageNo: 1, pageSize: 100 })
|
|
|
- .then((res) => {
|
|
|
- if (res.data.code === 200) {
|
|
|
- const page = res.data.result || {};
|
|
|
- this.list = (page.records || []).map(mapMealBoxItem);
|
|
|
- } else {
|
|
|
- this.$tip.toast(res.data.message || '加载失败');
|
|
|
- }
|
|
|
- })
|
|
|
- .finally(() => {
|
|
|
- this.loading = false;
|
|
|
- });
|
|
|
+ afterFetch(result) {
|
|
|
+ const records = Array.isArray(result.records) ? result.records : [];
|
|
|
+ records.forEach((item) => {
|
|
|
+ Object.assign(item, mapMealBoxItem(item));
|
|
|
+ });
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const scroll = this.$refs.listScroll;
|
|
|
+ this.listCount = (scroll && scroll.dataList && scroll.dataList.length) || 0;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ reloadList() {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const scroll = this.$refs.listScroll;
|
|
|
+ if (scroll && scroll.mescroll) {
|
|
|
+ scroll.reloadList(this.initParams);
|
|
|
+ }
|
|
|
+ });
|
|
|
},
|
|
|
goEdit(item) {
|
|
|
const q = item ? `?id=${item.id}` : '';
|
|
|
@@ -67,7 +127,7 @@ export default {
|
|
|
if (!res.confirm) return;
|
|
|
merchantDishApi.mealBoxDelete(item.id).then((r) => {
|
|
|
this.$tip.toast(r.data.message || (r.data.code === 200 ? '删除成功' : '删除失败'));
|
|
|
- if (r.data.code === 200) this.fetchList();
|
|
|
+ if (r.data.code === 200) this.reloadList();
|
|
|
});
|
|
|
}
|
|
|
});
|
|
|
@@ -78,59 +138,121 @@ export default {
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
.page {
|
|
|
- min-height: 100vh;
|
|
|
- background: #f7f8fc;
|
|
|
- padding-bottom: 160rpx;
|
|
|
+ height: 100vh;
|
|
|
+ background: #f7f8fa;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
}
|
|
|
-.list {
|
|
|
- padding: 24rpx;
|
|
|
+.list-wrap {
|
|
|
+ flex: 1;
|
|
|
+ height: 0;
|
|
|
+ box-sizing: border-box;
|
|
|
}
|
|
|
-.card {
|
|
|
- display: flex;
|
|
|
- background: #fff;
|
|
|
- border-radius: 16rpx;
|
|
|
- padding: 20rpx;
|
|
|
+.spec-block {
|
|
|
margin-bottom: 16rpx;
|
|
|
- .img {
|
|
|
- width: 120rpx;
|
|
|
- height: 120rpx;
|
|
|
- border-radius: 12rpx;
|
|
|
- background: #eee;
|
|
|
+}
|
|
|
+.spec-head {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 20rpx 24rpx;
|
|
|
+ background: #eef3f8;
|
|
|
+ .spec-title {
|
|
|
+ font-size: 30rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #333;
|
|
|
}
|
|
|
- .info {
|
|
|
- flex: 1;
|
|
|
- margin-left: 16rpx;
|
|
|
- .name {
|
|
|
- font-size: 30rpx;
|
|
|
- font-weight: 500;
|
|
|
+ .spec-ops {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ .op {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-left: 28rpx;
|
|
|
+ font-size: 26rpx;
|
|
|
+ color: #449aff;
|
|
|
+ text {
|
|
|
+ margin-left: 6rpx;
|
|
|
+ }
|
|
|
}
|
|
|
- .meta {
|
|
|
- font-size: 24rpx;
|
|
|
+ }
|
|
|
+}
|
|
|
+.spec-body {
|
|
|
+ background: #fff;
|
|
|
+}
|
|
|
+.row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ min-height: 96rpx;
|
|
|
+ padding: 0 24rpx;
|
|
|
+ border-bottom: 1rpx solid #f0f0f0;
|
|
|
+ &.last {
|
|
|
+ border-bottom: none;
|
|
|
+ }
|
|
|
+ &.link:active {
|
|
|
+ background: #fafafa;
|
|
|
+ }
|
|
|
+ .label {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #333;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+ .value {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #333;
|
|
|
+ text-align: right;
|
|
|
+ &.muted {
|
|
|
color: #999;
|
|
|
- margin-top: 8rpx;
|
|
|
- &.link {
|
|
|
- color: #449aff;
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
- .ops {
|
|
|
+ .value-wrap {
|
|
|
display: flex;
|
|
|
- flex-direction: column;
|
|
|
- justify-content: center;
|
|
|
- gap: 16rpx;
|
|
|
- font-size: 26rpx;
|
|
|
- color: #449aff;
|
|
|
- .danger {
|
|
|
- color: #ff4d4f;
|
|
|
+ align-items: center;
|
|
|
+ .value {
|
|
|
+ margin-right: 4rpx;
|
|
|
}
|
|
|
}
|
|
|
+ .thumb {
|
|
|
+ width: 72rpx;
|
|
|
+ height: 72rpx;
|
|
|
+ border-radius: 8rpx;
|
|
|
+ background: #eee;
|
|
|
+ }
|
|
|
}
|
|
|
.footer {
|
|
|
position: fixed;
|
|
|
left: 0;
|
|
|
right: 0;
|
|
|
bottom: 0;
|
|
|
+ z-index: 20;
|
|
|
padding: 20rpx 40rpx calc(20rpx + env(safe-area-inset-bottom));
|
|
|
background: #fff;
|
|
|
}
|
|
|
+.primary-btn {
|
|
|
+ height: 88rpx;
|
|
|
+ line-height: 88rpx;
|
|
|
+ text-align: center;
|
|
|
+ color: #fff;
|
|
|
+ font-size: 32rpx;
|
|
|
+ border-radius: 44rpx;
|
|
|
+ background: linear-gradient(90deg, #77b6ff 0%, #449aff 100%);
|
|
|
+}
|
|
|
+
|
|
|
+/* 空态按钮对齐设计:蓝描边胶囊 */
|
|
|
+::v-deep .mescroll-empty .empty-tip {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #999;
|
|
|
+ margin-top: 0;
|
|
|
+}
|
|
|
+::v-deep .mescroll-empty .empty-btn {
|
|
|
+ margin-top: 40rpx;
|
|
|
+ min-width: 260rpx;
|
|
|
+ padding: 16rpx 40rpx;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #449aff;
|
|
|
+ border: 2rpx solid #449aff;
|
|
|
+ border-radius: 36rpx;
|
|
|
+ background: #fff;
|
|
|
+}
|
|
|
</style>
|