|
|
@@ -0,0 +1,399 @@
|
|
|
+<template>
|
|
|
+ <view class="container">
|
|
|
+ <!-- 搜索栏 -->
|
|
|
+ <view class="search-bar">
|
|
|
+<!-- <up-search placeholder="搜索商品名称" shape="square" :clearabled="true"-->
|
|
|
+<!-- height="36" bgColor="#F9F7F0" :showAction="false" v-model="searchVal"-->
|
|
|
+<!-- @clear="onClear" @search="onSearch"-->
|
|
|
+<!-- :focus="isFocus" @focus="onFocus" @blur="onBlur" ></up-search>-->
|
|
|
+ <view class="search-bar-con">
|
|
|
+ <view class="search-input-wrapper">
|
|
|
+ <uni-icons class="search-icon" type="search" size="18" color="#999"></uni-icons>
|
|
|
+ <input
|
|
|
+ class="search-input"
|
|
|
+ v-model="searchVal"
|
|
|
+ placeholder="请输入搜索内容"
|
|
|
+ placeholder-class="placeholder"
|
|
|
+ @input="onSearch"
|
|
|
+ @confirm="onSearch"
|
|
|
+ :focus="isFocus"
|
|
|
+ />
|
|
|
+ <view v-if="searchVal" class="clear-btn" @click="onClear">
|
|
|
+ <uni-icons type="clear" size="18" color="#999"></uni-icons>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+
|
|
|
+ <!-- 商品列表 -->
|
|
|
+ <view class="product-list">
|
|
|
+ <view class="product-card" v-for="(item, index) in goodsList" :key="index">
|
|
|
+ <view class="product-header">
|
|
|
+ <image class="product-image" :src="item.image" mode="aspectFit" />
|
|
|
+ <view class="product-info">
|
|
|
+ <view class="nameweight">
|
|
|
+ <text class="product-name">{{ item.storeName }}</text>
|
|
|
+ <text class="product-weight">{{ item.weight }}g</text>
|
|
|
+ </view>
|
|
|
+ <view class="nameweight">
|
|
|
+ <view class="price-info">
|
|
|
+ <text class="label">工费</text>
|
|
|
+ <view class="value"><text class="unit">¥</text>{{ item.totalLaborCost }}<text class="unit">/g</text></view>
|
|
|
+ </view>
|
|
|
+ <view class="price-info">
|
|
|
+ <text class="label">附加费</text>
|
|
|
+ <view class="value"><text class="unit">¥</text>{{ item.additionalAmount }}</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="product-stats">
|
|
|
+ <text class="stat">销量:{{ Number(item.sales || 0) + Number(item.ficti || 0) }}</text>
|
|
|
+ <text class="stat">库存:{{ item.stock }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="action-buttons">
|
|
|
+ <button class="btn btn-offline" v-show="params.isShow==1" @click="OffShellFn(item,index)">下架</button>
|
|
|
+ <button class="btn btn-offline" v-show="params.isShow==0" @click="PutOnShellFn(item,index)">上架</button>
|
|
|
+ <button class="btn btn-edit" @click="toEditProduct(item)">编辑</button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="loadingicon acea-row row-center-wrapper" v-if="goodScroll">
|
|
|
+ <text
|
|
|
+ class="loading iconfont icon-jiazai"
|
|
|
+ :hidden="loading == false"
|
|
|
+ ></text>
|
|
|
+ </view>
|
|
|
+ <view class="no-data" v-if="isNoDataState">
|
|
|
+ <image
|
|
|
+ src="https://my-go-easy-im.oss-cn-shenzhen.aliyuncs.com/goeasy-im-%E6%B0%B4%E8%B4%9D%E5%95%86%E5%9F%8E/zhanwu_20250827104005_1720_6.png"
|
|
|
+ />
|
|
|
+ </view>
|
|
|
+ <view class="mores-txt flex" v-if="!goodScroll && !isNoDataState">
|
|
|
+ <text>我是有底线的</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import {computed, ref} from 'vue'
|
|
|
+import { onLoad, onShow, onReachBottom } from "@dcloudio/uni-app";
|
|
|
+import { productsList,productPutOnShell,productOffShell } from "@/api/merchant.js";
|
|
|
+import { useAppStore } from "@/stores/app";
|
|
|
+
|
|
|
+const appStore = useAppStore();
|
|
|
+
|
|
|
+const tabList = ref([
|
|
|
+ {name:'销售中',code:1},
|
|
|
+ {name:'已下架',code:0}
|
|
|
+])
|
|
|
+const searchVal = ref('')
|
|
|
+const goodsList = ref([]);
|
|
|
+const goodType = ref(1);
|
|
|
+// Pagination
|
|
|
+const params = ref({
|
|
|
+ page: 1,
|
|
|
+ limit: 10,
|
|
|
+ isShow:1,
|
|
|
+});
|
|
|
+const loading = ref(false);
|
|
|
+const goodScroll = ref(true);
|
|
|
+const merchantInfo = ref({})
|
|
|
+
|
|
|
+const isFocus = ref(false)
|
|
|
+
|
|
|
+const isNoDataState = computed(() => {
|
|
|
+ return goodsList.value.length === 0 && !loading.value;
|
|
|
+});
|
|
|
+
|
|
|
+
|
|
|
+onShow(() => {
|
|
|
+ merchantInfo.value = appStore.userInfo.merchant;
|
|
|
+ getGroomList()
|
|
|
+})
|
|
|
+
|
|
|
+const onFocus = () => {
|
|
|
+ console.log('获取焦点')
|
|
|
+ isFocus.value = true
|
|
|
+}
|
|
|
+
|
|
|
+const onBlur = () => {
|
|
|
+ console.log('失去焦点')
|
|
|
+ // 不要立即设置为false,避免焦点闪烁
|
|
|
+ setTimeout(() => {
|
|
|
+ isFocus.value = false
|
|
|
+ }, 200)
|
|
|
+}
|
|
|
+const tabChange = (item) => {
|
|
|
+ console.log('item',item)
|
|
|
+ goodsList.value = [];
|
|
|
+ loading.value = false;
|
|
|
+ goodScroll.value = true;
|
|
|
+ params.value.isShow = item.code;
|
|
|
+ params.value.page = 1;
|
|
|
+ getGroomList();
|
|
|
+}
|
|
|
+const onSearch = () => {
|
|
|
+ goodsList.value = [];
|
|
|
+ loading.value = false;
|
|
|
+ goodScroll.value = true;
|
|
|
+ params.value.page = 1;
|
|
|
+ getGroomList();
|
|
|
+}
|
|
|
+// 清除搜索内容
|
|
|
+const onClear = () => {
|
|
|
+ console.log('清除搜索内容');
|
|
|
+ searchVal.value = ''; // 手动清空关键词
|
|
|
+ // 如果需要清除后立即刷新列表,可以调用搜索
|
|
|
+ onSearch();
|
|
|
+}
|
|
|
+const getGroomList = async () => {
|
|
|
+ if (!goodScroll.value) return;
|
|
|
+ try {
|
|
|
+ loading.value = true;
|
|
|
+ params.value.merchantId = merchantInfo.value.id;
|
|
|
+ params.value.keyword = searchVal.value;
|
|
|
+ const { data } = await productsList(params.value);
|
|
|
+ goodsList.value = [...goodsList.value, ...data.list] || [];
|
|
|
+ goodScroll.value = data.list.length >= params.value.limit;
|
|
|
+ params.value.page++;
|
|
|
+ } catch (err) {
|
|
|
+ console.error(err);
|
|
|
+ } finally {
|
|
|
+ loading.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+async function OffShellFn(obj,index) {
|
|
|
+ const {code} = await productOffShell(obj.id);
|
|
|
+ if(code == 200){
|
|
|
+ uni.showToast({ title: "操作成功", icon: "none" });
|
|
|
+ goodsList.value.splice(index,1);
|
|
|
+ }
|
|
|
+}
|
|
|
+async function PutOnShellFn(obj,index) {
|
|
|
+ const {code} = await productPutOnShell(obj.id);
|
|
|
+ if(code == 200){
|
|
|
+ uni.showToast({ title: "操作成功", icon: "none" });
|
|
|
+ goodsList.value.splice(index,1);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+function toEditProduct (obj){
|
|
|
+ uni.navigateTo({
|
|
|
+ url:`pages/merchantCenter/releaseProduct?id=${obj.id}`
|
|
|
+ })
|
|
|
+}
|
|
|
+onReachBottom(() => {
|
|
|
+ getGroomList();
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+
|
|
|
+/* 搜索栏样式 */
|
|
|
+.search-bar {
|
|
|
+ background: #fff;
|
|
|
+ padding: 30rpx 30rpx 0;
|
|
|
+}
|
|
|
+
|
|
|
+.search-input {
|
|
|
+ width: 100%;
|
|
|
+ height: 60rpx;
|
|
|
+ font-size: 28rpx;
|
|
|
+}
|
|
|
+
|
|
|
+/* 标签页样式 */
|
|
|
+.tabs {
|
|
|
+ display: flex;
|
|
|
+ background: white;
|
|
|
+ border-radius: 10rpx;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.tab {
|
|
|
+ flex: 1;
|
|
|
+ text-align: center;
|
|
|
+ padding: 20rpx;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+
|
|
|
+.tab.active {
|
|
|
+ color: #333;
|
|
|
+ font-weight: bold;
|
|
|
+ border-bottom: 4rpx solid #333;
|
|
|
+}
|
|
|
+.product-list{
|
|
|
+ padding: 30rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+/* 商品卡片样式 */
|
|
|
+.product-card {
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 16rpx;
|
|
|
+ padding: 30rpx;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.product-header {
|
|
|
+ display: flex;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.product-image {
|
|
|
+ width: 120rpx;
|
|
|
+ height: 120rpx;
|
|
|
+ border-radius: 10rpx;
|
|
|
+ margin-right: 20rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.product-info {
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.nameweight{
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+}
|
|
|
+.product-name {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #333;
|
|
|
+ display: block;
|
|
|
+}
|
|
|
+.product-weight {
|
|
|
+ background-color: rgba(197, 128, 3, 0.10);
|
|
|
+ color: #C58003;
|
|
|
+ font-size: 24rpx;
|
|
|
+ padding: 8rpx 16rpx;
|
|
|
+ border-radius: 8rpx;
|
|
|
+ float: right;
|
|
|
+}
|
|
|
+
|
|
|
+.price-info {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ margin-bottom: 8rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.label {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #666666;
|
|
|
+}
|
|
|
+
|
|
|
+.value {
|
|
|
+ color: #FD5F3C;
|
|
|
+ font-size: 32rpx;
|
|
|
+ .unit{
|
|
|
+ font-size: 24rpx;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 销售数据样式 */
|
|
|
+.product-stats {
|
|
|
+ display: flex;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+ gap: 10rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.stat {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #666;
|
|
|
+ padding: 10rpx;
|
|
|
+ background-color: #F5F7FA;
|
|
|
+ border-radius: 8rpx;
|
|
|
+}
|
|
|
+
|
|
|
+/* 操作按钮样式 */
|
|
|
+.action-buttons {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ gap: 30rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.btn {
|
|
|
+ flex: 1;
|
|
|
+ height: 60rpx;
|
|
|
+ line-height: 60rpx;
|
|
|
+ border-radius: 8rpx;
|
|
|
+ font-size: 28rpx;
|
|
|
+ border: none;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+.btn-offline {
|
|
|
+ background: #F5F7FA;
|
|
|
+ color: #333;
|
|
|
+}
|
|
|
+
|
|
|
+.btn-edit {
|
|
|
+ background: #F8C008;
|
|
|
+ color: #333;
|
|
|
+}
|
|
|
+.no-data {
|
|
|
+ margin: 150rpx auto 0;
|
|
|
+ text-align: center;
|
|
|
+
|
|
|
+ img {
|
|
|
+ width: 65%;
|
|
|
+ height: auto;
|
|
|
+ }
|
|
|
+}
|
|
|
+.mores-txt {
|
|
|
+ width: 100%;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ height: 70rpx;
|
|
|
+ color: #999;
|
|
|
+ font-size: 24rpx;
|
|
|
+
|
|
|
+ .iconfont {
|
|
|
+ margin-top: 2rpx;
|
|
|
+ font-size: 20rpx;
|
|
|
+ }
|
|
|
+}
|
|
|
+.search-bar-con {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ background-color: #fff;
|
|
|
+ border-bottom: 1rpx solid #eee;
|
|
|
+}
|
|
|
+
|
|
|
+.search-input-wrapper {
|
|
|
+ flex: 1;
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ background-color: #F9F7F0;
|
|
|
+ border-radius: 16rpx;
|
|
|
+ height: 72rpx;
|
|
|
+ line-height: 72rpx;
|
|
|
+ padding: 0 20rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+
|
|
|
+.search-icon {
|
|
|
+ margin-right: 20rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.search-input {
|
|
|
+ flex: 1;
|
|
|
+ height: 100%;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #333;
|
|
|
+}
|
|
|
+
|
|
|
+.placeholder {
|
|
|
+ color: #999;
|
|
|
+ font-size: 28rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.clear-btn {
|
|
|
+ padding: 10rpx;
|
|
|
+ margin-left: 10rpx;
|
|
|
+}
|
|
|
+
|
|
|
+</style>
|