first commit
This commit is contained in:
305
src/pages/goods-manager/childPages/right-main/right-main.scss
Normal file
305
src/pages/goods-manager/childPages/right-main/right-main.scss
Normal file
@@ -0,0 +1,305 @@
|
||||
.skuName-cell {
|
||||
box-sizing: border-box;
|
||||
background: white;
|
||||
padding: 19rpx;
|
||||
border-radius: 10rpx;
|
||||
margin: 15rpx 15rpx;
|
||||
box-shadow: 0rpx 2rpx 10rpx rgb(207, 207, 207);
|
||||
|
||||
|
||||
.skuName {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
position: relative;
|
||||
|
||||
.skuName-img {
|
||||
position: relative;
|
||||
|
||||
view {
|
||||
position: absolute;
|
||||
z-index: 9;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 182rpx;
|
||||
height: 182rpx;
|
||||
border-radius: 10rpx;
|
||||
background: rgba(0, 0, 0, .4);
|
||||
text-align: center;
|
||||
line-height: 182rpx;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.imglabel {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
border-radius: 10rpx;
|
||||
border: 1rpx solid rgb(218, 218, 218);
|
||||
}
|
||||
}
|
||||
|
||||
.skuName-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
margin-left: 17rpx;
|
||||
width: 100%;
|
||||
height: 180rpx;
|
||||
|
||||
.input-price {
|
||||
position: absolute;
|
||||
border: 1rpx solid rgba(0, 0, 0, 0.1);
|
||||
background: white;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
top: 60rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.skuName-name {
|
||||
color: #333;
|
||||
font-size: 32rpx;
|
||||
line-height: 1;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.skuName-monthsale {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
line-height: 1;
|
||||
margin-top: 7rpx;
|
||||
}
|
||||
|
||||
.skuName-failsync {
|
||||
font-size: 28rpx;
|
||||
color: #F60D58;
|
||||
line-height: 1;
|
||||
margin-top: 7rpx;
|
||||
margin-bottom: -30rpx;
|
||||
}
|
||||
|
||||
.skuName-price {
|
||||
display: flex;
|
||||
color: #F60D58;
|
||||
line-height: 1;
|
||||
|
||||
.icon-modify {
|
||||
margin-left: 15rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.skuName-tips {
|
||||
font-size: 28rpx;
|
||||
line-height: 1;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.red {
|
||||
color: #F60D58;
|
||||
}
|
||||
|
||||
.green {
|
||||
color: $jx-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sku
|
||||
.skus {
|
||||
border-top: 1rpx dashed #ccc;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
// justify-content: flex-end;
|
||||
// padding-top: 16rpx;
|
||||
// overflow: hidden;
|
||||
margin-top: 10rpx;
|
||||
align-items: flex-start;
|
||||
|
||||
.sku-cell:nth-of-type(even) {
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
// 价格审核中样式
|
||||
.check-display {
|
||||
color: #f44;
|
||||
font-size: 24rpx;
|
||||
font-weight: bold;
|
||||
animation: rubberBand 1s infinite alternate;
|
||||
}
|
||||
}
|
||||
|
||||
.skus-wrapper-new {
|
||||
border-top: 1rpx solid rgb(219, 219, 219);
|
||||
|
||||
.error {
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
font-weight: bold;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.mt {
|
||||
color: #f29a40;
|
||||
}
|
||||
|
||||
.eb {
|
||||
color: #51a7fc;
|
||||
}
|
||||
|
||||
.sku-cell2 {
|
||||
padding: 10rpx 0 0 0;
|
||||
border-bottom: 1rpx solid rgb(219, 219, 219);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.isSale2 {}
|
||||
|
||||
.cell-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.price {
|
||||
color: #333;
|
||||
width: 23%;
|
||||
flex-shrink: 0;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-flow: column;
|
||||
|
||||
.sku-spec {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.sku-price {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.promotion-price {
|
||||
color: #F60D58;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
width: 78%;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
|
||||
.btn {
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
border-radius: 10rpx;
|
||||
color: $jx-primary;
|
||||
border: 2rpx solid $jx-primary;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.tmpSaleNo {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 28rpx;
|
||||
line-height: 1.02;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.onActive {
|
||||
background: $jx-primary;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cell-bottom {
|
||||
font-size: 28rpx;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
padding: 5rpx 0;
|
||||
}
|
||||
|
||||
.sku-autoSaleAt {
|
||||
font-size: 26rpx;
|
||||
text-align: center;
|
||||
color: #F25340;
|
||||
padding: 5rpx 0;
|
||||
|
||||
text {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.checkBoxWrap {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: flex-end;
|
||||
padding-top: 15rpx;
|
||||
}
|
||||
|
||||
.aduit-type {
|
||||
font-size: 28rpx;
|
||||
text-align: center;
|
||||
color: $jx-primary;
|
||||
}
|
||||
|
||||
.aduit-btn-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-top: 20rpx;
|
||||
|
||||
.btn {
|
||||
font-size: 28rpx;
|
||||
padding: 20rpx 40rpx;
|
||||
background: $jx-primary;
|
||||
border-radius: 10rpx;
|
||||
color: white;
|
||||
margin: 0 20rpx;
|
||||
}
|
||||
|
||||
.refuse {
|
||||
background: #f44;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rubberBand {
|
||||
from {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
|
||||
30% {
|
||||
transform: scale3d(1.01, 0.75, 1);
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: scale3d(0.95, 1.25, 1);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale3d(1.02, 0.85, 1);
|
||||
}
|
||||
|
||||
65% {
|
||||
transform: scale3d(0.98, 1.05, 1);
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: scale3d(1.01, 0.95, 1);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
177
src/pages/goods-manager/childPages/right-main/right-main.ts
Normal file
177
src/pages/goods-manager/childPages/right-main/right-main.ts
Normal file
@@ -0,0 +1,177 @@
|
||||
import shopping from "@/api/https/shopping"
|
||||
import { store } from "@/store"
|
||||
import { getStorage } from "@/utils/storage"
|
||||
import toast from "@/utils/toast"
|
||||
import { jx_throttles, timeFormatD } from "@/utils/tools"
|
||||
import { computed } from "@vue/reactivity"
|
||||
import configCms from "@/utils/configCms"
|
||||
|
||||
interface propType {
|
||||
skuName: AnyObject
|
||||
isAudit: boolean
|
||||
isHot: boolean
|
||||
showMountTab: boolean
|
||||
}
|
||||
/*************************************************
|
||||
* 商品列表
|
||||
*/
|
||||
function goodsListFn(props: Readonly<propType>) {
|
||||
|
||||
/*************************************************
|
||||
* 列表判断条件
|
||||
*/
|
||||
const isNewPriceDisplay: any = computed(() => {
|
||||
store.getters['storeInfo/isNewPriceDisplay']
|
||||
})
|
||||
|
||||
/*************************************************
|
||||
* 获取userType
|
||||
*/
|
||||
const userType = computed(() => {
|
||||
return +getStorage('userType')
|
||||
})
|
||||
|
||||
/*************************************************
|
||||
* 修改商品售卖状态
|
||||
*/
|
||||
function updateSaleStatus(sku: AnyObject, skuName: AnyObject, status: number) {
|
||||
if (+sku.storeSkuStatus === +status && !sku.autoSaleAt) return false
|
||||
let data = {
|
||||
sku,
|
||||
skuName,
|
||||
status
|
||||
}
|
||||
updateSaleStatusThrottles(data)
|
||||
}
|
||||
const updateSaleStatusThrottles = jx_throttles({
|
||||
time: 500,
|
||||
success: async (e: AnyObject) => {
|
||||
let data = {
|
||||
storeIDs: JSON.stringify([getStorage('storeID')]),
|
||||
payload: JSON.stringify([
|
||||
{
|
||||
nameID: e.skuName.id,
|
||||
skus: [
|
||||
{
|
||||
skuID: e.sku.id,
|
||||
isSale: +e.status === 0 ? -1 : +e.status,
|
||||
},
|
||||
],
|
||||
},
|
||||
]),
|
||||
}
|
||||
let res = await shopping.update_stores_skus(data)
|
||||
if (res.code == 0) {
|
||||
changeSaleStatus(e.sku, e.skuName, e.status)
|
||||
if (e.sku.autoSaleAt) e.sku.autoSaleAt = 0
|
||||
} else {
|
||||
toast('修改失败', 2)
|
||||
}
|
||||
},
|
||||
fail: (t: number) => {
|
||||
toast(`操作太快`)
|
||||
}
|
||||
})
|
||||
|
||||
/*************************************************
|
||||
* 修改商品临时不可售
|
||||
*/
|
||||
function tmpSaleNo(sku: AnyObject, skuName: AnyObject) {
|
||||
if (sku.storeSkuStatus === 0 && sku.autoSaleAt) return false
|
||||
let data = {
|
||||
sku,
|
||||
skuName,
|
||||
}
|
||||
tmpSaleNoThrottles(data)
|
||||
}
|
||||
const tmpSaleNoThrottles = jx_throttles({
|
||||
time: 500,
|
||||
success: async (e: AnyObject) => {
|
||||
let autoSaleAt = computedAutoSaleAt()
|
||||
let data = {
|
||||
storeIDs: JSON.stringify([getStorage('storeID')]),
|
||||
payload: JSON.stringify([{
|
||||
skuID: e.sku.id,
|
||||
isSale: -1,
|
||||
isAsync: false,
|
||||
}]),
|
||||
autoSaleAt: autoSaleAt
|
||||
}
|
||||
let res = await shopping.update_stores_skus_sale(data)
|
||||
|
||||
// let res:AnyObject = {
|
||||
// code: "-105",
|
||||
// desc: "本地数据修改成功,但同步失败,请根据错误提示处理!,同步错误信息:[{\"商品ID\":0,\"分类名\":\"\",\"门店ID\":804947,\"平台名\":\"抖店平台\",\"平台商品ID\":\"\",\"商品nameID\":0,\"平台价\":0,\"同步类型\":\"异常同步错误\",\"错误信息\":\"门店:804947,修改没有创建的商品:22807\"},{\"商品ID\":22807,\"分类名\":\"\",\"门店ID\":804947,\"平台名\":\"京东到家\",\"平台商品ID\":\"2792687352\",\"商品nameID\":8643,\"平台价\":0,\"同步类型\":\"更新商品状态\",\"错误信息\":\"未查询到到家商品编码\"}]",
|
||||
// data: ""
|
||||
// }
|
||||
|
||||
// if (res.code === '0') {
|
||||
// changeSaleStatus(e.sku, e.skuName, 0)
|
||||
// e.sku.autoSaleAt = autoSaleAt
|
||||
// } else {
|
||||
// if(res.code === '-105' && res.desc.includes('本地数据修改成功,但同步失败,请根据错误提示处理')) toast(res.desc)
|
||||
// else toast('修改失败', 2)
|
||||
// }
|
||||
|
||||
if (res.code == 0) {
|
||||
changeSaleStatus(e.sku, e.skuName, 0)
|
||||
e.sku.autoSaleAt = autoSaleAt
|
||||
} else {
|
||||
let findIndex = res.desc.indexOf('[')
|
||||
let str = ''
|
||||
if(findIndex!== -1){
|
||||
JSON.parse(res.desc.substring(findIndex)).forEach((element:AnyObject) => {
|
||||
str = str.length >0 ? str + ';\n' + element['平台名'] + ':【' + element['错误信息'] + '】': str + element['平台名'] +':【' + element['错误信息']+'】'
|
||||
});
|
||||
}
|
||||
if(res.code === '-105' && res.desc.includes('本地数据修改成功,但同步失败,请根据错误提示处理')) toast(`${str}`)
|
||||
else toast('修改失败', 2)
|
||||
}
|
||||
},
|
||||
fail: (t: number) => {
|
||||
toast(`操作太快`)
|
||||
}
|
||||
})
|
||||
|
||||
/*************************************************
|
||||
* 计算自动可售时间
|
||||
*/
|
||||
function computedAutoSaleAt() {
|
||||
let now = +new Date()
|
||||
let autoTime = +new Date(`${timeFormatD(+new Date())} ${autoSaleAt.value}`)
|
||||
if (now < autoTime) {
|
||||
return `${timeFormatD(+new Date())} ${autoSaleAt.value}`
|
||||
} else {
|
||||
return `${timeFormatD(+new Date() + 24 * 3600 * 1000)} ${autoSaleAt.value}`
|
||||
}
|
||||
}
|
||||
|
||||
// 自动可售时间
|
||||
const autoSaleAt = computed(() => {
|
||||
let { autoSaleAt = '' } = configCms.serveInfo
|
||||
return autoSaleAt
|
||||
})
|
||||
|
||||
/*************************************************
|
||||
* 修改商品可售状态
|
||||
*/
|
||||
async function changeSaleStatus(sku: AnyObject, skuName: AnyObject, status: number) {
|
||||
if (props.isAudit) return false
|
||||
sku.storeSkuStatus = +status
|
||||
// 计算可售不可售图标
|
||||
if (skuName.skus.some((item: AnyObject) => item.storeSkuStatus)) {
|
||||
skuName.skuAllnoSale = false
|
||||
} else {
|
||||
skuName.skuAllnoSale = true
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
isNewPriceDisplay, // 列表判断条件
|
||||
userType, // 获取userType
|
||||
updateSaleStatus, // 修改商品售卖状态
|
||||
tmpSaleNo, // 临时不可售
|
||||
}
|
||||
}
|
||||
|
||||
export default goodsListFn
|
||||
263
src/pages/goods-manager/childPages/right-main/right-main.vue
Normal file
263
src/pages/goods-manager/childPages/right-main/right-main.vue
Normal file
@@ -0,0 +1,263 @@
|
||||
<template>
|
||||
<view class="skuName-cell">
|
||||
<!-- skuName -->
|
||||
<view class="skuName">
|
||||
<!-- 图片 -->
|
||||
<view class="skuName-img" @tap="previewImg(skuName)">
|
||||
<view v-show="skuName.skuAllnoSale">不可售</view>
|
||||
<image
|
||||
class="imglabel"
|
||||
mode="scaleToFill"
|
||||
lazy-load
|
||||
:src="skuName.img"
|
||||
/>
|
||||
</view>
|
||||
<!-- 图片 -->
|
||||
<!-- 其他信息 -->
|
||||
<view class="skuName-info">
|
||||
<!-- 名称 -->
|
||||
<view class="skuName-name">
|
||||
{{ skuName.prefix ? '[' + skuName.prefix + ']' : ''
|
||||
}}{{ skuName.name }}
|
||||
</view>
|
||||
<view @tap.stop="copyInfo(''+ skuName.id, '复制nameID成功')" style="color:#818181;">
|
||||
<text>{{ skuName.id }}</text>
|
||||
<jx-icon icon="fuzhi" color="#818181" style="margin-left: 10rpx;"></jx-icon>
|
||||
</view>
|
||||
<!-- 价格 改价 -->
|
||||
<view class="skuName-price" @tap="openPriceDialog(skuName)">
|
||||
<jx-price
|
||||
:price="skuName.unitPrice"
|
||||
color="#F60D58"
|
||||
sizeM="22rpx"
|
||||
sizeN="38rpx"
|
||||
/>
|
||||
|
||||
<view class="icon-modify" v-if="!isAudit">
|
||||
<jx-icon icon="shuxie" color="#999" :size="38" />
|
||||
</view>
|
||||
</view>
|
||||
<!-- 提示信息 -->
|
||||
<view>
|
||||
<view class="skuName-tips" v-if="skuName.unit === '份'">
|
||||
该价格为每斤价格
|
||||
</view>
|
||||
<view class="skuName-tips green" v-if="skuName.unit !== '份'">
|
||||
该价格为每{{ skuName.unit }}价格
|
||||
</view>
|
||||
<!-- 审核状态 -->
|
||||
<view class="check-display" v-show="skuName.auditUnitPrice">
|
||||
审核中价格:<jx-price
|
||||
:price="skuName.auditUnitPrice"
|
||||
color="#f44"
|
||||
size="24rpx"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 其他信息 -->
|
||||
</view>
|
||||
<!-- skuName -->
|
||||
<!-- sku2 -->
|
||||
<view class="skus-wrapper-new" v-if="!isAudit">
|
||||
<view v-for="(sku, j) in skuName.skus" :key="j" class="sku-cell2">
|
||||
<!-- 异常商品 -->
|
||||
<view
|
||||
class="error mt"
|
||||
v-if="
|
||||
sku.mtwmID !== '' &&
|
||||
(sku.mtwmSyncStatus & 16) === 16 &&
|
||||
(sku.mtwmSyncStatus & 2) !== 2 &&
|
||||
(sku.mtwmSyncStatus & 4) !== 4
|
||||
"
|
||||
>美团:该商品无法修改价格,请联系运营修改</view
|
||||
>
|
||||
<view
|
||||
class="error eb"
|
||||
v-if="
|
||||
sku.ebaiID !== '' &&
|
||||
(sku.ebaiSyncStatus & 16) === 16 &&
|
||||
(sku.ebaiSyncStatus & 2) !== 2 &&
|
||||
(sku.ebaiSyncStatus & 4) !== 4
|
||||
"
|
||||
>饿佰:该商品无法修改价格,请联系运营修改</view
|
||||
>
|
||||
<view class="cell-top">
|
||||
<view class="price">
|
||||
<view class="sku-spec">
|
||||
{{ sku.specQuality }}{{ sku.specUnit }}
|
||||
</view>
|
||||
<view
|
||||
class="sku-price"
|
||||
:class="{ 'promotion-price': !isNewPriceDisplay && sku.actPrice }"
|
||||
>
|
||||
<jx-price
|
||||
:price="sku.comparePrice"
|
||||
sizeM="22rpx"
|
||||
sizeN="28rpx"
|
||||
color="#000"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn-group">
|
||||
<view
|
||||
class="btn"
|
||||
:class="{ onActive: sku.storeSkuStatus }"
|
||||
@tap="updateSaleStatus(sku, skuName, 1)"
|
||||
>
|
||||
可售
|
||||
</view>
|
||||
<view
|
||||
class="btn"
|
||||
:class="{ onActive: !sku.storeSkuStatus && !sku.autoSaleAt }"
|
||||
@tap="updateSaleStatus(sku, skuName, 0)"
|
||||
>
|
||||
不可售
|
||||
</view>
|
||||
<view
|
||||
v-if="!isHot"
|
||||
class="btn tmpSaleNo"
|
||||
:class="{ onActive: !sku.storeSkuStatus && sku.autoSaleAt }"
|
||||
@tap="tmpSaleNo(sku, skuName)"
|
||||
>
|
||||
<text>临时</text>
|
||||
<text>不可售</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 库存以及位置码 -->
|
||||
<view style="display: flex;color:#666;margin-top:20rpx;justify-content: center">
|
||||
<view @tap="openDialog(skuName,sku,'stock')">
|
||||
库存:{{sku.stock}}
|
||||
<jx-icon icon="shuxie" color="#999" :size="24" />
|
||||
</view>
|
||||
<view style="margin-left: 20rpx;" @tap="openDialog(skuName,sku,'locationCode')">
|
||||
货架码:{{sku.locationCode && sku.locationCode !== 'EMPTY_VALUE' ? sku.locationCode : ''}}
|
||||
<jx-icon icon="shuxie" color="#999" :size="24" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="cell-bottom">{{ sku.comment ? sku.comment : '' }}</view>
|
||||
<view class="sku-autoSaleAt" v-if="sku.autoSaleAt">
|
||||
该规格将在 <text>{{ sku.autoSaleAt }}</text> 可售
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="showMountTab" class="checkBoxWrap">
|
||||
<label @tap="handleSale(skuName)">
|
||||
<checkbox color="#4eb331" style="transform: scale(0.8)" />选中商品
|
||||
</label>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 待审核商品操作面板 -->
|
||||
<view class="aduit-wall" v-else>
|
||||
<view class="aduit-type">{{
|
||||
skuName.type === 1 ? '【价格】正在审核中' : '【新建】正在审核中'
|
||||
}}</view>
|
||||
<!-- ((userType & 4) === 4) 运营 -->
|
||||
<view class="aduit-btn-group" v-if="(+getStorage('userType') & 4) === 4">
|
||||
<view class="btn refuse" @tap="toExamine(skuName, -1)">拒绝</view>
|
||||
<view class="btn" @tap="toExamine(skuName, 1)">批准</view>
|
||||
</view>
|
||||
<view class="aduit-btn-group" v-else>
|
||||
<view class="btn" @tap="phoneCall(storeInfo.marketManName)"
|
||||
>联系运营加快审核</view
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup >
|
||||
import useGlobalFunc from '@/composables/useGlobalFunc'
|
||||
import { store } from '@/store'
|
||||
import { getStorage } from '@/utils/storage'
|
||||
import { computed } from 'vue'
|
||||
import goodsListFn from './right-main'
|
||||
import useOrderInfo from '@/composables/useOrderInfo'
|
||||
const { copyInfo } = useOrderInfo()
|
||||
const { phoneCall } = useGlobalFunc()
|
||||
|
||||
/*************************************************
|
||||
* 接收数据
|
||||
*/
|
||||
interface propType {
|
||||
skuName: AnyObject
|
||||
isAudit: boolean
|
||||
isHot: boolean
|
||||
showMountTab: boolean
|
||||
}
|
||||
|
||||
const prop = defineProps<propType>()
|
||||
|
||||
const {
|
||||
isNewPriceDisplay, // 列表判断条件
|
||||
updateSaleStatus, // 修改商品售卖状态
|
||||
tmpSaleNo, // 临时不可售
|
||||
} = goodsListFn(prop)
|
||||
const {
|
||||
previewImage, // 预览图片
|
||||
} = useGlobalFunc()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'handleSale', data: AnyObject): void
|
||||
(e: 'openPriceDialog', data: AnyObject): void
|
||||
(e: 'openDialog', data: AnyObject): void
|
||||
(e: 'toExamine', data: AnyObject): void
|
||||
}>()
|
||||
function handleSale(skuName: AnyObject) {
|
||||
emit('handleSale', skuName)
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 预览图片
|
||||
*/
|
||||
function previewImg(skuName:AnyObject) {
|
||||
let arr = [skuName.img,skuName.img2,skuName.img3,skuName.img4,skuName.img5].filter(item => { return item && item.length > 0 })
|
||||
previewImage(arr)
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 修改操作
|
||||
*/
|
||||
function openPriceDialog(skuName: AnyObject) {
|
||||
if (prop.isAudit) return
|
||||
emit('openPriceDialog', skuName)
|
||||
}
|
||||
|
||||
|
||||
function openDialog(skuName: AnyObject,sku:AnyObject,type:String) {
|
||||
let payload = {
|
||||
nameID:skuName.id,
|
||||
Skus:[{
|
||||
skuID:sku.id,
|
||||
stock:sku.stock,
|
||||
locationCode:sku.locationCode && sku.locationCode !== 'EMPTY_VALUE' ? sku.locationCode : ''
|
||||
}]
|
||||
}
|
||||
emit('openDialog', {payload,type,name:skuName.name})
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 拒绝改价
|
||||
*/
|
||||
function toExamine(skuName: AnyObject, type: any) {
|
||||
let data = {
|
||||
status: type,
|
||||
nameID: skuName.nameID,
|
||||
storeID: getStorage('storeID'),
|
||||
auditPrice: skuName.auditUnitPrice,
|
||||
}
|
||||
emit('toExamine', data)
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* 获取门店信息
|
||||
*/
|
||||
const storeInfo = computed(() => {
|
||||
return store.state.storeInfo.allStoreInfo
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './right-main.scss';
|
||||
</style>
|
||||
@@ -0,0 +1,217 @@
|
||||
<template>
|
||||
<view class="filter-root"
|
||||
:class="{'filter-fill':isCheckoutFilter}">
|
||||
<template v-if="isCheckoutFilter">
|
||||
<view
|
||||
class="item item-fill"
|
||||
:class="{ active: filteActive2 == item.lable }"
|
||||
v-for="(item, index) in filterData2"
|
||||
:key="index"
|
||||
@tap="fliterFn2(item.lable, item.status)"
|
||||
>{{ item.title }}</view
|
||||
>
|
||||
</template>
|
||||
<template v-else>
|
||||
<view
|
||||
class="item item-fill"
|
||||
:class="{ active: filteActive == item.lable }"
|
||||
v-for="(item, index) in filterData"
|
||||
:key="index"
|
||||
@tap="fliterFn(item, item.status)"
|
||||
>{{ item.title }}</view
|
||||
>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup >
|
||||
import { ref, watch } from 'vue'
|
||||
import { jx_throttles } from '@/utils/tools'
|
||||
import toast from '@/utils/toast'
|
||||
|
||||
interface propsType {
|
||||
isCheckoutFilter: boolean
|
||||
updateStateOk: boolean
|
||||
}
|
||||
const props = defineProps<propsType>()
|
||||
|
||||
/*************************************************
|
||||
* 参数1
|
||||
*/
|
||||
const filterData = ref<Array<AnyObject>>([
|
||||
{
|
||||
title: '全部',
|
||||
name:'all',
|
||||
lable: 2,
|
||||
status: -1,
|
||||
},
|
||||
{
|
||||
title: '可售',
|
||||
name:'status',
|
||||
lable: 1,
|
||||
status: 1,
|
||||
},
|
||||
{
|
||||
title: '不可售',
|
||||
name:'status',
|
||||
lable: 0,
|
||||
status: 0,
|
||||
},
|
||||
{
|
||||
title: '有库存', //库存 1 全查~ 2 有~ 3 无~
|
||||
name:'stock',
|
||||
lable:4,
|
||||
status: 2,
|
||||
},
|
||||
{
|
||||
title: '无库存',
|
||||
name:'stock',
|
||||
lable:5,
|
||||
status: 3,
|
||||
},
|
||||
// {
|
||||
// title: '有货架码',
|
||||
// name:'locationCode',
|
||||
// lable:6,
|
||||
// status:false // 实际上是全部查,感觉没用
|
||||
// },
|
||||
{
|
||||
title: '无货架码',
|
||||
name:'locationCode',
|
||||
lable:7,
|
||||
status:true
|
||||
},
|
||||
{
|
||||
title: '批量',
|
||||
name:'',
|
||||
lable: 3,
|
||||
status: -1,
|
||||
},
|
||||
])
|
||||
|
||||
/*************************************************
|
||||
* 参数2
|
||||
*/
|
||||
const filterData2 = ref<Array<AnyObject>>([
|
||||
{
|
||||
title: '全部',
|
||||
lable: 2,
|
||||
status: -1,
|
||||
},
|
||||
{
|
||||
title: '批量',
|
||||
lable: 3,
|
||||
status: -1,
|
||||
},
|
||||
])
|
||||
|
||||
/*************************************************
|
||||
* emit
|
||||
*/
|
||||
const emit = defineEmits<{
|
||||
(e: 'updateIsSale', data: AnyObject): void
|
||||
(e: 'updateTowFilter', data: AnyObject): void
|
||||
}>()
|
||||
|
||||
/*************************************************
|
||||
* 筛选1
|
||||
*/
|
||||
const filteActive = ref<number>(2)
|
||||
function fliterFn(item: AnyObject, status: number) {
|
||||
if (filteActive.value == item.lable) return
|
||||
fliterFnThrottles(item, status)
|
||||
}
|
||||
const fliterFnThrottles = jx_throttles({
|
||||
time: 2000,
|
||||
success: (item: AnyObject, status: number | boolean) => {
|
||||
filteActive.value = item.lable
|
||||
filteActive2.value = item.lable
|
||||
let data = {
|
||||
status: status,
|
||||
lable: item.lable,
|
||||
name:item.name
|
||||
}
|
||||
emit('updateIsSale', data)
|
||||
},
|
||||
fail: () => {
|
||||
toast('老板要点慢点哦')
|
||||
},
|
||||
})
|
||||
|
||||
/*************************************************
|
||||
* 筛选2
|
||||
*/
|
||||
const filteActive2 = ref<number>(2)
|
||||
function fliterFn2(lable: number, status: number) {
|
||||
if (filteActive2.value == lable) return
|
||||
filteActive2.value = lable
|
||||
filteActive.value = lable
|
||||
let data = {
|
||||
status: status,
|
||||
lable: lable,
|
||||
}
|
||||
emit('updateTowFilter', data)
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.updateStateOk,
|
||||
(val) => {
|
||||
if (val) {
|
||||
filteActive2.value = 2
|
||||
filteActive.value = 2
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.filter-root {
|
||||
display: flex;
|
||||
overflow-x: auto; /* 允许水平方向滚动 */
|
||||
white-space: nowrap; /* 防止子元素换行 */
|
||||
align-items: center;
|
||||
// justify-content: space-around;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
border-left: 1rpx solid rgb(223, 223, 223);
|
||||
height: 90rpx;
|
||||
background-color: #fff;
|
||||
box-shadow: 10rpx 0rpx 10rpx rgb(207, 207, 207);
|
||||
border-bottom: 1rpx solid rgb(224, 224, 224);
|
||||
padding: 0 10rpx;
|
||||
|
||||
.filter-fill{
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.item {
|
||||
flex: 1;
|
||||
height: 60rpx;
|
||||
border-radius: 10rpx;
|
||||
border: 2rpx solid $jx-primary;
|
||||
color: $jx-primary;
|
||||
padding: 0 10rpx;
|
||||
line-height: 60rpx;
|
||||
text-align: center;
|
||||
transition: all 0.2s;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.item-filter{
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.item-fill{
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.item:nth-child(1) {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.active {
|
||||
background-color: $jx-primary;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<view class="search-root">
|
||||
<view class="add-shopping" @tap="createGoods">
|
||||
<jx-icon icon="jiahao" color="#4eb331" />
|
||||
<text>新建</text>
|
||||
</view>
|
||||
|
||||
<uni-search-bar
|
||||
cancelButton="none"
|
||||
clearButton="auto"
|
||||
placeholder="请输入关键字 例如:精华液"
|
||||
@confirm="confirm"
|
||||
@input="input"
|
||||
@clear="clear"
|
||||
v-model="text"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup >
|
||||
import toast from '@/utils/toast'
|
||||
import { jx_trembling } from '@/utils/tools'
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
/*************************************************
|
||||
* props
|
||||
*/
|
||||
interface propsType {
|
||||
isFilter: string | number
|
||||
}
|
||||
const props = defineProps<propsType>()
|
||||
|
||||
const text = ref<string>('')
|
||||
|
||||
let isInput = false
|
||||
watch(
|
||||
() => props.isFilter,
|
||||
(val) => {
|
||||
if (val == 'hot' || val == 'audit') {
|
||||
isInput = true
|
||||
} else {
|
||||
isInput = false
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
/*************************************************
|
||||
* emit
|
||||
*/
|
||||
const emit = defineEmits<{
|
||||
(e: 'serachShopping', data: string): void
|
||||
(e: 'clearInpu', data: string): void
|
||||
(e: 'createGoods'): void
|
||||
}>()
|
||||
|
||||
/*************************************************
|
||||
* 确定搜索
|
||||
*/
|
||||
let watchTimer: any = null
|
||||
function confirm(e: AnyObject) {
|
||||
if (isInput) {
|
||||
let watchTimer = setTimeout(() => {
|
||||
text.value = ''
|
||||
clearTimeout(watchTimer)
|
||||
}, 500)
|
||||
return toast('该分类暂不支持搜索')
|
||||
}
|
||||
emit('serachShopping', e.value)
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 输入框加载
|
||||
*/
|
||||
function input(e: string) {
|
||||
if (isInput) {
|
||||
let watchTimer = setTimeout(() => {
|
||||
text.value = ''
|
||||
clearTimeout(watchTimer)
|
||||
}, 500)
|
||||
return toast('该分类暂不支持搜索')
|
||||
}
|
||||
trembling(e)
|
||||
}
|
||||
const trembling = jx_trembling((e: string) => {
|
||||
emit('serachShopping', e)
|
||||
}, 1000)
|
||||
|
||||
/*************************************************
|
||||
* 清空输入框
|
||||
*/
|
||||
function clear(e: AnyObject) {
|
||||
if (isInput) return
|
||||
emit('clearInpu', e.value)
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 新建商品
|
||||
*/
|
||||
function createGoods() {
|
||||
emit('createGoods')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.search-root {
|
||||
box-sizing: border-box;
|
||||
background-color: $jx-primary;
|
||||
padding: 0 20rpx 2rpx 20rpx;
|
||||
height: 92rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.add-shopping {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
background-color: #fff;
|
||||
font-size: 20rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
border-radius: 50%;
|
||||
color: $jx-primary;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
45
src/pages/goods-manager/component/left-bar/left-bar.scss
Normal file
45
src/pages/goods-manager/component/left-bar/left-bar.scss
Normal file
@@ -0,0 +1,45 @@
|
||||
// 一级
|
||||
.one-item {
|
||||
background-color: #fff;
|
||||
height: 90rpx;
|
||||
overflow: hidden;
|
||||
transition: all 0.4s;
|
||||
border-bottom: 1rpx solid #f1f1f1;
|
||||
|
||||
// 二级名字
|
||||
.one-item-name {
|
||||
display: flex;
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
|
||||
.iconfont {
|
||||
display: inline-block;
|
||||
transform: rotate(0deg);
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.noe-seat {
|
||||
display: inline-block;
|
||||
width: 30rpx;
|
||||
height: 90rpx;
|
||||
border-left: 7rpx solid transparent;
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
// 二级内容
|
||||
.tow-item {
|
||||
display: flex;
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
transition: none;
|
||||
|
||||
// 二级左侧竖杠
|
||||
.tow-seat {
|
||||
display: inline-block;
|
||||
width: 30rpx;
|
||||
height: 90rpx;
|
||||
border-left: 7rpx solid transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
83
src/pages/goods-manager/component/left-bar/left-bar.ts
Normal file
83
src/pages/goods-manager/component/left-bar/left-bar.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import { getStorage } from "@/utils/storage"
|
||||
import { onLoad } from "@dcloudio/uni-app"
|
||||
import { ref } from "vue"
|
||||
import shopping from "@/api/https/shopping"
|
||||
|
||||
/*************************************************
|
||||
* 商品分类栏目
|
||||
*/
|
||||
function leftBarFn(props: AnyObject) {
|
||||
|
||||
onLoad(async () => {
|
||||
await GetStoreCategoryMap()
|
||||
})
|
||||
|
||||
/*************************************************
|
||||
* @info 左侧tab数据
|
||||
* 获取列表数据
|
||||
*/
|
||||
const cat = ref<Array<AnyObject>>([])
|
||||
async function GetStoreCategoryMap() {
|
||||
let data = {
|
||||
storeID: getStorage('storeID'),
|
||||
parentID: -1,
|
||||
}
|
||||
let res = await shopping.getStore_category_map(data)
|
||||
if (res.code == 0) {
|
||||
handledata(res.data, true)
|
||||
} else {
|
||||
cat.value = []
|
||||
handleOriginData()
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 处理列表数据
|
||||
*/
|
||||
const _isMap = ref<boolean>(false)
|
||||
function handledata(curdeData: Array<AnyObject>, isMap: boolean) {
|
||||
let data = curdeData
|
||||
let catData: Array<AnyObject> = []
|
||||
data.forEach((item: AnyObject) => {
|
||||
if (item.name !== '3件9.9') {
|
||||
item.name = item.name.slice(0, 4)
|
||||
}
|
||||
catData.push(item)
|
||||
})
|
||||
|
||||
//把sku分类过滤掉
|
||||
if (!isMap) catData = catData.filter((item) => item.type === 0)
|
||||
let catLevel1 = catData.filter((item) => item.level === 1)
|
||||
let catLevel2 = catData.filter((item) => item.level === 2)
|
||||
|
||||
// 组合分类
|
||||
let catData2: Array<AnyObject> = []
|
||||
let catData3: AnyObject
|
||||
catLevel1.forEach((level1: AnyObject) => {
|
||||
isMap
|
||||
? (catData3 = catLevel2.filter(
|
||||
(level2) => level2.parentID === level1.categoryID
|
||||
))
|
||||
: (catData3 = catLevel2.filter((level2) => level2.parentID === level1.id))
|
||||
level1.children = catData3
|
||||
_isMap.value = isMap
|
||||
catData2.push(level1)
|
||||
})
|
||||
let lastData = props.dafauleData.concat(catData2)
|
||||
cat.value = lastData
|
||||
}
|
||||
|
||||
async function handleOriginData() {
|
||||
let res = await shopping.get_categories()
|
||||
if (res.code == 0) {
|
||||
handledata(res.data, false)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
cat, // 右侧菜单数据
|
||||
GetStoreCategoryMap, // 获取数据
|
||||
}
|
||||
}
|
||||
|
||||
export default leftBarFn
|
||||
139
src/pages/goods-manager/component/left-bar/left-bar.vue
Normal file
139
src/pages/goods-manager/component/left-bar/left-bar.vue
Normal file
@@ -0,0 +1,139 @@
|
||||
<template>
|
||||
<view
|
||||
v-for="(item, index) in cat"
|
||||
:key="index"
|
||||
class="one-item"
|
||||
:class="{
|
||||
'one-item-active':
|
||||
index == oneActive && item.children.length != 0 && isOpen,
|
||||
'item-name': oneActive == index && item.children.length == 0,
|
||||
}"
|
||||
>
|
||||
<!-- 第一层 -->
|
||||
<view
|
||||
:class="{
|
||||
'never-pen-active': index == oneActive && item.children.length != 0,
|
||||
}"
|
||||
class="one-item-name"
|
||||
@tap="oneItemFn(item, index)"
|
||||
>
|
||||
<text class="iconfont icon-jiantou1" v-if="item.children.length != 0" />
|
||||
<text class="noe-seat noe-seat-active" v-else></text>
|
||||
<text>{{ item.name }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 第二层 -->
|
||||
<view
|
||||
class="tow-item"
|
||||
:class="{ 'tow-item-active': towActive == childIndex }"
|
||||
v-for="(childItem, childIndex) in item.children"
|
||||
:key="childIndex"
|
||||
@tap="towItemFn(childItem, childIndex)"
|
||||
>
|
||||
<text class="tow-seat tow-seat-active"></text>{{ childItem.name }}</view
|
||||
>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup >
|
||||
import { Ref, ref } from 'vue'
|
||||
import leftBarFn from './left-bar'
|
||||
|
||||
/*************************************************
|
||||
* 接收数据
|
||||
*/
|
||||
interface propsType {
|
||||
dafauleData: Array<AnyObject>
|
||||
}
|
||||
const props = defineProps<propsType>()
|
||||
|
||||
const {
|
||||
cat, // 右侧菜单数据
|
||||
GetStoreCategoryMap, // 获取数据
|
||||
} = leftBarFn(props)
|
||||
|
||||
/*************************************************
|
||||
* emit
|
||||
*/
|
||||
const eimt = defineEmits<{
|
||||
(e: 'oneMenuClick', data: string | number): void
|
||||
}>()
|
||||
|
||||
/*************************************************
|
||||
* 一级菜单点击
|
||||
*/
|
||||
const isOpen = ref<boolean>(false)
|
||||
const oneActive = ref<number>(0) // 高亮
|
||||
const oneHeight: Ref<string> = ref('0px') // 高度
|
||||
function oneItemFn(item: AnyObject, index: number) {
|
||||
if (oneActive.value == index) {
|
||||
isOpen.value = !isOpen.value
|
||||
} else {
|
||||
isOpen.value = true
|
||||
}
|
||||
oneActive.value = index // 一级菜单
|
||||
oneHeight.value = `${(item.length + 1) * 90}rpx` // 动态高度
|
||||
towActive.value = -1 // 默认二级菜单
|
||||
if (!isOpen.value) return
|
||||
eimt('oneMenuClick', item.categoryID)
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 二级菜单点击
|
||||
*/
|
||||
const towActive = ref<number>(-1) // 高亮
|
||||
function towItemFn(childItem: AnyObject, index: number) {
|
||||
if (towActive.value == index) return
|
||||
towActive.value = index
|
||||
eimt('oneMenuClick', childItem.categoryID)
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 导出子组件方法
|
||||
*/
|
||||
defineExpose({
|
||||
GetStoreCategoryMap,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './left-bar.scss';
|
||||
|
||||
// 一级展开动画
|
||||
.one-item-active {
|
||||
height: v-bind(oneHeight) !important;
|
||||
background-color: rgb(236, 252, 233);
|
||||
|
||||
// 三角图标动画
|
||||
.icon-jiantou1 {
|
||||
display: inline-block;
|
||||
transform: rotate(90deg) !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 一级选中高亮
|
||||
.never-pen-active {
|
||||
background-color: $jx-primary;
|
||||
color: #fff;
|
||||
border-bottom: 1rpx solid #fff;
|
||||
}
|
||||
|
||||
// 一级展开背景
|
||||
.item-name {
|
||||
color: $jx-primary;
|
||||
.noe-seat-active {
|
||||
border-left: 7rpx solid $jx-primary !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 二级高亮
|
||||
.tow-item-active {
|
||||
color: $jx-primary;
|
||||
background-color: #fff;
|
||||
|
||||
// 二级选中高亮
|
||||
.tow-seat-active {
|
||||
border-left: 7rpx solid $jx-primary !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
132
src/pages/goods-manager/main.scss
Normal file
132
src/pages/goods-manager/main.scss
Normal file
@@ -0,0 +1,132 @@
|
||||
.status_bar {
|
||||
height: var(--status-bar-height);
|
||||
width: 100%;
|
||||
background-color: $jx-primary;
|
||||
}
|
||||
|
||||
.MountWrap {
|
||||
display: flex;
|
||||
z-index: 99;
|
||||
box-sizing: border-box;
|
||||
justify-content: space-between;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: $jx-primary;
|
||||
padding: 20rpx 25rpx;
|
||||
|
||||
.onActive {
|
||||
width: 44%;
|
||||
background-color: #fff;
|
||||
color: $jx-primary;
|
||||
text-align: center;
|
||||
border-radius: 10rpx;
|
||||
padding: 10rpx 0;
|
||||
}
|
||||
}
|
||||
|
||||
.createGoods {
|
||||
padding: 10rpx 80rpx;
|
||||
border-radius: 10rpx;
|
||||
background-color: $jx-primary;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.jx-popup-update {
|
||||
box-sizing: border-box;
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 0 0 15rpx 15rpx;
|
||||
|
||||
.text {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
margin-bottom: 25rpx;
|
||||
padding-bottom: 10rpx;
|
||||
border-bottom: 2rpx solid rgb(234, 234, 234);
|
||||
}
|
||||
|
||||
.tip-new{
|
||||
padding: 2rpx 0;
|
||||
height: 66rpx;
|
||||
line-height: 66rpx;
|
||||
text-align: left;
|
||||
border-bottom:1px dashed #999;
|
||||
|
||||
.money {
|
||||
color: $jx-primary;
|
||||
}
|
||||
}
|
||||
|
||||
.ipt-box{
|
||||
margin: 10rpx 0;
|
||||
// height: 86rpx;
|
||||
// line-height: normal;
|
||||
}
|
||||
|
||||
|
||||
.tip {
|
||||
padding: 10rpx 0;
|
||||
|
||||
.money {
|
||||
color: $jx-primary;
|
||||
}
|
||||
}
|
||||
|
||||
.ipt {
|
||||
border: 2rpx solid rgb(209, 209, 209);
|
||||
text-align: center;
|
||||
|
||||
border-radius: 5rpx;
|
||||
height: 86rpx;
|
||||
line-height: normal;
|
||||
// -webkit-appearance: none;
|
||||
// border-radius: 0
|
||||
}
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.btn-root {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 40rpx 0 0rpx 0;
|
||||
|
||||
.btn-esc,
|
||||
.btn-ok {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
padding: 15rpx 0;
|
||||
border-radius: 10rpx;
|
||||
border: 2rpx solid $jx-primary;
|
||||
color: $jx-primary;
|
||||
}
|
||||
|
||||
.btn-ok {
|
||||
background-color: $jx-primary;
|
||||
color: #fff;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.btn-esc {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.delete {
|
||||
margin-top: 50rpx;
|
||||
margin-bottom: 20rpx;
|
||||
background-color: $jx-warring;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
padding: 20rpx;
|
||||
border-radius: 15rpx;
|
||||
}
|
||||
}
|
||||
714
src/pages/goods-manager/main.ts
Normal file
714
src/pages/goods-manager/main.ts
Normal file
@@ -0,0 +1,714 @@
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||
import { getStorage } from '@/utils/storage'
|
||||
import { computed, onBeforeUnmount, ref } from 'vue'
|
||||
import { store } from '@/store'
|
||||
import { timeFormatD, timeFormatHMS } from '@/utils/tools'
|
||||
import toast from '@/utils/toast'
|
||||
import merchant from "@/api/https/merchant"
|
||||
import shopping from "@/api/https/shopping"
|
||||
/*************************************************
|
||||
* 商品管理
|
||||
*/
|
||||
function shoppingMangerFn() {
|
||||
/*************************************************
|
||||
* 数据归位,元神显现
|
||||
*/
|
||||
function dataHoming() {
|
||||
skuNames.value = []
|
||||
page.value = 1
|
||||
totalCount.value = 0
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 下拉刷新数据重现
|
||||
*/
|
||||
const leftBarRef = ref<any>(null)
|
||||
let onPullDownRefreshTimer: any = ''
|
||||
const triggered = ref<boolean>(false)
|
||||
function refresherrefresh() {
|
||||
triggered.value = true
|
||||
clearTimeout(onPullDownRefreshTimer)
|
||||
onPullDownRefreshTimer = setTimeout(() => {
|
||||
triggered.value = false
|
||||
dataHoming()
|
||||
oneMenuClick(isFilter.value)
|
||||
if (isFilter.value == 'hot') return
|
||||
leftBarRef.value.GetStoreCategoryMap()
|
||||
}, 500)
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 获取数据
|
||||
*/
|
||||
let oldStoreID: any = 0
|
||||
onShow(() => {
|
||||
if (oldStoreID != getStorage('storeID') && oldStoreID != 0) {
|
||||
triggered.value = true
|
||||
}
|
||||
oldStoreID = getStorage('storeID')
|
||||
})
|
||||
|
||||
/*************************************************
|
||||
* 默认数据
|
||||
*/
|
||||
const dafauleData: Array<AnyObject> = [
|
||||
{
|
||||
categoryID: 'all',
|
||||
children: [],
|
||||
level: 1,
|
||||
name: '所有分类',
|
||||
},
|
||||
{
|
||||
categoryID: 'act',
|
||||
children: [],
|
||||
level: 1,
|
||||
name: '活动商品',
|
||||
},
|
||||
{
|
||||
categoryID: 'hot',
|
||||
children: [],
|
||||
level: 1,
|
||||
name: '畅销推荐',
|
||||
},
|
||||
{
|
||||
categoryID: 'audit',
|
||||
children: [],
|
||||
level: 1,
|
||||
name: '待审商品',
|
||||
},
|
||||
]
|
||||
|
||||
/*************************************************
|
||||
* @info 右侧主体数据
|
||||
* 获取商品数据
|
||||
*/
|
||||
const statusBarHeight = ref<string>('0px') // 状态栏高度
|
||||
onLoad(async () => {
|
||||
// 获取状态栏高度
|
||||
uni.getSystemInfo({
|
||||
success: (res: any) => {
|
||||
statusBarHeight.value = res.statusBarHeight + 'px'
|
||||
}
|
||||
})
|
||||
await getSkuNames()
|
||||
})
|
||||
const keyword = ref<string>('')
|
||||
const categoryID = ref<string>('') // 分类id
|
||||
const isAct = ref<boolean>(false) // 是否是活动商品
|
||||
const totalCount = ref<number>(0) // 总条数
|
||||
const skuNames = ref<Array<AnyObject>>([]) // 商品数据
|
||||
const isAudit = ref<boolean>(false) // 商品列表判断条件
|
||||
const isHot = ref<boolean>(false) // 商品列表判断条件
|
||||
async function getSkuNames() {
|
||||
isLoad.value = true
|
||||
let data:AnyObject = {
|
||||
categoryID: categoryID.value,
|
||||
isFocus: true,
|
||||
keyword: keyword.value,
|
||||
offset: pageSize.value * (page.value - 1),
|
||||
pageSize: pageSize.value,
|
||||
isAct: isAct.value,
|
||||
status: -1,
|
||||
storeID: getStorage('storeID')
|
||||
}
|
||||
|
||||
if(allSaleStatus.value && allSaleStatus.value.name !== 'all') data[allSaleStatus.value.name] = allSaleStatus.value.status
|
||||
|
||||
keyFilter(data)
|
||||
let res = await shopping.get_stores_skus_for_store(data)
|
||||
if (res.code == 0) {
|
||||
totalCount.value = res.data.totalCount
|
||||
let filterData = mapskuName(res.data.skuNames || [])
|
||||
skuNames.value = skuNames.value.concat(filterData)
|
||||
if (filterData.length == 0) return toast('该分类未找到商品')
|
||||
} else {
|
||||
dataHoming()
|
||||
toast('分类查询错误')
|
||||
}
|
||||
isLoad.value = false
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 过滤对象空字段
|
||||
*/
|
||||
function keyFilter(obj: AnyObject) {
|
||||
for (let key in obj) {
|
||||
if ('' + obj[key] == "" || '' + obj[key] == undefined) {
|
||||
delete obj[key]
|
||||
}
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 列表判断条件
|
||||
*/
|
||||
const isNewPriceDisplay = ref<boolean>(
|
||||
store.getters['storeInfo/isNewPriceDisplay']
|
||||
)
|
||||
|
||||
/*************************************************
|
||||
* 格式化数据
|
||||
*/
|
||||
function mapskuName(skuNames: Array<AnyObject>) {
|
||||
let arr = skuNames.map((skuName) => {
|
||||
skuName.auditUnitPrice = skuName.auditUnitPrice
|
||||
// 是否全部不可售
|
||||
if (skuName.skus.some((item: AnyObject) => item.storeSkuStatus)) {
|
||||
skuName.skuAllnoSale = false
|
||||
} else {
|
||||
skuName.skuAllnoSale = true
|
||||
}
|
||||
// skus
|
||||
skuName.skus = skuName.skus.map((sku: AnyObject) => {
|
||||
// 价格异常请参考老版本或者在git进行查看
|
||||
sku.comparePrice = sku.price
|
||||
sku.autoSaleAt =
|
||||
+new Date(sku.autoSaleAt) > 0 ? timeFormatHMS(sku.autoSaleAt) : 0
|
||||
return sku
|
||||
})
|
||||
return skuName
|
||||
})
|
||||
return arr
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 页面触底,加载更多数据
|
||||
*/
|
||||
const page = ref<number>(1) // 第几页
|
||||
const pageSize = ref<number>(20) // 每页条数
|
||||
const isLoad = ref<boolean>(false) // 加载图
|
||||
function scrolltolower() {
|
||||
page.value++
|
||||
if (pageSize.value * (page.value - 1) > totalCount.value || totalCount.value < pageSize.value) {
|
||||
isLoad.value = false
|
||||
} else {
|
||||
if (isLoad.value) return
|
||||
if (isFilter.value == 'hot') return
|
||||
if (isFilter.value == 'audit') return GetStoreSkuAudit()
|
||||
getSkuNames()
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 点击菜单获取数据
|
||||
*/
|
||||
const isCheckoutFilter = ref<boolean>(false)
|
||||
const isFilter = ref<string | number>('')
|
||||
function oneMenuClick(catID: string | number) {
|
||||
isAct.value = false
|
||||
isHot.value = false
|
||||
isCheckoutFilter.value = false
|
||||
categoryID.value = ''
|
||||
keyword.value = ''
|
||||
isFilter.value = catID
|
||||
isAudit.value = false
|
||||
dataHoming()
|
||||
if (catID == 'all') { // 全部商品
|
||||
isAct.value = false
|
||||
getSkuNames()
|
||||
} else if (catID == 'act') { // 活动商品
|
||||
isAct.value = true
|
||||
getSkuNames()
|
||||
} else if (catID == 'hot') { // 畅销商品
|
||||
isHot.value = true
|
||||
isCheckoutFilter.value = true
|
||||
getTopSkus()
|
||||
} else if (catID == 'audit') { // 待审核商品
|
||||
isCheckoutFilter.value = true
|
||||
isAudit.value = true
|
||||
GetStoreSkuAudit()
|
||||
} else {
|
||||
categoryID.value = catID as string
|
||||
getSkuNames()
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 畅销推荐
|
||||
*/
|
||||
async function getTopSkus() {
|
||||
isLoad.value = true
|
||||
let data = {
|
||||
storeID: getStorage('storeID')
|
||||
}
|
||||
let res = await shopping.get_top_skus_by_city_code(data)
|
||||
if (res.code == 0) {
|
||||
let data = res.data || []
|
||||
if (data.length > 0) {
|
||||
totalCount.value = data.length
|
||||
skuNames.value = mapskuName(data)
|
||||
} else {
|
||||
dataHoming()
|
||||
toast('暂无畅销商品')
|
||||
}
|
||||
|
||||
} else {
|
||||
toast('分类查询错误')
|
||||
dataHoming()
|
||||
}
|
||||
isLoad.value = false
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 待审核商品
|
||||
*/
|
||||
async function GetStoreSkuAudit() {
|
||||
isLoad.value = true
|
||||
let data = {
|
||||
storeIDs: JSON.stringify([getStorage('storeID')]),
|
||||
applyTimeStart: timeFormatD(+new Date() - 1000 * 60 * 60 * 24 * 30) + ' 00:00:00',
|
||||
applyTimeEnd: timeFormatD(+new Date()) + ' 23:59:59',
|
||||
statuss: JSON.stringify([0]),
|
||||
types: JSON.stringify([1, 2]),
|
||||
offset: pageSize.value * (page.value - 1),
|
||||
pageSize: pageSize.value,
|
||||
}
|
||||
let res = await shopping.get_store_sku_audit(data)
|
||||
if (res.code == 0) {
|
||||
totalCount.value = res.data.totalCount
|
||||
let newData = res.data.data || []
|
||||
let filterSkuName = mapAuditSkuName(newData)
|
||||
skuNames.value = skuNames.value.concat(filterSkuName)
|
||||
if (newData.length == 0) return toast('暂无待审核商品')
|
||||
} else {
|
||||
toast('分类查询错误')
|
||||
dataHoming()
|
||||
}
|
||||
isLoad.value = false
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* 过滤待审核商品
|
||||
*/
|
||||
function mapAuditSkuName(data: AnyObject) {
|
||||
let arr = data.map((item: any) => ({
|
||||
auditUnitPrice: item.unitPrice,
|
||||
unitPrice: item.originPrice,
|
||||
skuAllnoSale: false,
|
||||
nameID: item.nameID,
|
||||
img: item.img,
|
||||
unit: item.unit,
|
||||
type: item.type,
|
||||
prefix: item.prefix,
|
||||
name: item.skuName,
|
||||
}))
|
||||
return arr
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* @info 过滤类数据
|
||||
*/
|
||||
const showMountTab = ref<boolean>(false)
|
||||
|
||||
|
||||
/*************************************************
|
||||
* 头部数据过滤
|
||||
*/
|
||||
const allSaleStatus = ref<AnyObject>()
|
||||
async function updateIsSale(data: AnyObject) {
|
||||
allSaleStatus.value = data
|
||||
data.lable == 3
|
||||
? (showMountTab.value = true)
|
||||
: (showMountTab.value = false)
|
||||
if (data.lable == 3) return
|
||||
dataHoming()
|
||||
await getSkuNames()
|
||||
}
|
||||
async function updateTowFilter(data: AnyObject) {
|
||||
if (data.lable == 3) {
|
||||
return showMountTab.value = true
|
||||
} else {
|
||||
showMountTab.value = false
|
||||
}
|
||||
if (isFilter.value == 'hot') {
|
||||
oneMenuClick(isFilter.value)
|
||||
}
|
||||
|
||||
if (isFilter.value == 'audit') {
|
||||
oneMenuClick(isFilter.value)
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* @info 搜索框操作
|
||||
*/
|
||||
async function serachShopping(text: string) {
|
||||
dataHoming()
|
||||
keyword.value = text
|
||||
await getSkuNames()
|
||||
}
|
||||
async function clearInpu() {
|
||||
dataHoming()
|
||||
keyword.value = ''
|
||||
await getSkuNames()
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 批量操作
|
||||
*/
|
||||
let picked: Array<AnyObject> = []
|
||||
function handleSale(skuName: AnyObject) {
|
||||
if (picked && picked.some((item) => item.nameID == skuName.id)) {
|
||||
picked = picked.filter((item) => {
|
||||
return item.nameID != skuName.id
|
||||
})
|
||||
} else {
|
||||
picked.push({ nameID: Number(skuName.id) })
|
||||
picked = distinct(picked, 'nameID')
|
||||
}
|
||||
}
|
||||
function distinct(arr: any, key: string) {
|
||||
let set = new Set()
|
||||
return arr.reduce(
|
||||
(p: any, c: any) => (set.has(c[key]) ? p : (set.add(c[key]), [...p, c])),
|
||||
[]
|
||||
)
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 批量可售与不可售
|
||||
*/
|
||||
let handleChangeSaleTimer: any = null
|
||||
const updateStateOk = ref<boolean>(false)
|
||||
async function handleChangeSale(type: number) {
|
||||
if (picked.length == 0) return toast('未选择商品')
|
||||
picked.forEach((item: AnyObject) => {
|
||||
item['isSale'] = type
|
||||
})
|
||||
let data = {
|
||||
storeIDs: JSON.stringify([getStorage('storeID')]),
|
||||
payload: JSON.stringify(picked),
|
||||
}
|
||||
let res = await shopping.update_stores_skus(data)
|
||||
if (res.code == 0) {
|
||||
toast('修改成功')
|
||||
let data = {
|
||||
status: -1,
|
||||
lable: 2,
|
||||
}
|
||||
updateStateOk.value = true
|
||||
handleChangeSaleTimer = setTimeout(() => {
|
||||
updateIsSale(data)
|
||||
clearTimeout(handleChangeSaleTimer)
|
||||
}, 1000)
|
||||
} else {
|
||||
toast('修改失败', 2)
|
||||
updateStateOk.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 去创建商品
|
||||
*/
|
||||
function createGoods() {
|
||||
uni.navigateTo({ url: '/subPages/shoppingChild/createGoods/createGoods' })
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 改价还是折扣(从vuex 里面读取)
|
||||
*/
|
||||
const isPointStore = computed(() => {
|
||||
return store.getters['storeInfo/isPointStore']
|
||||
})
|
||||
// skuName
|
||||
const skuName = ref<AnyObject>({
|
||||
unit: '',
|
||||
auditUnitPrice: ''
|
||||
})
|
||||
function openPriceDialog(skuNames: AnyObject) {
|
||||
skuName.value = skuNames
|
||||
popup.value.open()
|
||||
}
|
||||
// 当前修改价格
|
||||
const currentValue = ref<string>('')
|
||||
// 审核价格
|
||||
const auditUnitPrice = computed(() => {
|
||||
let price = skuName.value.auditUnitPrice
|
||||
if (price) {
|
||||
return +((price * 1) / 100).toFixed(2)
|
||||
} else {
|
||||
return +'0.00'
|
||||
}
|
||||
})
|
||||
// 弹窗实例
|
||||
const popup = ref<any>(null)
|
||||
// 确定修改价格
|
||||
function handleConfirm() {
|
||||
if (isNaN(+currentValue.value)) return toast('请输入格式正确的价格')
|
||||
if (+currentValue.value < 0.01) return toast('请输入大于等于1分钱的价格')
|
||||
if (
|
||||
currentValue.value.toString().indexOf('.') > -1 &&
|
||||
currentValue.value.toString().split('.')[1].length > 2
|
||||
) {
|
||||
return toast('最多只能有两位小数')
|
||||
}
|
||||
let updatePrice = Math.round(+currentValue.value * 100)
|
||||
if (updatePrice == skuName.value.unitPrice) {
|
||||
return toast('没有修改价格')
|
||||
}
|
||||
if (updatePrice > skuName.value.unitPrice * 1.3 ||
|
||||
updatePrice < skuName.value.unitPrice * 0.7) {
|
||||
uni.jxConfirm({
|
||||
title: '提示',
|
||||
content: `修改幅度超过30%,新价格为¥${(updatePrice / 100).toFixed(2)},是否确定修改?`,
|
||||
success: () => {
|
||||
updatePriceFn(updatePrice, skuName.value.id, skuName.value.unitPrice)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
updatePriceFn(updatePrice, skuName.value.id, skuName.value.unitPrice)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 验证通过开始修改价格
|
||||
*/
|
||||
let updatePriceFnTimer: any = null
|
||||
async function updatePriceFn(price: string | number, id: number, originalUnitPrice: number) {
|
||||
let data = {
|
||||
storeIDs: JSON.stringify([+getStorage('storeID')]),
|
||||
payload: JSON.stringify([
|
||||
{
|
||||
nameID: skuName.value.id,
|
||||
unitPrice: price,
|
||||
},
|
||||
]),
|
||||
}
|
||||
popup.value.close() // 关闭 popup
|
||||
// 修改价格
|
||||
let updatePrice = await shopping.update_stores_skus(data)
|
||||
|
||||
if (updatePrice.code == 0) {
|
||||
// 获取单个门店serverSkuName
|
||||
let storeData = {
|
||||
storeIDs: JSON.stringify([+getStorage('storeID')]),
|
||||
isFocus: true,
|
||||
nameIDs: JSON.stringify([id]),
|
||||
fromStatus: 0,
|
||||
toStatus: 1,
|
||||
}
|
||||
const serverSkuName = await merchant.get_stores_skus(storeData)
|
||||
if (serverSkuName.code == 0) {
|
||||
let skuNameData = serverSkuName.data.skuNames || []
|
||||
if (skuNameData.length > 0) {
|
||||
let index = skuNames.value.findIndex((item: any) => item.id == id)
|
||||
if (index !== -1) skuNames.value[index] = mapskuName(skuNameData)[0]
|
||||
}
|
||||
}
|
||||
// 判断提示
|
||||
if (isPointStore.value || store.state.storeInfo.allStoreInfo.storeLevel == 'E') {
|
||||
toast('修改成功')
|
||||
currentValue.value = ''
|
||||
} else {
|
||||
currentValue.value = ''
|
||||
toast(
|
||||
+price < originalUnitPrice ? '修改成功' : '提交成功, 请等待审核'
|
||||
)
|
||||
}
|
||||
} else {
|
||||
toast('修改失败', 2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* 修该库存或货架码
|
||||
*/
|
||||
const popupDialog = ref<any>(null)
|
||||
const skuNameItem = ref<AnyObject>({
|
||||
payload:{
|
||||
nameID:0,
|
||||
Skus:[],
|
||||
},
|
||||
name:'',
|
||||
type:'price'
|
||||
})
|
||||
const stockOrCode = ref('')
|
||||
|
||||
// 打开dialog 修改库存以及货架码
|
||||
function openDialog(payload: AnyObject) {
|
||||
skuNameItem.value = payload
|
||||
const sku = payload.payload.Skus[0]
|
||||
if(payload.type === 'stock') stockOrCode.value = sku.stock + ''
|
||||
if(payload.type === 'locationCode') stockOrCode.value = sku.locationCode
|
||||
popupDialog.value.open()
|
||||
}
|
||||
async function sureStockOrCode() {
|
||||
const nameID = skuNameItem.value.payload.nameID
|
||||
const skuID = skuNameItem.value.payload.Skus[0].skuID
|
||||
let data:AnyObject = {
|
||||
storeIDs: JSON.stringify([+getStorage('storeID')])
|
||||
}
|
||||
if(skuNameItem.value.type === 'stock') {
|
||||
data.payload = JSON.stringify([{
|
||||
nameID: nameID,
|
||||
Skus:[
|
||||
{
|
||||
skuID: skuID,
|
||||
stock: +stockOrCode.value
|
||||
}
|
||||
]
|
||||
}])
|
||||
}else{
|
||||
data.payload = JSON.stringify([{
|
||||
nameID: nameID,
|
||||
Skus:[
|
||||
{
|
||||
skuID:skuID,
|
||||
locationCode: ''+ stockOrCode.value ? '' + stockOrCode.value : 'EMPTY_VALUE'
|
||||
}
|
||||
]
|
||||
}])
|
||||
}
|
||||
popupDialog.value.close() // 关闭 popupDialog
|
||||
let res = await shopping.update_stores_skus(data)
|
||||
if (res.code == 0) {
|
||||
let storeData = {
|
||||
storeIDs: JSON.stringify([+getStorage('storeID')]),
|
||||
isFocus: true,
|
||||
nameIDs: JSON.stringify([skuNameItem.value.payload.nameID]),
|
||||
fromStatus: 0,
|
||||
toStatus: 1,
|
||||
}
|
||||
const serverSkuName = await merchant.get_stores_skus(storeData)
|
||||
if (serverSkuName.code == 0) {
|
||||
let skuNameData = serverSkuName.data.skuNames || []
|
||||
if (skuNameData.length > 0) {
|
||||
let index = skuNames.value.findIndex((item: any) => item.id == skuNameItem.value.payload.nameID)
|
||||
if (index !== -1) {
|
||||
skuNames.value[index] = mapskuName(skuNameData)[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
toast('修改成功')
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 删除商品
|
||||
*/
|
||||
function handleDelete() {
|
||||
uni.jxConfirm({
|
||||
title: '提示',
|
||||
content: `确认删除《${skuName.value.name}》吗?`,
|
||||
confirmText: '确认',
|
||||
success: async () => {
|
||||
popup.value.close() // 关闭 popup
|
||||
let data = {
|
||||
storeIDs: JSON.stringify([getStorage('storeID')]),
|
||||
payload: JSON.stringify([{ nameID: skuName.value.id, isFocus: -1 }]),
|
||||
}
|
||||
let res = await shopping.update_stores_skus(data)
|
||||
if (res.code == 0) {
|
||||
toast('删除成功')
|
||||
skuNames.value = skuNames.value.filter((item) => item.id != skuName.value.id)
|
||||
if (skuNames.value.length == 0) return dataHoming()
|
||||
} else {
|
||||
toast('删除失败', 2)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const toExamineData = ref<AnyObject>({}) // 审核商品数据
|
||||
const toExaminePopup = ref<any>(null) // 审核弹窗实例
|
||||
const toExamineValue = ref<string | number>('') // 审核输入框
|
||||
/*************************************************
|
||||
* 审核商品
|
||||
*/
|
||||
function toExamine(res: AnyObject) {
|
||||
toExamineData.value = res
|
||||
if (res.status == 1) {
|
||||
toExamineValue.value = res.auditPrice / 100
|
||||
} else {
|
||||
toExamineValue.value = ''
|
||||
}
|
||||
toExaminePopup.value.open()
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* 改价审核操作
|
||||
*/
|
||||
async function toExamineConfirm() {
|
||||
toExaminePopup.value.close()
|
||||
let data = {
|
||||
status: toExamineData.value.status,
|
||||
isAsync: false,
|
||||
isContinueWhenError: true,
|
||||
payload: JSON.stringify([{
|
||||
storeID: toExamineData.value.storeID,
|
||||
nameID: toExamineData.value.nameID,
|
||||
...(toExamineData.value.status == 1
|
||||
? { auditPrice: Math.floor(+toExamineValue.value * 100) }
|
||||
: { remark: toExamineValue.value })
|
||||
}])
|
||||
}
|
||||
let res = await shopping.store_sku_price_audit(data)
|
||||
if (res.code == 0) {
|
||||
toast('操作成功')
|
||||
skuNames.value = skuNames.value.filter((item) => item.nameID != toExamineData.value.nameID)
|
||||
if (skuNames.value.length == 0) return dataHoming()
|
||||
} else {
|
||||
toast(res.desc || res.data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* 善后工作
|
||||
*/
|
||||
onBeforeUnmount(() => {
|
||||
clearTimeout(handleChangeSaleTimer)
|
||||
clearTimeout(updatePriceFnTimer)
|
||||
clearTimeout(onPullDownRefreshTimer)
|
||||
})
|
||||
|
||||
return {
|
||||
dafauleData, // 左侧tablist 数据
|
||||
totalCount, // 商品总条数
|
||||
skuNames, // 商品列表数据
|
||||
skuNameItem, // 商品数据2
|
||||
isAudit, // 商品列表判断条件
|
||||
isHot, // 商品列表判断条件
|
||||
showMountTab, // 批量操作判断
|
||||
scrolltolower, // 页面触底
|
||||
isLoad, // 加载动画
|
||||
updateIsSale, // 过滤筛选
|
||||
updateTowFilter, // 过滤筛选
|
||||
serachShopping, // 搜索框确定
|
||||
clearInpu, // 清空搜索框
|
||||
oneMenuClick, // 一级菜单点击事件
|
||||
isCheckoutFilter, // 切换过滤选项
|
||||
isFilter, // 判断条件
|
||||
handleSale, // 批量可售与不可售
|
||||
handleChangeSale, // 批量可售与不可售
|
||||
updateStateOk, // 批量操作成功
|
||||
createGoods, // 去创建商品
|
||||
isPointStore, // 判断扣点还是折扣
|
||||
skuName, // 当前修改的价格
|
||||
auditUnitPrice, // 正在审核的价格
|
||||
currentValue, // 当前修改价格
|
||||
popup, // 弹窗实例
|
||||
stockOrCode, // stock locationCode
|
||||
popupDialog, // 弹窗 stock locationCode
|
||||
handleConfirm, // 确定修改价格
|
||||
openPriceDialog, // 获取修改数据
|
||||
openDialog, // 获取修改数据2
|
||||
sureStockOrCode, // 确认框 stock locationCode
|
||||
handleDelete, // 删除商品
|
||||
refresherrefresh, // 下拉刷新
|
||||
triggered, // 下拉刷新标识
|
||||
leftBarRef, // 右侧导航栏实例
|
||||
statusBarHeight, // 状态栏高度
|
||||
toExamine, // 审核商品
|
||||
toExamineData, // 审核商品数据
|
||||
toExaminePopup, // 改价审核实例
|
||||
toExamineConfirm, // 确定操作审核
|
||||
toExamineValue, // 审核输入内容
|
||||
}
|
||||
}
|
||||
|
||||
export default shoppingMangerFn
|
||||
252
src/pages/goods-manager/main.vue
Normal file
252
src/pages/goods-manager/main.vue
Normal file
@@ -0,0 +1,252 @@
|
||||
<template>
|
||||
<view class="status_bar"></view>
|
||||
<view>
|
||||
<shopping-search
|
||||
class="shopping-cel"
|
||||
:isFilter="isFilter"
|
||||
@serachShopping="serachShopping"
|
||||
@clearInpu="clearInpu"
|
||||
@createGoods="createGoods"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="main-center-root">
|
||||
<view class="left-bar-root">
|
||||
<scroll-view
|
||||
scroll-y
|
||||
:style="{ height: `calc(100vh - 92rpx - ${statusBarHeight})` }"
|
||||
>
|
||||
<left-bar
|
||||
ref="leftBarRef"
|
||||
:dafauleData="dafauleData"
|
||||
@oneMenuClick="oneMenuClick"
|
||||
/>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="right-center">
|
||||
<shopping-filter
|
||||
@updateIsSale="updateIsSale"
|
||||
@updateTowFilter="updateTowFilter"
|
||||
:isCheckoutFilter="isCheckoutFilter"
|
||||
:updateStateOk="updateStateOk"
|
||||
/>
|
||||
|
||||
<scroll-view
|
||||
scroll-y
|
||||
:style="{ height: `calc(100vh - 182rpx - ${statusBarHeight})` }"
|
||||
refresher-enabled
|
||||
:refresher-triggered="triggered"
|
||||
@scrolltolower="scrolltolower"
|
||||
@refresherrefresh="refresherrefresh"
|
||||
>
|
||||
<right-main
|
||||
v-for="item in skuNames"
|
||||
:key="item.id"
|
||||
:skuName="item"
|
||||
:isAudit="isAudit"
|
||||
:isHot="isHot"
|
||||
:showMountTab="showMountTab"
|
||||
@handleSale="handleSale"
|
||||
@openPriceDialog="openPriceDialog"
|
||||
@openDialog="openDialog"
|
||||
@toExamine="toExamine"
|
||||
/>
|
||||
<jx-load-more
|
||||
v-show="totalCount >= 4"
|
||||
:isLoad="isLoad"
|
||||
tip="没有更多商品了"
|
||||
/>
|
||||
<jx-empty
|
||||
class="jx-empty"
|
||||
v-show="totalCount == 0"
|
||||
title="该分类暂无商品"
|
||||
>
|
||||
<view class="createGoods" @tap="createGoods">去创建商品</view>
|
||||
</jx-empty>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="showMountTab" class="MountWrap">
|
||||
<view class="btn onActive" @tap="handleChangeSale(1)">可售</view>
|
||||
<view class="btn onActive" @tap="handleChangeSale(-1)">不可售</view>
|
||||
</view>
|
||||
|
||||
<!-- 修改价格 -->
|
||||
<uni-popup ref="popup" type="top">
|
||||
<view class="status_bar"></view>
|
||||
<view class="jx-popup-update">
|
||||
<text class="text">{{ isPointStore ? '改价' : '提交改价审核' }}</text>
|
||||
<view class="tip">
|
||||
当前价格每<text style="color: #f60d58">{{
|
||||
skuName.unit === '份' ? '斤' : skuName.unit
|
||||
}}</text
|
||||
>:
|
||||
<jx-price :price="skuName.unitPrice" color="#4eb331" />
|
||||
</view>
|
||||
<view class="tip audit" v-if="auditUnitPrice > 0">
|
||||
正在审核:¥<text>{{ auditUnitPrice }}</text>
|
||||
</view>
|
||||
<input
|
||||
class="ipt"
|
||||
type="digit"
|
||||
v-model="currentValue"
|
||||
placeholder="请输入修改价格"
|
||||
/>
|
||||
|
||||
<view class="btn-root">
|
||||
<view class="btn-esc" @tap="popup.close()">取消</view>
|
||||
<view class="btn-ok" @tap="handleConfirm">确定修改</view>
|
||||
</view>
|
||||
|
||||
<view class="delete">
|
||||
<view class="delete-text" @tap="handleDelete"
|
||||
>删除《{{ skuName.name }}》</view
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 审核商品 -->
|
||||
<uni-popup ref="toExaminePopup" type="top">
|
||||
<view class="status_bar"></view>
|
||||
<view class="jx-popup-update">
|
||||
<text class="text">{{
|
||||
toExamineData.status == 1 ? '同意申请' : '拒绝申请'
|
||||
}}</text>
|
||||
<view class="tip audit"
|
||||
>商户申请价格:¥{{ toExamineData.auditPrice / 100 }}</view
|
||||
>
|
||||
<input
|
||||
class="ipt"
|
||||
type="digit"
|
||||
v-model="toExamineValue"
|
||||
:placeholder="
|
||||
toExamineData.status == 1 ? '请输入审核价格' : '请输入拒绝原因'
|
||||
"
|
||||
/>
|
||||
<view class="btn-root">
|
||||
<view class="btn-esc" @tap="toExaminePopup.close()">取消</view>
|
||||
<view class="btn-ok" @tap="toExamineConfirm">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
|
||||
<!-- 修改库存以及商品 -->
|
||||
<uni-popup ref="popupDialog" type="top">
|
||||
<view class="jx-popup-update" >
|
||||
<view class="text">
|
||||
{{ skuNameItem.type === 'stock' ? '修改库存' : '修改货架码' }}
|
||||
</view>
|
||||
<view class="tip-new">{{ skuNameItem.name }}</view>
|
||||
<view class="ipt-box">
|
||||
<input
|
||||
class="ipt"
|
||||
:type="skuNameItem.type === 'stock' ? 'number' : 'text'"
|
||||
v-model="stockOrCode"
|
||||
:placeholder="
|
||||
skuNameItem.type === 'stock' ? '请输入商品库存' : '请输入商品货架码'
|
||||
"
|
||||
/>
|
||||
</view>
|
||||
<view class="btn-root">
|
||||
<view class="btn-esc" @tap="popupDialog.close()">取消</view>
|
||||
<view class="btn-ok" @tap="sureStockOrCode">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 公共组件 -->
|
||||
<jx-loading />
|
||||
<jx-login-empty title="马上登录,管理商品" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import shoppingSearch from './childPages/shopping-search/shopping-search.vue'
|
||||
import leftBar from './component/left-bar/left-bar.vue'
|
||||
import rightMain from './childPages/right-main/right-main.vue'
|
||||
import shoppingFilter from './childPages/shopping-filter/shopping-filter.vue'
|
||||
import shoppingMangerFn from './main'
|
||||
const {
|
||||
dafauleData, // 左侧tablit数据
|
||||
totalCount, // 商品总条数
|
||||
skuNames, // 商品列表数据
|
||||
skuNameItem, // 商品数据2
|
||||
isAudit, // 商品列表判断条件
|
||||
isHot, // 商品列表判断条件
|
||||
showMountTab, // 批量操作判断
|
||||
scrolltolower, // 页面触底
|
||||
isLoad, // 加载动画
|
||||
updateIsSale, // 过滤筛选
|
||||
updateTowFilter, // 过滤筛选
|
||||
serachShopping, // 搜索框确定
|
||||
clearInpu, // 清空搜索框
|
||||
oneMenuClick, // 一级菜单点击事件
|
||||
isCheckoutFilter, // 切换过滤选项
|
||||
isFilter, // 判断条件
|
||||
handleSale, // 批量可售与不可售
|
||||
handleChangeSale, // 批量可售与不可售
|
||||
updateStateOk, // 批量操作成功
|
||||
createGoods, // 去创建商品
|
||||
isPointStore, // 判断扣点还是折扣
|
||||
skuName, // 当前修改的价格
|
||||
auditUnitPrice, // 正在审核的价格
|
||||
currentValue, // 当前修改价格
|
||||
popup, // 弹窗实例
|
||||
stockOrCode, // stock locationCode
|
||||
popupDialog, // 弹窗 stock locationCode
|
||||
handleConfirm, // 确定修改价格
|
||||
openPriceDialog, // 获取修改数据
|
||||
openDialog, // 获取修改数据2
|
||||
sureStockOrCode, // 确认框 stock locationCode
|
||||
handleDelete, // 删除商品
|
||||
refresherrefresh, // 下拉刷新
|
||||
triggered, // 下拉刷新标识
|
||||
leftBarRef, // 右侧导航栏实例
|
||||
statusBarHeight, // 状态栏高度
|
||||
toExamine, // 审核商品
|
||||
toExamineData, // 审核商品数据
|
||||
toExaminePopup, // 改价审核实例
|
||||
toExamineConfirm, // 确定操作审核
|
||||
toExamineValue, // 审核输入内容
|
||||
} = shoppingMangerFn()
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './main.scss';
|
||||
|
||||
.shopping-cel {
|
||||
:deep(.uni-searchbar) {
|
||||
padding: 0 !important;
|
||||
width: 610rpx !important;
|
||||
height: 70rpx;
|
||||
|
||||
.uni-searchbar__box {
|
||||
border-radius: 7rpx !important;
|
||||
height: auto !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.main-center-root {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.left-bar-root {
|
||||
width: 200rpx;
|
||||
box-shadow: 0rpx 10rpx 10rpx rgb(207, 207, 207);
|
||||
}
|
||||
|
||||
.right-center {
|
||||
width: calc(100vw - 200rpx);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user