代码更新

This commit is contained in:
GaoHao
2025-02-26 19:46:20 +08:00
parent 7519ffced3
commit b4a0393d2d
413 changed files with 7483 additions and 60762 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,125 +1,31 @@
<template>
<view class="u-relative choose-haocai">
<!-- <view class="input u-flex" @click="toggle" >
<up-input @blur="blur" @change="filterHaocaiList" border="none" v-model="text" placeholder="请选择"></up-input>
<up-icon :size="10" name="arrow-down-fill"></up-icon>
</view> -->
<view class="input u-flex" >
<view>{{text||''}}</view>
<!-- <up-input @blur="blur" disabled="true" @change="filterHaocaiList" border="none" v-model="text" placeholder="请选择"></up-input> -->
</view>
<view class="u-absolute" v-if="popShow">
<scroll-view scroll-y="true" class="scroll">
<view class="item" v-for="(item,index) in $haocaiList" :key="index" @click="haocaiClick(item,index)">
{{item.name}}
</view>
<view class="item no-wrap" @click="toggle" v-if="text&&!$haocaiList.length">没有该单位</view>
</scroll-view>
</view>
</view>
</template>
<script setup>
import {
reactive,
ref,
watch,
onMounted
} from 'vue';
import { reactive, ref, watch, onMounted } from 'vue';
const props = defineProps({
listMap: {
type: Object,
default: () => {}
},
list: {
type: Array,
default: () => []
},
modelValue: {
type: [String, Number],
default: ''
},
show: {
type: Boolean,
default: false
},
})
let text = ref('')
let popShow = ref(props.show)
const emits = defineEmits(['update:show', 'close', 'confirm', 'update:modelValue'])
function close() {
popShow.value = false
}
function confirm() {
popShow.value = false
}
watch(() => props.show, (newval) => {
popShow.value = newval
})
watch(() => popShow.value, (newval) => {
console.log(newval);
emits('update:show', newval)
})
let $haocaiList = ref(props.list)
watch(() => props.list, (newval) => {
$haocaiList.value = newval
setText()
})
watch(() => props.modelValue, (newval) => {
console.log(newval);
setText()
})
function setText() {
// const item = props.listMap[props.modelValue]
// text.value = item ? item.name : ''
text.value=props.modelValue
}
function toggle(e) {
popShow.value = !popShow.value
}
function filterHaocaiList(e) {
if (e === '') {
return $haocaiList.value = props.list
}
const arr = props.list.filter(v => v.name.match(e))
$haocaiList.value = arr
}
function haocaiClick(item, index) {
console.log(item);
// if (item.id != props.modelValue) {
// emits('update:modelValue', item.id)
// }
if(item.name!=props.modelValue){
emits('update:modelValue', item.name)
}
popShow.value = false
}
function focus(){
console.log('focus');
popShow.value = true
}
function blur() {
console.log('blur');
// setTimeout(()=>{
// popShow.value = false
// },100)
}
onMounted(() => {
setText()
})
function setText() {
text.value=props.modelValue
}
</script>
<style lang="scss" scoped>
@@ -137,27 +43,5 @@
border: 2rpx solid #E5E5E5;
overflow: hidden;
}
.u-absolute {
top: calc(100% + 10rpx);
border: 1px solid #E5E5E5;
left: 0;
background-color: #fff;
z-index: 10;
right: 0;
border-radius: 8rpx;
.scroll {
$line-h: 60rpx;
max-height: calc($line-h * 4);
.item {
line-height: $line-h;
padding: 0 20rpx;
}
}
}
}
</style>

View File

@@ -22,7 +22,7 @@
</view>
<scroll-view :scroll-x="false" scroll-y="true" :style="computedStyle()">
<scroll-view :scroll-x="true" :scroll-y="true" :style="computedStyle()">
<view class="u-p-l-30 u-p-r-30 table">
<view class="u-flex u-row-between no-wrap title">
<view>
@@ -31,8 +31,6 @@
</view>
<view>商品信息</view>
<view>规格</view>
<!-- <view>是否售尽</view> -->
<!-- <view>是否分销</view> -->
<view>售价</view>
<view>销量/库存</view>
<view>分类名称</view>
@@ -41,23 +39,19 @@
<view class="">
<my-radio @change="radioChange($event,item)" v-model="item.checked" shape="square" :size="20"></my-radio>
</view>
<view class="u-text-left u-flex-1 u-p-l-20">
<!-- <view class="u-flex">
<image lazy-load class="coverImg" :src="item.coverImg" mode=""></image>
</view> -->
<view class="u-text-left u-flex-1 u-p-l-20" style="flex-shrink: 0;">
<view class="">{{item.name}}</view>
</view>
<view class="u-flex-1 u-p-l-4 u-p-r-4 box-size-border">
{{item.typeEnum}}
{{isType(item.type)}}
</view>
<view class="u-flex-1">
{{ item.lowPrice }}
</view>
<view class="u-flex-1">
<!-- {{ item.realSalesNumber }}/{{ item.stockNumber }} -->
{{ item.stockNumber }}
{{ item.stockNumber }}
</view>
<view class="u-flex-1">
<view class="u-flex-1" style="text-overflow: ellipsis;overflow: hidden;word-break: break-all;white-space: nowrap;">
{{item.categoryName}}
</view>
</view>
@@ -80,15 +74,9 @@
</template>
<script setup>
import {
$tbProductList
} from '@/http/yskApi/goods.js';
import {
reactive,
onMounted,
ref,
watch
} from 'vue';
import { reactive, onMounted, ref, watch, computed } from 'vue';
import { getProductList} from '@/api/product.js';
const props = defineProps({
modelValue: {
type: Boolean,
@@ -105,6 +93,98 @@
}
}
})
const emits = defineEmits(['update:modelValue', 'confirm'])
const $quey = {
categoryId: "",
id: "",
name: "",
orderBy: "create_time desc",
page: 1,
size: 10,
}
const query = reactive({
...$quey
})
const goods = reactive({
list: [],
allChecked: false,
totalElements: 0,
query: {
...$quey
}
})
//页面全部数据
const pageData = reactive({
// 商品类型
types: [{
name: '单规格',
value: 'single'
},
{
name: '多规格',
value: 'sku'
},
{
name: '套餐',
value: 'package'
},
{
name: '称重',
value: 'weigh'
},
// {
// name: '团购券',
// value: 'coupon'
// },
],
})
function isType (e) {
let obj = pageData.types.find(item=> item.value == e)
return obj.name
}
getGoods()
/**
* 获取商品列表
*/
function getGoods() {
const arr=selArr
getProductList(goods.query).then(res => {
let selLen=0;
goods.list = res.records.map(v => {
const checked=$selGoodsMap[v.id]?true:false
selLen+=(checked?1:0)
return {
...v,
checked
}
})
goods.allChecked = selLen==res.records.length?true:false
goods.totalElements = res.totalRow
})
}
/**
* 单个商品选中
* @param {Object} newval
* @param {Object} item
*/
function radioChange(newval,item) {
if(!newval&&$selGoodsMap[item.id]){
delete $selGoodsMap[item.id]
}else{
$selGoodsMap[item.id]=item
}
goods.allChecked = goods.list.filter(v => v.checked).length != 0
}
/**
* 全选
* @param {Object} item
*/
function changeChecked(item){
item.checked=!item.checked
if(!item.checked&&$selGoodsMap[item.id]){
@@ -128,8 +208,7 @@
selArr=arr
console.log(arr);
for(let i in arr){
$selGoodsMap[arr[i].proId
]=arr[i]
$selGoodsMap[arr[i].proId]=arr[i]
}
getGoods()
}
@@ -150,60 +229,11 @@
return `height:${typeof props.height==='string'?props.height:props.height+'rpx'};`
}
const emits = defineEmits(['update:modelValue', 'confirm'])
const $quey = {
categoryId: "",
createdAt: [],
id: "",
name: "",
sort: "createdAt,desc",
type: "",
page: 0,
size: 10,
}
const query = reactive({
...$quey
})
const goods = reactive({
list: [],
allChecked: false,
totalElements: 0,
query: {
...$quey
}
})
getGoods()
function getGoods() {
const arr=selArr
$tbProductList(goods.query).then(res => {
let selLen=0;
goods.list = res.content.map(v => {
const checked=$selGoodsMap[v.id]?true:false
selLen+=(checked?1:0)
return {
...v,
checked
}
})
goods.allChecked = selLen==res.content.length?true:false
goods.totalElements = res.totalElements
})
}
function pageChange(page) {
goods.query.page = page - 1
goods.query.page = page
getGoods()
}
function radioChange(newval,item) {
if(!newval&&$selGoodsMap[item.id]){
delete $selGoodsMap[item.id]
}else{
$selGoodsMap[item.id]=item
}
goods.allChecked = goods.list.filter(v => v.checked).length != 0
}
function radioAllChange(newval) {
goods.list.forEach(i => {
@@ -223,7 +253,6 @@
delete $selGoodsMap[item.id]
}
}
console.log($selGoodsMap);
const arr = Object.values($selGoodsMap)
emits('confirm', arr)
}

View File

@@ -11,7 +11,7 @@
<view class="skd" v-for="(item,index) in skuList" :key="index"
:class="{active:sel.id==item.id}"
@click="guigeClick(item,index)">
<text>{{item.specSnap||item.name}}</text>
<text>{{item.specInfo||item.name}}</text>
<view class="tag-primary tag" v-if="item.isGrounding">上架中</view>
<view class="tag-gray tag" v-if="item.isPauseSale">已售罄</view>
<view class="tag-gray tag" v-if="!item.isGrounding">已下架</view>
@@ -35,15 +35,9 @@
</template>
<script setup>
import {
$tbProduct
} from '@/http/yskApi/goods.js';
import {
reactive,
onMounted,
ref,
watch
} from 'vue';
import { reactive, ref, watch } from 'vue';
import { $tbProduct } from '@/http/yskApi/goods.js';
import infoBox from '@/commons/utils/infoBox.js'
const props = defineProps({
modelValue: {

View File

@@ -1,57 +0,0 @@
<template>
<up-popup :round="10" :show="popShow" :closeable="true" @close="close">
<view class="u-text-center font-bold u-font-32 u-p-t-30">选择状态</view>
<view style="height: 20rpx;"></view>
<view class="u-p-30 all-list u-flex u-flex-wrap gap-20">
<view class="all-list-item" :class="{active:statusItemIndex==statusData.allListSel}" @click="changeAllListSel(statusItemIndex)" v-for="(statusItem,statusItemIndex) in statusData.allList" :key="statusItemIndex">
{{statusItem.label}}
</view>
</view>
<view class="u-flex u-p-t-30 u-p-b-30 u-p-l-20 u-p-r-20 gap-20">
<up-button @click="close">取消</up-button>
<up-button type="primary" @click="confirm">确定</up-button>
</view>
</up-popup>
</template>
<script setup>
import { ref, watch } from 'vue';
const props=defineProps({
show:{
type:Boolean,
default:false
}
})
let popShow=ref(props.show)
const emits=defineEmits(['update:show','close','confirm'])
function close(){
popShow.value=false
}
function confirm(){
popShow.value=false
}
watch(()=>props.show,(newval)=>{
popShow.value=newval
})
watch(()=>popShow.value,(newval)=>{
emits('update:show',newval)
})
</script>
<style lang="scss" scoped>
.all-list-item{
text-align: center;
width: 156rpx;
white-space: nowrap;
color: #666;
padding: 10rpx 20rpx;
border-radius: 8rpx;
transition: all .2s ease-in-out;
border: 1px solid #eee;
&.active {
color: $my-main-color;
border-color: $my-main-color;
}
}
</style>

View File

@@ -1,11 +1,7 @@
<template>
<view class="u-relative choose-haocai">
<view class="input u-flex" @click="toggle">
<!-- <view>
<text v-if="modelValue">{{modelValue}}</text>
<text v-else class="color-666">请选择</text>
</view> -->
<up-input @blur="blur" @change="filterHaocaiList" border="none" v-model="text" placeholder="请选择"></up-input>
<up-input @change="filterHaocaiList" border="none" v-model="text" placeholder="请选择"></up-input>
<up-icon :size="10" name="arrow-down-fill"></up-icon>
</view>
<view class="u-absolute" v-if="popShow">
@@ -21,12 +17,7 @@
</template>
<script setup>
import {
reactive,
ref,
watch,
onMounted
} from 'vue';
import { reactive, ref, watch, onMounted } from 'vue';
const props = defineProps({
listMap: {
type: Object,
@@ -48,15 +39,11 @@
})
let text = ref('')
let popShow = ref(props.show)
const emits = defineEmits(['update:show', 'close', 'confirm', 'update:modelValue','change'])
const emits = defineEmits(['update:show', 'update:modelValue','change'])
onMounted(() => {
setText()
})
function close() {
popShow.value = false
}
function confirm() {
popShow.value = false
}
watch(() => props.show, (newval) => {
popShow.value = newval
})
@@ -81,6 +68,10 @@
popShow.value = !popShow.value
}
/**
* 耗材选择监听
* @param {Object} e
*/
function filterHaocaiList(e) {
if (e === '') {
return $haocaiList.value = props.list
@@ -88,9 +79,13 @@
const arr = props.list.filter(v => v.conName.match(e))
$haocaiList.value = arr
}
/**
* 耗材选择确认
* @param {Object} item
* @param {Object} index
*/
function haocaiClick(item, index) {
console.log(item);
if (item.id != props.modelValue) {
emits('update:modelValue', item.id)
emits('change', item)
@@ -98,14 +93,7 @@
popShow.value = false
}
function blur() {
// setTimeout(()=>{
// popShow.value = false
// },100)
}
onMounted(() => {
setText()
})
</script>
<style lang="scss" scoped>

View File

@@ -3,24 +3,22 @@
<view class="default-box-padding bg-fff border-r-18">
<view class="u-flex u-row-between">
<view>商品名称</view>
<!-- <template v-if="isSku"> -->
<view class="u-flex u-font-24 color-666">
<view class="u-m-r-20">绑定至规格</view>
<view class="u-flex u-relative">
<up-switch :size="18" v-model="isBindGuige" :disabled="!isSku">绑定至规格</up-switch>
<up-switch :size="18" v-model="pageData.isBindGuige" :disabled="!isSku">绑定至规格</up-switch>
<view class="u-absolute position-all" style="z-index: 1;" v-if="!isSku"
@click="infoBox.showToast('该商品是单规格商品,只有多规格商品可绑定至规格',3)"></view>
@click="infoBox.showToast('只有单规格或者多规格商品可绑定至规格',3)"></view>
</view>
</view>
<!-- </template> -->
</view>
<view class="border-bottom u-m-t-16 u-p-b-32">{{goods.name}}</view>
<view class="border-bottom u-m-t-16 u-p-b-32">{{skuList.length}}{{goods.name}}</view>
<view class="">
<template v-if="isBindGuige&&isSku">
<template v-if="pageData.isBindGuige&&isSku">
<view class="list">
<view class="u-p-b-32 u-p-t-32 border-bottom" v-for="(sku,index) in skuList" :key="index">
<view>规格名称</view>
<view class="u-m-t-16">{{sku.specSnap}}</view>
<view class="u-m-t-16">{{sku.specInfo}}</view>
<view class="color-666 u-m-t-24 u-flex">
<view class="xuhao">序号</view>
<view class="u-flex u-flex-1 u-p-l-32 gap-20">
@@ -37,7 +35,7 @@
<view class="u-flex-1 ">
<choose-haocai @change="conInfosChange($event,item)"
:listMap="$haocaiMap" :list="haoCaiList"
v-model="item.conInfoId"></choose-haocai>
v-model="item.consInfoId"></choose-haocai>
</view>
<view class="u-flex-1 ">
<choose-danwei :listMap="$danweiMap" :list="danweiList"
@@ -88,19 +86,10 @@
<view class="u-flex u-flex-1 u-p-l-32 gap-20">
<view class="u-flex-1 ">
<choose-haocai @change="conInfosChange($event,item)" :listMap="$haocaiMap"
:list="haoCaiList" v-model="item.conInfoId"></choose-haocai>
<!-- <view class="u-flex input">
<view>{{item.conName}}</view>
<up-icon :size="10" name="arrow-down-fill"></up-icon>
</view> -->
:list="haoCaiList" v-model="item.consInfoId"></choose-haocai>
</view>
<view class="u-flex-1 ">
<choose-danwei :listMap="$danweiMap" :list="danweiList"
v-model="item.conUnit"></choose-danwei>
<!-- <view class="u-flex input">
<view>{{item.conUnit}}</view>
<up-icon :size="10" name="arrow-down-fill"></up-icon>
</view> -->
<choose-danwei v-model="item.conUnit"></choose-danwei>
</view>
<view class="u-flex-1 ">
<view class="u-flex input">
@@ -124,7 +113,7 @@
</view>
</view>
</template>
<template v-if="!isBindGuige">
<template v-if="!pageData.isBindGuige">
<view class="u-flex">
<view class=" u-p-t-32 u-flex" @click="addHaocai">
<up-icon :size="18" color="#318AFE" name="plus-circle-fill"></up-icon>
@@ -139,9 +128,7 @@
<view class="default-box-padding bg-fff border-r-18 u-flex u-row-between u-m-t-32">
<view>当某个耗材的使用库存不足时商品自动
售罄</view>
<!-- <view class="u-flex u-p-l-32">
<up-switch :size="20"></up-switch>
</view> -->
</view>
<view class="bottom">
<my-button type="primary" shape="circle" font-weight="700" @click="save">保存</my-button>
@@ -153,46 +140,19 @@
</template>
<script setup>
import {
ref,
reactive,
toRefs,
watch,
computed,
onMounted
}
from 'vue';
import {
getviewConSku,
gettbProductSpec,
gettbConsInfo,
posttbProskuCons,
puttbProskuCon,
deletetbProskuCon,
} from "@/http/yskApi/consumable.js";
import {
tbShopCurrencyGet,
$hasPermission
} from '@/http/yskApi/shop.js'
import { ref, reactive, watch, computed, onMounted } from 'vue';
import { deletetbProskuCon, } from "@/http/yskApi/consumable.js";
import infoBox from '@/commons/utils/infoBox.js'
import chooseHaocai from './choose-haocai.vue';
import chooseDanwei from './choose-danwei.vue';
import {
$tbProskuConV2
} from '@/http/yskApi/goods.js'
import {
cloneWith
} from 'lodash';
import {
hasPermission
} from '@/commons/utils/hasPermission.js';
import { hasPermission } from '@/commons/utils/hasPermission.js';
import { getConsList } from '@/api/cons.js';
import { productBind } from '@/api/product.js';
const emits = defineEmits(['cancel', 'updateGoods'])
function cancel() {
emits('cancel')
}
const props = defineProps({
goods: {
type: Object,
@@ -205,56 +165,108 @@
}
}
})
const conInfos = ref(props.goods.conInfos)
const pageData = reactive({
isBindGuige: false, //是否绑定至规格
})
let haoCaiList = ref([])
let $haocaiMap = reactive({})
const skuList = ref(props.goods.skuList)
const conInfos = ref(props.goods.conInfos||[])
watch(() => props.goods.conInfos, (newval) => {
console.log(newval);
conInfos.value = newval
})
watch(() => props.goods.skuList, (newval) => {
skuList.value = newval
})
watch(() => props.goods.type, (newval) => {
if(!newval){
pageData.isBindGuige = false
}
})
onMounted(() => {
init()
if(props.goods.conInfos){
const firstItem= props.goods.conInfos[0]
pageData.isBindGuige = firstItem?(firstItem.productSkuId==0?false:true):false
}
})
function init() {
console.log(skuList)
getConsList({
"status": 1,
}).then(res => {
for (let i in res) {
const item = res[i]
$haocaiMap[item.id] = item
}
haoCaiList.value = res
})
}
/**
* 取消耗材绑定
*/
function cancel() {
emits('cancel')
}
/**
* 耗材选择
* @param {Object} newval
* @param {Object} item
*/
function conInfosChange(newval, item) {
console.log(newval);
item.stockNumber = newval.balance
item.conUnit = newval.conUnit
}
const skuList = ref(props.goods.skuList)
watch(() => props.goods.skuList, (newval) => {
console.log(newval);
skuList.value = newval
})
const $baseicHaocaiData = {
conInfoId: '',
consInfoId: '',
conUnit: '',
surplusStock: ''
}
/**
* 添加商品耗材
*/
function addHaocai() {
conInfos.value.push({
...$baseicHaocaiData
})
}
const popup = reactive({
haocai: {
show: true
}
})
/**
* 添加规格耗材
* @param {Object} index
*/
function addGuigeHaocai(index) {
console.log(skuList.value[index])
if (skuList.value[index].haoCaiList) {
skuList.value[index].haoCaiList.push({
...$baseicHaocaiData
})
} else {
skuList.value[index].haoCaiList = [{
skuList.value[index]['haoCaiList'] = [{
...$baseicHaocaiData
}]
}
console.log(skuList.value[index]);
}
/**
* 删除商品耗材
* @param {Object} index
*/
function delHaocai(index) {
const item = conInfos.value[index]
console.log(item);
@@ -276,7 +288,12 @@
})
}
/**
* 删除规格耗材
* @param {Object} guigeIndex
* @param {Object} haocaiIndex
*/
function delGuigeHaocao(guigeIndex, haocaiIndex) {
const item = skuList.value[guigeIndex].haoCaiList[haocaiIndex]
console.log(item);
@@ -298,19 +315,16 @@
})
}
// 是否是多规格商品
/**
* 是否是多规格商品
*/
const isSku = computed(() => {
return props.goods.typeEnum == 'sku'
return props.goods.type == 'sku'||props.goods.type == 'single'
})
let isBindGuige = ref(false)
watch(() => props.goods.typeEnum, (newval) => {
if(!newval){
isBindGuige.value = false
}
})
/**
* 保存
*/
async function save() {
const bol = await hasPermission('允许修改商品')
if (!bol) {
@@ -318,17 +332,16 @@
}
console.log('save');
let isPas = false
if (!isBindGuige.value) {
if (!pageData.isBindGuige) {
//绑定至商品
isPas = conInfos.value.every(v => {
return v.conInfoId && v.conUnit && v.surplusStock > 0
return v.consInfoId && v.conUnit && v.surplusStock > 0
})
} else {
//绑定至规格
isPas = skuList.value.filter(v => v.haoCaiList && v.haoCaiList.length).every(sku => {
console.log(sku.haoCaiList);
return sku.haoCaiList.every(v => {
return v.conInfoId && v.conUnit && v.surplusStock > 0
return v.consInfoId && v.conUnit && v.surplusStock > 0
})
})
}
@@ -337,20 +350,17 @@
return infoBox.showToast('请填写全部耗材选项值')
}
let ajaxData = {
productId: props.goods.id,
cons: []
id: props.goods.id,
consList: []
}
if (!isBindGuige.value) {
if (!pageData.isBindGuige) {
//绑定至商品
ajaxData.cons = conInfos.value.map(v => {
ajaxData.consList = conInfos.value.map(v => {
return {
id: v.id || '',
conInfoId: v.conInfoId,
consInfoId: v.consInfoId,
productId: props.goods.id,
shopId: uni.getStorageSync('shopId'),
productSkuId: 0,
surplusStock: v.surplusStock * 1,
status: 1
}
})
} else {
@@ -358,56 +368,22 @@
const haocaiList = skuList.value[i].haoCaiList || []
for (let k in haocaiList) {
const v = haocaiList[k]
ajaxData.cons.push({
ajaxData.consList.push({
id: v.id || '',
conInfoId: v.conInfoId,
consInfoId: v.consInfoId,
productId: props.goods.id,
shopId: uni.getStorageSync('shopId'),
productSkuId: skuList.value[i].id,
surplusStock: v.surplusStock * 1,
status: 1
})
}
}
}
console.log(ajaxData);
await $tbProskuConV2(ajaxData)
await productBind(ajaxData)
emits('updateGoods')
infoBox.showToast('修改成功')
}
let haoCaiList = ref([])
let $haocaiMap = reactive({})
let danweiList = ref([])
let $danweiMap = reactive({})
function init() {
gettbConsInfo({
"status": 1,
}).then(res => {
for (let i in res.content) {
const item = res.content[i]
$haocaiMap[item.id] = item
}
haoCaiList.value = res.content
})
tbShopCurrencyGet({
page: 0,
size: 200
}).then(res => {
for (let i in res.content) {
const item = res.content[i]
$danweiMap[item.id] = item
}
danweiList.value = res.content
})
}
onMounted(() => {
init()
const firstItem= props.goods.conInfos[0]
isBindGuige.value=firstItem?(firstItem.productSkuId==0?false:true):false
})
</script>
<style lang="scss" scoped>

View File

@@ -1,224 +0,0 @@
<template>
<view class="u-p-30 min-page u-font-28">
<!-- <view class="u-flex">
<view style="width: 210rpx;">
<my-button shape="circle" @click="addTimer">添加定时器</my-button>
</view>
</view> -->
<view class="list u-m-t-20" v-if="list.length">
<view class="block" v-for="(item,index) in list" :key="index">
<!-- <view class="u-flex u-row-between">
<view>定时器{{index+1}}</view>
<uni-icons @click="delTimer(index)" type="trash"></uni-icons>
</view> -->
<view class="u-flex u-row-between">
<view>周期</view>
<view class="color-main" @click="selectAllClick(index)">
{{isAllChecked?'取消全选':'全选'}}
</view>
</view>
<view class="u-m-t-24">
<uni-data-checkbox :selectedColor="color.ColorMain" multiple v-model="item.cycleChecked" :localdata="cycle"></uni-data-checkbox>
</view>
<view class="u-m-t-24">
<view class="u-flex">
<view>上架时间:</view>
<view class="u-flex-1 u-m-l-10">
<picker mode="multiSelector" @change="listingTimeChange($event,index)"
:value="item.listingTime.index" :range="times">
<view class="bg-gray u-p-l-20 u-p-t-6 u-p-b-6 u-p-r-20 ">
{{item.listingTime.value}}
</view>
</picker>
</view>
</view>
<view class="u-flex u-m-t-16">
<view>下架时间:</view>
<view class="u-flex-1 u-m-l-10">
<picker mode="multiSelector" @change="offShelfChange($event,index)"
:value="item.offShelf.index" :range="times">
<view class="bg-gray u-p-l-20 u-p-t-6 u-p-b-6 u-p-r-20 ">
{{item.offShelf.value}}
</view>
</picker>
</view>
</view>
</view>
</view>
</view>
<view class="u-flex u-row-center u-m-t-60">
<my-button width="580" shape="circle" @click="save">保存</my-button>
</view>
</view>
</template>
<script setup>
import {
onLoad,
onReady
} from '@dcloudio/uni-app';
import {
computed,
ref
} from 'vue';
import go from '@/commons/utils/go.js';
import color from '@/commons/color.js'
import {
$getProductDetail,
} from '@/http/yskApi/goods.js'
//返回一天的时间 时分格式
function returnDayTime() {
return new Array(2).fill(1).map((v, index) => {
if (index === 0) {
return new Array(24).fill(1).map((hour, index) => {
return `0${index}`.slice(-2)
})
}
if (index === 1) {
return new Array(60).fill(1).map((hour, index) => {
return `0${index}`.slice(-2)
})
}
})
}
const times = ref(returnDayTime())
let defaultTimeIndex = ref(0)
function getTime(indexArr) {
const hour = times.value[0][indexArr[0]]
const month = times.value[1][indexArr[1]]
return `${hour}:${month}`
}
//获取$event.detail.value
function getEnentDetailValue(e) {
return e.detail.value
}
function setListTimeValue(index, key, time) {
list.value[index][key].value = time
}
function listingTimeChange(e, index) {
const indexArr = getEnentDetailValue(e)
const time = getTime(indexArr)
setListTimeValue(index, 'listingTime', time)
}
function offShelfChange(e, index) {
const indexArr = getEnentDetailValue(e)
const time = getTime(indexArr)
setListTimeValue(index, 'offShelf', time)
}
const cycle = [{
value: 0,
text: '星期一'
},
{
value: 1,
text: '星期二'
},
{
value: 2,
text: '星期三'
},
{
value: 3,
text: '星期四'
},
{
value: 4,
text: '星期五'
},
{
value: 5,
text: '星期六'
},
{
value: 6,
text: '星期日'
}
]
const ListDataconstructor = {
cycleChecked: [0, 1, 2, 3, 4, 5, 6],
}
function returnBasicTimeConstructor() {
return {
listingTime: {
value: '00:00',
index: [0, 0]
},
offShelf: {
value: '00:00',
index: [0, 0]
}
}
}
const list = ref([returnBasicDataConstructor()])
function returnBasicDataConstructor() {
return {
...ListDataconstructor,
...returnBasicTimeConstructor()
}
}
function addTimer() {
list.value.push(returnBasicDataConstructor())
}
function delTimer(index) {
list.value.splice(index,1)
}
const isAllChecked=computed(()=>{
return list.value[0].cycleChecked.length==cycle.length?true:false
})
function selectAllClick(index){
if(isAllChecked.value){
list.value[index].cycleChecked=[]
}else{
list.value[index].cycleChecked=ListDataconstructor.cycleChecked
}
}
// 触发定时器保存事件将数据给到添加商品页面
function emitTimerSave(){
uni.$emit('timerSave',list.value)
go.back()
}
function save(){
console.log(list.value);
emitTimerSave()
}
let goodsDetail=ref({})
function returnTimer(res){
return []
}
onLoad(async(opt)=>{
let res=null
if(opt.productId){
res=await $getProductDetail(opt.productId)
goodsDetail.value=res
}
const arr=res?returnTimer(res):[]
if(arr.length){
list.value=arr
}
})
</script>
<style lang="scss">
.min-page {
background-color: #F9F9F9;
}
.block {
background: #FFFFFF;
border-radius: 18rpx 18rpx 18rpx 18rpx;
padding: 32rpx 28rpx;
margin-bottom: 32rpx;
}
</style>

View File

@@ -1,16 +1,7 @@
<template>
<view class="u-p-30 min-page u-font-28">
<!-- <view class="u-flex">
<view style="width: 210rpx;">
<my-button shape="circle" @click="addTimer">添加定时器</my-button>
</view>
</view> -->
<view class="list u-m-t-20" v-if="list.length">
<view class="block" v-for="(item,index) in list" :key="index">
<!-- <view class="u-flex u-row-between">
<view>定时器{{index+1}}</view>
<uni-icons @click="delTimer(index)" type="trash"></uni-icons>
</view> -->
<view class="u-flex u-row-between">
<view>周期</view>
<view class="color-main" @click="selectAllClick(index)">
@@ -193,8 +184,8 @@
function emitTimerSave() {
const par = {
days: list.value[0].cycleChecked.join(','),
startTime: list.value[0].startTime.value,
endTime: list.value[0].endTime.value
startTime: list.value[0].startTime.value+':00',
endTime: list.value[0].endTime.value+':00'
}
console.log(par);
uni.$emit('timerSave', par)

View File

@@ -1,499 +0,0 @@
<template>
<view class="page">
<view class="box">
<view class="block border-top-0">
<uni-forms ref="nameFormRef" :model="specifications" :rules="rules" :label-width="350"
label-position="top" validateTrigger="blur">
<uni-forms-item label="模版名称" required name="name">
<uni-easyinput :placeholderStyle="placeholderStyle" :inputBorder="inputBorder"
v-model="specifications.name" placeholder="模版名称,如:衣服" />
</uni-forms-item>
</uni-forms>
</view>
<view v-for="(item,index) in specifications.list" :key="index">
<uni-forms :model="item" :rules="rules" err-show-type="undertext" validateTrigger="blur"
:ref="setFormRef(index)" :border="true" label-position="top" label-width="350">
<view class="block">
<view class="border-top-0">
<uni-forms-item label="规格组名" required name="name">
<uni-easyinput :placeholderStyle="placeholderStyle" :inputBorder="inputBorder"
v-model="item.name" placeholder="规格组名,如:尺码" />
</uni-forms-item>
</view>
<uni-forms-item label="规格值">
<view class="option">
<view class="">
<view class="u-flex option-item" v-for="(option,optionIndex) in item.options"
:key="optionIndex">
<view class="u-flex-1">
<uni-forms-item :key="optionIndex" :name="['options',optionIndex,'name']"
:ref="setFormInputRef(index,optionIndex)"
:rules="[{'required': true,errorMessage: '必填'}]" label-width="0"
label="" required :showRequired="false">
<uni-easyinput
v-model="specifications.list[index].options[optionIndex].name"
@input="inpuChange(index,optionIndex)"
:placeholderStyle="placeholderStyle" :inputBorder="inputBorder"
placeholder="请输入规格值,如:S、M" />
</uni-forms-item>
</view>
<view class=" u-flex">
<uni-forms-item :key="optionIndex" label-width="0" label=""
:showRequired="false">
<view class="u-flex">
<!-- <uni-easyinput v-model="specifications.list[index].options[optionIndex].optionPrice"
@input="inpuChange(index,optionIndex)"
:placeholderStyle="placeholderStyle" :inputBorder="inputBorder"
type="digit" placeholder="填写价格" /> -->
<view class="icon icon-reduce u-m-l-38"
@click="delOption(index,optionIndex)">
</view>
</view>
</uni-forms-item>
</view>
</view>
</view>
<view class="u-flex" @click="addOptions(index)">
<view class="icon icon-add u-m-r-22 ">
</view>
<view class="color-main">添加规格</view>
</view>
</view>
</uni-forms-item>
<view class="u-flex u-m-t-48 u-m-b-24" @click="delSpecificationsGroup(index)">
<view class="icon icon-reduce u-m-r-22 ">
</view>
<view class="color-red">删除规格组</view>
</view>
</view>
</uni-forms>
</view>
<view class="u-flex block u-p-l-20 u-p-r-20 u-p-t-28 u-p-b-28" @click="addSpecificationsGroup">
<view class="icon icon-add u-m-r-22 ">
</view>
<view class="color-main">添加规格组</view>
</view>
<view class="save-btn-box">
<button class="save-btn" hover-class="btn-hover-class" @click="save">保存</button>
</view>
</view>
<view class="bottom" ref="bottom"></view>
</view>
</template>
<script setup>
import go from '@/commons/utils/go.js';
import {
$productSpec
} from '@/http/yskApi/goods.js'
import {
onLoad,
onReady,
} from '@dcloudio/uni-app';
import infoBox from '@/commons/utils/infoBox.js'
import {
onMounted,
reactive,
nextTick,
ref,
onBeforeMount
} from 'vue';
const nameFormRef = ref(null)
// 表单样式
const placeholderStyle = ref('font-size:28rpx;')
//表单边框
const inputBorder = ref(false)
const form = ref(null)
const bottom = ref(null)
//表单验证
const rules = {
name: {
rules: [{
required: true,
errorMessage: '必填'
}]
},
MinOptional: {
rules: [{
required: true,
errorMessage: '必填'
}]
},
MaxOptional: {
rules: [{
required: true,
errorMessage: '必填'
}]
},
optionPrice: {
rules: [{
required: true,
errorMessage: '必填'
}]
}
}
// 构造规格的选项值的基础数据
const specificationsOptionsBasicData = {
name: '',
optionPrice: '0.00'
}
function returnOptionsBasicData() {
return {
...specificationsOptionsBasicData
}
}
// 构造规格的基础数据
const specificationsBasicData = {
name: '',
// MinOptional: 1,
// MaxOptional: 1,
options: []
}
function returnSpecificationsOptionsBasicData() {
return {
...specificationsBasicData,
options: [returnOptionsBasicData()]
}
}
function onFieldChange(e) {
console.log(e);
}
// 规格列表
const specifications = reactive({
name: '',
list: [returnSpecificationsOptionsBasicData()]
})
//添加规格组
function addSpecificationsGroup() {
specifications.list.push(returnSpecificationsOptionsBasicData())
scrollPageBottom()
}
//删除规格组
function delSpecificationsGroup(index) {
specifications.list.splice(index, 1)
}
// 向指定索引的规格组添加规格项
function addOptions(index) {
specifications.list[index].options.push(returnOptionsBasicData())
}
// 删除指定索引的规格组添加规格项
function delOption(index, optionIndex) {
specifications.list[index].options.splice(optionIndex, 1)
}
//页面滚动到最底部
function scrollPageBottom() {
nextTick(() => {
uni.pageScrollTo({
duration: 100, // 过渡时间
scrollTop: 100000, // 滚动的实际距离
})
})
}
//设置表单验证规则
function setFormRules() {
form.value.setRules(rules)
}
const formRefs = ref([]);
//绑定表单元素
function setFormRef(index) {
formRefs.value[index] = null;
return (el) => {
if (el) {
formRefs.value[index] = el;
}
};
}
// 绑定option input元素
const refFormInput = ref([])
function setFormInputRef(index, index1) {
const newIndex = index * 10000 + index1
return (el) => {
if (el) {
if (!refFormInput.value[newIndex]) {
refFormInput.value[newIndex] = el;
}
}
}
}
// 当表单内容输入变化根据配置的rules进行验证
function inpuChange(index, index1) {
const newIndex = index * 10000 + index1
console.log(refFormInput.value[newIndex]);
refFormInput.value[newIndex].onFieldChange()
}
const option = {
type: 'add',
id: undefined
}
onLoad(opt => {
console.log(opt);
if (opt && JSON.stringify(opt) !== '{}' && opt.type) {
option.type = opt.type
const data = uni.getStorageSync('spec')
uni.removeStorageSync('spec')
if(data){
specifications.name = data.name
specifications.id = data.id
specifications.list = data.specList.map(v => {
return {
...v,
options: v.value.map(v => {
return {
name: v
}
})
}
})
}
}
uni.setNavigationBarTitle({
title: option.type === 'edit' ? '编辑规格模版' : '添加规格模版'
})
})
function returnPromise(prosise, index) {
return new Promise((resolve, reject) => {
prosise.then(res => {
console.log(res);
resolve({
sucees: true
})
}).catch(err => {
console.log(err);
resolve({
sucees: false
})
})
})
}
let timer = null
function settimeoutBack(time) {
clearTimeout(timer)
timer = setTimeout(() => {
uni.navigateBack()
}, time)
}
async function save() {
let isAllPassForm = 0
const nameFormRes = await returnPromise(nameFormRef.value.validate())
console.log(nameFormRes);
if (!nameFormRes.sucees) {
isAllPassForm -= 1
}
for (let i in specifications.list) {
const res = await returnPromise(formRefs.value[i].validate(), i)
isAllPassForm += res.sucees ? 1 : 0
}
//判断验证是否通过
if (isAllPassForm === specifications.list.length) {
console.log('pass');
const data = {
name: specifications.name,
id:specifications.id,
specList: specifications.list.map(v => {
return {
...v,
value: v.options.map(v => v.name),
options: undefined
}
})
}
if (option.type === 'add') {
return $productSpec.add(data).then(res => {
infoBox.showSuccessToast('添加成功')
settimeoutBack(1500)
})
}
$productSpec.update(data).then(res => {
infoBox.showSuccessToast('修改成功')
settimeoutBack(1500)
})
}
}
</script>
<style scoped>
page {
background: #F9F9F9;
}
</style>
<style lang="scss" scoped>
$icon-size: 34rpx;
$icon-line-width: 20rpx;
$icon-line-height: 4rpx;
.page {
background: #F9F9F9;
padding: 30rpx;
padding-bottom: 200rpx;
}
.my-switch {
transform: scale(0.7);
}
::v-deep .uni-forms-item__error {
display: none !important;
}
::v-deep .option .uni-forms-item {
padding: 0;
min-height: inherit;
background-color: transparent;
border-top: none;
}
.icon {
width: $icon-size;
height: $icon-size;
position: relative;
border-radius: 50%;
&:before,
&::after {
position: absolute;
display: block;
content: '';
background-color: #fff;
}
}
.icon-add {
background-color: $my-main-color;
&::before {
width: $icon-line-height;
height: $icon-line-width;
top: calc(($icon-size /2) - ($icon-line-width / 2));
left: calc(($icon-size /2) - ($icon-line-height / 2));
}
&::after {
width: $icon-line-width;
height: 4rpx;
top: calc(($icon-size /2) - ($icon-line-height / 2));
left: calc(($icon-size /2) - ($icon-line-width / 2));
}
}
.icon-reduce {
background-color: $my-red-color;
&::after {
width: $icon-line-width;
height: $icon-line-height;
top: calc(($icon-size /2) - ($icon-line-height / 2));
left: calc(($icon-size /2) - ($icon-line-width / 2));
}
}
.label-title {
font-size: 28rpx;
font-weight: bold;
font-family: Source Han Sans CN, Source Han Sans CN;
}
.lh40 {
line-height: 40rpx;
}
.box {
margin-top: 70rpx;
font-size: 28rpx;
.block {
background: #FFFFFF;
border-radius: 18rpx 18rpx 18rpx 18rpx;
padding: 12rpx 24rpx;
margin-bottom: 32rpx;
}
}
.save-btn-box {
position: fixed;
left: 30rpx;
right: 30rpx;
bottom: 60rpx;
}
::v-deep.uni-forms-item {
align-items: inherit;
}
::v-deep .uni-forms-item .uni-forms-item__label {
text-indent: 0;
font-size: 28rpx !important;
font-weight: bold;
color: #333;
}
::v-deep .border-top-0 .uni-forms-item.is-direction-top {
border-color: transparent !important;
}
.save-btn {
background-color: $my-main-color;
color: #fff;
border-radius: 12rpx;
font-size: 28rpx;
}
.btn-hover-class {
opacity: .6;
}
.zuofa {
padding: 28rpx 0;
background: #F9F9F9;
padding-left: 42rpx;
border-radius: 14rpx 14rpx 14rpx 14rpx;
}
::v-deep .uni-input-placeholder {
font-size: 28rpx;
}
.option {
padding: 26rpx 30rpx 24rpx 24rpx;
background: #F9F9F9;
}
.option-item {
margin-bottom: 34rpx;
}
</style>

View File

@@ -1,464 +0,0 @@
<template>
<view class="page">
<view class="box">
<view v-for="(item,index) in specifications.list" :key="index">
<uni-forms :model="item" :rules="rules" err-show-type="undertext" validateTrigger="blur"
:ref="setFormRef(index)" :border="true" label-position="top" label-width="350">
<view class="block">
<view class="border-top-0">
<uni-forms-item label="规格组名" required name="name" >
<uni-easyinput :placeholderStyle="placeholderStyle" :inputBorder="inputBorder"
v-model="item.name" placeholder="规格组名" />
</uni-forms-item>
</view>
<!-- <uni-forms-item label="最少可选" required name="MinOptional" >
<uni-easyinput :placeholderStyle="placeholderStyle" :inputBorder="inputBorder"
v-model="item.MinOptional" type="number" placeholder="填写最小数量" />
</uni-forms-item>
<uni-forms-item label="最大可选" required name="MaxOptional" >
<uni-easyinput :placeholderStyle="placeholderStyle" :inputBorder="inputBorder"
v-model="item.MaxOptional" type="number" placeholder="填写最大数量" />
</uni-forms-item> -->
<uni-forms-item label="选项值">
<view class="option">
<view class="u-flex">
<view class="u-flex-1">名称</view>
<view class="u-flex-1 u-p-l-60">加价</view>
</view>
<view class="u-m-t-32">
<view class="u-flex option-item"
v-for="(option,optionIndex) in item.options"
:key="optionIndex"
>
<view class="u-flex-1">
<uni-forms-item :key="optionIndex" :name="['options',optionIndex,'optionName']"
:ref="setFormInputRef(index,optionIndex)"
:rules="[{'required': true,errorMessage: '必填'}]"
label-width="0" label="" required :showRequired="false"
>
<uni-easyinput v-model="specifications.list[index].options[optionIndex].optionName"
@input="inpuChange(index,optionIndex)"
:placeholderStyle="placeholderStyle" :inputBorder="inputBorder"
placeholder="选项名" />
</uni-forms-item>
</view>
<view class="u-p-l-60 u-flex-1 u-flex">
<uni-forms-item :key="optionIndex"
:rules="[{'required': true,errorMessage: '必填'}]"
:ref="setFormInputRef(index,optionIndex)"
:name="['options',optionIndex,'optionPrice']" label-width="0" label="" required :showRequired="false"
>
<view class="u-flex">
<uni-easyinput v-model="specifications.list[index].options[optionIndex].optionPrice"
@input="inpuChange(index,optionIndex)"
:placeholderStyle="placeholderStyle" :inputBorder="inputBorder"
type="digit" placeholder="填写价格" />
<view class="icon icon-reduce u-m-l-38"
@click="delOption(index,optionIndex)">
</view>
</view>
</uni-forms-item>
</view>
</view>
</view>
<view class="u-flex" @click="addOptions(index)">
<view class="icon icon-add u-m-r-22 ">
</view>
<view class="color-main">添加规格</view>
</view>
</view>
</uni-forms-item>
<view class="u-flex u-m-t-48 u-m-b-24" @click="delSpecificationsGroup(index)">
<view class="icon icon-reduce u-m-r-22 ">
</view>
<view class="color-red">删除规格组</view>
</view>
</view>
</uni-forms>
</view>
<view class="u-flex block u-p-l-20 u-p-r-20 u-p-t-28 u-p-b-28" @click="addSpecificationsGroup">
<view class="icon icon-add u-m-r-22 ">
</view>
<view class="color-main">添加规格组</view>
</view>
<view class="save-btn-box">
<button class="save-btn" hover-class="btn-hover-class" @click="save">保存</button>
</view>
</view>
<view class="bottom" ref="bottom"></view>
</view>
</template>
<script setup>
import go from '@/commons/utils/go.js';
import {
onLoad,
onReady
} from '@dcloudio/uni-app';
import {
onMounted,
reactive,
nextTick,
ref,
onBeforeMount
} from 'vue';
// 表单样式
const placeholderStyle = ref('font-size:28rpx;')
//表单边框
const inputBorder = ref(false)
const form = ref(null)
const bottom = ref(null)
//表单验证
const rules = {
name: {
rules: [{
required: true,
errorMessage: '必填'
}]
},
MinOptional: {
rules: [{
required: true,
errorMessage: '必填'
}]
},
MaxOptional: {
rules: [{
required: true,
errorMessage: '必填'
}]
},
optionName: {
rules: [{
required: true,
errorMessage: '必填'
}]
},
optionPrice: {
rules: [{
required: true,
errorMessage: '必填'
}]
}
}
// 构造规格的选项值的基础数据
const specificationsOptionsBasicData = {
optionName: '',
optionPrice: '0.00'
}
function returnOptionsBasicData() {
return {
...specificationsOptionsBasicData
}
}
// 构造规格的基础数据
const specificationsBasicData = {
name: '',
MinOptional: 1,
MaxOptional: 1,
options: []
}
function returnSpecificationsOptionsBasicData() {
return {
...specificationsBasicData,
options: [returnOptionsBasicData()]
}
}
function onFieldChange(e) {
console.log(e);
}
// 规格列表
const specifications = reactive({
list: [returnSpecificationsOptionsBasicData()]
})
//添加规格组
function addSpecificationsGroup() {
specifications.list.push(returnSpecificationsOptionsBasicData())
scrollPageBottom()
}
//删除规格组
function delSpecificationsGroup(index) {
specifications.list.splice(index, 1)
}
// 向指定索引的规格组添加规格项
function addOptions(index) {
specifications.list[index].options.push(returnOptionsBasicData())
}
// 删除指定索引的规格组添加规格项
function delOption(index, optionIndex) {
specifications.list[index].options.splice(optionIndex, 1)
}
//页面滚动到最底部
function scrollPageBottom() {
nextTick(() => {
uni.pageScrollTo({
duration: 100, // 过渡时间
scrollTop: 100000, // 滚动的实际距离
})
})
}
//设置表单验证规则
function setFormRules() {
form.value.setRules(rules)
}
const formRefs = ref([]);
//绑定表单元素
function setFormRef(index) {
formRefs.value[index] = null;
return (el) => {
if (el) {
formRefs.value[index] = el;
}
};
}
// 绑定option input元素
const refFormInput=ref([])
function setFormInputRef(index, index1) {
const newIndex = index * 10000 + index1
return (el) => {
if (el) {
if (!refFormInput.value[newIndex]) {
refFormInput.value[newIndex] = el;
}
}
}
}
// 当表单内容输入变化根据配置的rules进行验证
function inpuChange(index, index1) {
const newIndex = index * 10000 + index1
console.log(refFormInput.value[newIndex]);
refFormInput.value[newIndex].onFieldChange()
}
let emitName=''
function triggerEvent (emitName,data){
if(emitName){
uni.$emit(emitName,data)
}
}
onLoad(opt=>{
const arr=uni.getStorageSync('guige')
if(arr.length){
specifications.list=arr
console.log(arr);
}
console.log(opt);
if(opt&&JSON.stringify(opt)!=='{}'&&opt.emitName){
emitName=opt.emitName
}
uni.setNavigationBarTitle({
title:emitName?'编辑规格模版':'添加规格模版'
})
})
function emitspecificationsSave(){
// emitspecificationsSave 触发规格保存事件将数据给到添加商品页面
// guigeEdit 触发规格保存事件将数据给到添加规格页面
uni.removeStorageSync('guige')
triggerEvent(emitName,specifications.list)
}
function returnPromise(index,prosise){
return new Promise((resolve,reject)=>{
prosise.then(res=>{
console.log(res);
resolve({sucees:true})
}).catch(err=>{
console.log(err);
resolve({sucees:false})
})
})
}
async function save() {
let isAllPassForm=0
for (let i in specifications.list) {
const res=await returnPromise(i,formRefs.value[i].validate())
isAllPassForm+=res.sucees?1:0
}
//判断验证是否通过
if(isAllPassForm===specifications.list.length){
console.log('pass');
emitspecificationsSave()
go.back()
}
}
</script>
<style scoped>
page {
background: #F9F9F9;
}
</style>
<style lang="scss" scoped>
$icon-size: 34rpx;
$icon-line-width: 20rpx;
$icon-line-height: 4rpx;
.page {
background: #F9F9F9;
padding: 30rpx;
padding-bottom: 200rpx;
}
.my-switch {
transform: scale(0.7);
}
::v-deep .uni-forms-item__error {
display: none !important;
}
::v-deep .option .uni-forms-item {
padding: 0;
min-height: inherit;
background-color: transparent;
border-top: none;
}
.icon {
width: $icon-size;
height: $icon-size;
position: relative;
border-radius: 50%;
&:before,
&::after {
position: absolute;
display: block;
content: '';
background-color: #fff;
}
}
.icon-add {
background-color: $my-main-color;
&::before {
width: $icon-line-height;
height: $icon-line-width;
top: calc(($icon-size /2) - ($icon-line-width / 2));
left: calc(($icon-size /2) - ($icon-line-height / 2));
}
&::after {
width: $icon-line-width;
height: 4rpx;
top: calc(($icon-size /2) - ($icon-line-height / 2));
left: calc(($icon-size /2) - ($icon-line-width / 2));
}
}
.icon-reduce {
background-color: $my-red-color;
&::after {
width: $icon-line-width;
height: $icon-line-height;
top: calc(($icon-size /2) - ($icon-line-height / 2));
left: calc(($icon-size /2) - ($icon-line-width / 2));
}
}
.label-title {
font-size: 28rpx;
font-weight: bold;
font-family: Source Han Sans CN, Source Han Sans CN;
}
.lh40 {
line-height: 40rpx;
}
.box {
margin-top: 70rpx;
font-size: 28rpx;
.block {
background: #FFFFFF;
border-radius: 18rpx 18rpx 18rpx 18rpx;
padding: 12rpx 24rpx;
margin-bottom: 32rpx;
}
}
.save-btn-box {
position: fixed;
left: 30rpx;
right: 30rpx;
bottom: 60rpx;
}
::v-deep.uni-forms-item {
align-items: inherit;
}
::v-deep .uni-forms-item .uni-forms-item__label {
text-indent: 0;
font-size: 28rpx !important;
font-weight: bold;
color: #333;
}
::v-deep .border-top-0 .uni-forms-item.is-direction-top {
border-color: transparent !important;
}
.save-btn {
background-color: $my-main-color;
color: #fff;
border-radius: 12rpx;
font-size: 28rpx;
}
.btn-hover-class {
opacity: .6;
}
.zuofa {
padding: 28rpx 0;
background: #F9F9F9;
padding-left: 42rpx;
border-radius: 14rpx 14rpx 14rpx 14rpx;
}
::v-deep .uni-input-placeholder {
font-size: 28rpx;
}
.option {
padding: 26rpx 30rpx 24rpx 24rpx;
background: #F9F9F9;
}
.option-item {
margin-bottom: 34rpx;
}
</style>

View File

@@ -2,276 +2,104 @@
<view class="page min-page">
<view class="box">
<view class="block border-top-0 u-p-t-32 u-p-b-32">
<uni-forms ref="nameFormRef" :model="specifications" :rules="rules" :label-width="350"
label-position="top" validateTrigger="blur">
<uni-forms-item label="模版名称" required name="name">
<uni-easyinput padding-none :placeholderStyle="placeholderStyle" :inputBorder="inputBorder"
v-model="specifications.name" placeholder="模版名称,如:衣服" />
</uni-forms-item>
</uni-forms>
</view>
<view v-for="(item,index) in specifications.list" :key="index">
<uni-forms :model="item" :rules="rules" err-show-type="undertext" validateTrigger="blur"
:ref="setFormRef(index)" :border="true" label-position="top" label-width="350">
<view class="block">
<view class="border-top-0">
<uni-forms-item label="规格组名" required name="name">
<uni-easyinput padding-none :placeholderStyle="placeholderStyle" :inputBorder="inputBorder"
v-model="item.name" placeholder="规格组名,如:尺码" />
</uni-forms-item>
</view>
<view class="u-p-b-8">
<uni-forms-item label="规格值">
<view class="option ">
<view class="">
<view class="u-flex option-item u-m-t-8" v-for="(option,optionIndex) in item.options"
:key="optionIndex">
<view class="u-flex-1">
<uni-forms-item :key="optionIndex" :name="['options',optionIndex,'name']"
:ref="setFormInputRef(index,optionIndex)"
:rules="[{'required': true,errorMessage: '必填'}]" label-width="0"
label="" required :showRequired="false">
<view class="bg-fff u-p-t-12 u-p-b-12" style="border-radius: 8rpx;">
<uni-easyinput
v-model="specifications.list[index].options[optionIndex].name"
@input="inpuChange(index,optionIndex)"
:placeholderStyle="placeholderStyle" :inputBorder="inputBorder"
placeholder="请输入规格值,如:S、M" />
</view>
</uni-forms-item>
</view>
<view class=" u-flex" v-if="item.options.length>1">
<uni-forms-item :key="optionIndex" label-width="0" label=""
:showRequired="false">
<view class="u-flex">
<!-- <uni-easyinput v-model="specifications.list[index].options[optionIndex].optionPrice"
@input="inpuChange(index,optionIndex)"
:placeholderStyle="placeholderStyle" :inputBorder="inputBorder"
type="digit" placeholder="填写价格" /> -->
<view class="icon icon-reduce u-m-l-38"
@click="delOption(index,optionIndex)">
</view>
</view>
</uni-forms-item>
</view>
</view>
</view>
<view class="u-flex u-m-t-24 " @click="addOptions(index)">
<view class="icon icon-add u-m-r-22 ">
</view>
<view class="color-main">添加规格</view>
</view>
</view>
</uni-forms-item>
</view>
<template v-if="specifications.list.length>1">
<view class="u-p-b-32">
<view class="u-flex " @click="delSpecificationsGroup(index)">
<view class="icon icon-reduce u-m-r-22 ">
</view>
<view class="color-red">删除规格组</view>
</view>
</view>
</template>
</view>
</uni-forms>
<!-- 注意如果需要兼容微信小程序最好通过setRules方法设置rules规则 -->
<up-form ref="formRef" labelPosition="top" :model="vdata.formData" :rules="vdata.rules" labelWidth="80" :labelStyle="{fontWeight:'bold'}">
<up-form-item label="规格名称" prop="name" borderBottom >
<up-input v-model="vdata.formData.name" border="none" placeholder="规格名称,如:衣服" ></up-input>
</up-form-item>
<up-form-item label="规格级别" prop="level" borderBottom @click="vdata.showLevel = true;">
<up-input v-model="vdata.levelName" readonly border="none" placeholder="请选择规格级别" ></up-input>
</up-form-item>
<up-form-item label="排序" prop="sort" borderBottom >
<up-input v-model="vdata.formData.sort" border="none" placeholder="请输入排序" ></up-input>
</up-form-item>
<up-form-item label="上级规格" prop="pid" borderBottom @click="vdata.showSpec = true;">
<up-input v-model="vdata.pidName" readonly border="none" placeholder="请选择上级规格" ></up-input>
</up-form-item>
</up-form>
</view>
<view class="u-flex block u-p-l-20 u-p-r-20 u-p-t-28 u-p-b-28" @click="addSpecificationsGroup">
<view class="icon icon-add u-m-r-22 ">
</view>
<view class="color-main">添加规格组</view>
</view>
<view class="save-btn-box">
<button class="save-btn " hover-class="btn-hover-class" @click="save">保存</button>
</view>
</view>
<view class="bottom" ref="bottom"></view>
<up-action-sheet
:show="vdata.showLevel"
:actions="vdata.levelList"
title="请选择规格级别"
@close="vdata.showLevel = false"
@select="levelSelect"
></up-action-sheet>
<up-action-sheet
:show="vdata.showSpec"
:actions="vdata.specList"
title="请选择规格级别"
@close="vdata.showSpec = false"
@select="specSelect"
></up-action-sheet>
</view>
</template>
<script setup>
import go from '@/commons/utils/go.js';
import {
$productSpec
} from '@/http/yskApi/goods.js'
import {
onLoad,
onReady,
} from '@dcloudio/uni-app';
import { reactive, nextTick, ref } from 'vue';
import { onLoad, onReady, } from '@dcloudio/uni-app';
import infoBox from '@/commons/utils/infoBox.js'
import {
onMounted,
reactive,
nextTick,
ref,
onBeforeMount
} from 'vue';
const nameFormRef = ref(null)
// 表单样式
const placeholderStyle = ref('font-size:28rpx;')
//表单边框
const inputBorder = ref(false)
const form = ref(null)
const bottom = ref(null)
//表单验证
const rules = {
name: {
rules: [{
required: true,
errorMessage: '必填'
}]
},
MinOptional: {
rules: [{
required: true,
errorMessage: '必填'
}]
},
MaxOptional: {
rules: [{
required: true,
errorMessage: '必填'
}]
},
optionPrice: {
rules: [{
required: true,
errorMessage: '必填'
}]
}
}
// 构造规格的选项值的基础数据
const specificationsOptionsBasicData = {
name: '',
optionPrice: '0.00'
}
function returnOptionsBasicData() {
return {
...specificationsOptionsBasicData
}
}
// 构造规格的基础数据
const specificationsBasicData = {
name: '',
// MinOptional: 1,
// MaxOptional: 1,
options: []
}
function returnSpecificationsOptionsBasicData() {
return {
...specificationsBasicData,
options: [returnOptionsBasicData()]
}
}
function onFieldChange(e) {
console.log(e);
}
// 规格列表
const specifications = reactive({
name: '',
list: [returnSpecificationsOptionsBasicData()]
})
//添加规格组
function addSpecificationsGroup() {
specifications.list.push(returnSpecificationsOptionsBasicData())
scrollPageBottom()
}
//删除规格组
function delSpecificationsGroup(index) {
if(specifications.list.length<=1){
return
}
specifications.list.splice(index, 1)
}
// 向指定索引的规格组添加规格项
function addOptions(index) {
specifications.list[index].options.push(returnOptionsBasicData())
}
// 删除指定索引的规格组添加规格项
function delOption(index, optionIndex) {
if(specifications.list[index].options.length<=1){
return
}
specifications.list[index].options.splice(optionIndex, 1)
}
//页面滚动到最底部
function scrollPageBottom() {
nextTick(() => {
uni.pageScrollTo({
duration: 100, // 过渡时间
scrollTop: 100000, // 滚动的实际距离
})
})
}
//设置表单验证规则
function setFormRules() {
form.value.setRules(rules)
}
const formRefs = ref([]);
//绑定表单元素
function setFormRef(index) {
formRefs.value[index] = null;
return (el) => {
if (el) {
formRefs.value[index] = el;
}
};
}
// 绑定option input元素
const refFormInput = ref([])
function setFormInputRef(index, index1) {
const newIndex = index * 10000 + index1
return (el) => {
if (el) {
if (!refFormInput.value[newIndex]) {
refFormInput.value[newIndex] = el;
}
}
}
}
// 当表单内容输入变化根据配置的rules进行验证
function inpuChange(index, index1) {
const newIndex = index * 10000 + index1
console.log(refFormInput.value[newIndex]);
refFormInput.value[newIndex].onFieldChange()
}
import { getSpecList, addSpec, updateSpec } from '@/api/product.js'
const option = {
type: 'add',
id: undefined
}
const formRef = ref(null)
const vdata = reactive({
showLevel: false,
showSpec: false,
levelList: [
{ name: "一级", value: 1},
{ name: "二级", value: 2},
{ name: "三级", value: 3}
],
levelName: "",
pidName: "",
formData: {
id: null,
name: "",
level: "",
sort: "",
pid: "",
},
rules: {
"name": {
required: true,
message: '请输入规格名称',
trigger: ['blur', 'change'],
},
"level": {
required: true,
message: '请选择规格级别',
trigger: ['blur', 'input'],
},
"sort": {
required: true,
message: '请输入排序',
trigger: ['blur', 'change'],
},
"pid": {
required: true,
message: '请选择上级规格',
trigger: ['blur', 'input'],
},
},
specList: []
})
onReady(()=>{
})
//表单验证
onLoad(opt => {
console.log(opt);
if (opt && JSON.stringify(opt) !== '{}' && opt.type) {
@@ -279,90 +107,68 @@
const data = uni.getStorageSync('spec')
uni.removeStorageSync('spec')
if(data){
specifications.name = data.name
specifications.id = data.id
specifications.list = data.specList.map(v => {
return {
...v,
options: v.value.map(v => {
return {
name: v
}
})
}
})
vdata.formData.id = data.id
vdata.formData.name = data.name
vdata.formData.level = data.level
vdata.formData.sort = data.sort
vdata.formData.pid = data.pid
vdata.levelName = vdata.levelList.filter(item => item.value == vdata.formData.level)[0].name
}
}
uni.setNavigationBarTitle({
title: option.type === 'edit' ? '编辑规格模版' : '添加规格模版'
})
getSpecData()
})
function returnPromise(prosise, index) {
return new Promise((resolve, reject) => {
prosise.then(res => {
console.log(res);
resolve({
sucees: true
})
}).catch(err => {
console.log(err);
resolve({
sucees: false
})
})
/**
* 获取规格列表
*/
function getSpecData(){
getSpecList({page: 0, size:10}).then(res=>{
vdata.specList = [{name: '顶级',id: 0},...res]
if(vdata.formData.id){
vdata.pidName = vdata.specList.filter(item => item.id == vdata.formData.pid)[0].name
}
})
}
function levelSelect (e) {
console.log(e)
vdata.levelName = e.name;
vdata.formData.level = e.value;
}
function specSelect (e) {
console.log(e)
vdata.pidName = e.name;
vdata.formData.pid = e.id;
}
/**
* 保存
*/
async function save() {
if (option.type === 'add') {
return addSpec(vdata.formData).then(res => {
infoBox.showToast('添加成功')
settimeoutBack(1500)
})
}
updateSpec(vdata.formData).then(res => {
infoBox.showToast('修改成功')
settimeoutBack(1500)
})
}
let timer = null
function settimeoutBack(time) {
clearTimeout(timer)
timer = setTimeout(() => {
uni.navigateBack()
}, time)
}
async function save() {
let isAllPassForm = 0
const nameFormRes = await returnPromise(nameFormRef.value.validate())
console.log(nameFormRes);
if (!nameFormRes.sucees) {
isAllPassForm -= 1
}
for (let i in specifications.list) {
const res = await returnPromise(formRefs.value[i].validate(), i)
isAllPassForm += res.sucees ? 1 : 0
}
//判断验证是否通过
if (isAllPassForm === specifications.list.length) {
console.log('pass');
const data = {
name: specifications.name,
id:specifications.id,
specList: specifications.list.map(v => {
return {
...v,
value: v.options.map(v => v.name),
options: undefined
}
})
}
if (option.type === 'add') {
return $productSpec.add(data).then(res => {
infoBox.showSuccessToast('添加成功')
settimeoutBack(1500)
})
}
$productSpec.update(data).then(res => {
infoBox.showSuccessToast('修改成功')
settimeoutBack(1500)
})
}
}
</script>
<style scoped>
page {

View File

@@ -15,31 +15,17 @@
</uni-data-picker>
</view>
</view>
<!-- <view class="border-top-0">
<uni-forms-item label="选择规格" required name="categoryId">
<uni-data-picker :clear-icon="false" @change="specIdChange"
:map="{text:'name',value:'id'}" placeholder="请选择规格" popup-title="请选择规格"
:localdata="FormData.specList" v-model="FormData.specId">
</uni-data-picker>
</uni-forms-item>
</view> -->
<view class=" ">
<view class="u-m-t-32" v-for="(item,index) in FormData.selectSpec" :key="index">
<view class="u-m-t-32" v-for="(item,index) in FormData.selectSpecInfo" :key="index">
<view class="font-bold">
{{item.name}}
</view>
<view class="u-m-t-16">
<!-- <up-checkbox-group :labelSize="12" :size="14" :activeColor="color.ColorMain"
shape="circle" v-model="item.selectSpecResult" placement="row"
@change="createResult">
<up-checkbox :customStyle="{marginRight: '60rpx',marginBottom:'16rpx'}"
v-for="(item, index) in item.value" :key="index" :label="item.text"
:name="item.value">
</up-checkbox>
</up-checkbox-group> -->
<uni-data-checkbox @change="createResult" multiple :selectedColor="color.ColorMain"
v-model="item.selectSpecResult" :localdata="item.value">
v-model="item.selectSpecResult" :localdata="item.children">
</uni-data-checkbox>
</view>
@@ -106,29 +92,13 @@
:inputBorder="inputBorder" v-model="item.skus.originPrice" type="digit"
placeholder="请输入原价(元)" />
</uni-forms-item>
<uni-forms-item label="起售数量" required name="suit">
<uni-easyinput @blur="priceFormat(item.skus,'suit')" :paddingNone="inputPaddingNone"
<uni-forms-item label="起售数量" required name="suitNum">
<uni-easyinput @blur="priceFormat(item.skus,'suitNum')" :paddingNone="inputPaddingNone"
:placeholderStyle="placeholderStyle" :inputBorder="inputBorder"
v-model="item.skus.suit" type="digit" placeholder="请输入起售数量" />
v-model="item.skus.suitNum" type="digit" placeholder="请输入起售数量" />
</uni-forms-item>
<!-- <view class="u-relative">
<uni-forms-item label="库存数量" required>
<uni-easyinput :disabled="disabledStock"
@blur="priceFormat(item.skus,'stockNumber')" :paddingNone="inputPaddingNone"
:placeholderStyle="placeholderStyle" :inputBorder="inputBorder"
v-model="item.skus.stockNumber" type="digit" placeholder="请输入库存数量" />
</uni-forms-item>
<view class="u-absolute position-all" v-if="disabledStock"
@click="canEditGoodsStock(true)">
</view>
</view> -->
<uni-forms-item label="分销金额" required>
<uni-easyinput @blur="priceFormat(item.skus,'firstShared')"
:paddingNone="inputPaddingNone" :placeholderStyle="placeholderStyle"
:inputBorder="inputBorder" v-model="item.skus.firstShared" type="digit"
placeholder="请输入分销金额" />
</uni-forms-item>
<uni-forms-item label="商品条码" required>
<view class="bg-gray u-flex u-col-center u-col-center u-p-l-24" style="height: 72rpx;background: #F6F6F6;border-radius: 8rpx ;">
<uni-easyinput disabled :paddingNone="inputPaddingNone"
@@ -171,48 +141,178 @@
</view>
</template>
<script setup>
import {
getSafeBottomHeight
} from '@/commons/utils/safe-bottom.js'
import {
formatPrice
} from "@/commons/utils/format.js";
import { reactive, nextTick, ref, watch } from 'vue';
import { onLoad, onReady, onShow } from '@dcloudio/uni-app';
import { getSafeBottomHeight } from '@/commons/utils/safe-bottom.js'
import { formatPrice } from "@/commons/utils/format.js";
import popFastEdit from "./components/fast-edit.vue"
import infoBox from '@/commons/utils/infoBox.js'
import dayjs from "dayjs";
import go from '@/commons/utils/go.js';
import color from '@/commons/color.js';
import {
$types,
$defaultSku
} from '@/commons/goodsData.js'
import {
$productSpec
} from '@/http/yskApi/goods.js';
import {
onLoad,
onReady,
onShow
} from '@dcloudio/uni-app';
import {
onMounted,
reactive,
nextTick,
ref,
onBeforeMount,
watch
} from 'vue';
import {
hasPermission
} from '@/commons/utils/hasPermission.js';
import { $defaultSku } from '@/commons/goodsData.js'
import { hasPermission } from '@/commons/utils/hasPermission.js';
import { getSpecList,delSpec } from '@/api/product.js'
//上个页面传来的参数
let option = {}
const FormData = reactive({
specId: '',
specItem: '',
specAllList: [],
result: [],
selectSpecInfo: [],
})
//表单验证
const rules = {
salePrice: {
rules: [{
required: true,
errorMessage: '售价必填'
}]
},
memberPrice: {
rules: [{
required: true,
errorMessage: '会员价必填'
}]
},
costPrice: {
rules: [{
required: true,
errorMessage: '成本价必填'
}]
},
originPrice: {
rules: [{
required: true,
errorMessage: '原价必填'
}]
},
suitNum: {
rules: [{
required: true,
errorMessage: '起售数量必填'
},
{
validateFunction: function(rule, value, data, callback) {
if (value < 1) {
callback('起售数量至少为1个')
}
return true
}
}
]
}
}
let bottomHeight = ref(100)
const inputPaddingNone = ref(true)
const form = ref(null)
const formRefs = ref([]);
const originSpecMap = {}
let emitName = ''
onReady(() => {
getSafeBottomHeight('safe-bottom').then(res => {
console.log(res);
bottomHeight.value = res
})
})
onShow(() => {
canEditGoodsStock()
})
onLoad(opt => {
Object.assign(option, opt)
const obj = uni.getStorageSync('guige')
getTbProductSpec(obj)
if (opt && JSON.stringify(opt) !== '{}' && opt.emitName) {
emitName = opt.emitName
}
})
function triggerEvent(emitName, data) {
if (emitName) {
uni.$emit(emitName, data)
}
}
/**
* 获取规格数据
*/
function getTbProductSpec(obj) {
getSpecList({name: ''}).then(res => {
FormData.specAllList = res;
FormData.specAllList.map(item => {
item.children.map(spe => {
spe.children.map(v => {
if (obj && JSON.stringify(obj) !== '{}') {
spe.selectSpecResult = []
for (var oe in obj.selectSpecInfo) {
if ( spe.name == oe ) {
spe.selectSpecResult = obj.selectSpecInfo[oe]
}
}
} else {
spe.selectSpecResult = []
}
v.text = v.name
v.value = v.name
})
})
});
if (obj && JSON.stringify(obj) !== '{}') {
FormData.specAllList.map(item=>{
if( item.id == obj.specId ){
obj.selectSpecInfo = item.children
}
})
}
FormData.specList = res.map(item => {
return {
id: item.id,
name: item.name,
}
})
if (obj && JSON.stringify(obj) !== '{}') {
// console.log(obj.selectSpecInfo);
Object.assign(FormData, obj)
for (let i of obj.result) {
const key = returnSpecSnap(i.names)
originSpecMap[key] = i
}
nextTick(() => {
FormData.result = obj.result
})
}
console.log(FormData)
})
}
/**
* 规则选择
* @param {Object} e
*/
function specIdChange(e) {
const item = FormData.specAllList.find(v => v.id === FormData.specId)
FormData.selectSpecInfo = (item.children || [])
console.log(item)
}
const refFiles = ref([]);
const imageStyles = reactive({
width: 82,
@@ -250,38 +350,38 @@
},
{
text: '起售数量',
key: 'suit',
key: 'suitNum',
value: ''
},
{
text: '库存数量',
key: 'stockNumber',
value: ''
},
{
text: '分销金额',
key: 'firstShared',
value: ''
}
],
sel: ''
})
/**
* 批量修改打开
*/
function fastEditShow() {
fastEdit.show = true
}
//上个页面传来的参数
let option = {}
//number类型数据限制
/**
* number类型数据限制
* @param {Object} item
* @param {Object} key
*/
function priceFormat(item, key) {
nextTick(() => {
let min = 0;
let max = 100000000;
console.log(item[key]);
if (key == 'suit') {
if (key == 'suitNum') {
min = 1
}
const newval = formatPrice(item[key], min, max, true)
@@ -298,7 +398,10 @@
}
/**
* 批量修改监听
* @param {Object} arr
*/
function updateSkuKey(arr) {
for (let i in FormData.result) {
const sku = FormData.result[i].skus
@@ -312,21 +415,12 @@
}
}
const inputPaddingNone = ref(true)
const form = ref(null)
const originSpecMap = {}
const FormData = reactive({
specId: '',
specItem: '',
result: [],
selectSpec: [],
})
//表单相关事件
function changeResultCover(val, index) {
FormData.result[index].coverImg = val
console.log(FormData.result[index]);
}
const formRefs = ref([]);
//绑定表单元素
function setFormRef(index) {
formRefs.value[index] = null;
@@ -346,7 +440,6 @@
const inputBorder = ref(false)
//生成笛卡尔集
function combineSpecs(specs) {
if (specs.length === 0) {
return [
@@ -366,9 +459,7 @@
};
const defaultSku = reactive({
...$defaultSku,
shopId: uni.getStorageSync('shopId'),
coverImg: '',
productId: option.productId,
barCode: `${uni.getStorageSync("shopId")}${dayjs().valueOf()}`
})
@@ -376,43 +467,33 @@
const randomNumber = Math.floor(Math.random() * 1000)
return {
...defaultSku,
productId: option.productId,
barCode: `${uni.getStorageSync("shopId")}${dayjs().valueOf()-randomNumber}`
}
}
/**
* 选择规格属性
*/
function createResult() {
let arr = []
// for(let i in FormData.selectSpec){
// const selectSpecResult=FormData.selectSpec[i].selectSpecResult
// if(selectSpecResult.length>0){
// arr.push({
// value: selectSpecResult,
// name: FormData.selectSpec[i].name
// })
// }
// }
for (let k of FormData.selectSpec) {
for (let k of FormData.selectSpecInfo) {
if (k.selectSpecResult.length) {
console.log(k.selectSpecResult.length);
arr.push({
value: k.selectSpecResult,
name: k.name
})
}
}
console.log(arr);
const spes = combineSpecs(arr)
console.log(spes);
const result = spes.filter(v => {
return !Array.isArray(v)
}).map(v => {
const specSnap = returnSpecSnap(v)
const data = originSpecMap[specSnap]
const specInfo = returnSpecSnap(v)
const data = originSpecMap[specInfo]
const skus = returnDefaultSku()
const newdata = {
names: v,
specSnap,
specInfo,
skus
}
return data || newdata
@@ -422,84 +503,6 @@
function specIdChange(e) {
console.log(e);
const item = FormData.specList.find(v => v.id === FormData.specId)
FormData.selectSpec = (item.specList || [])
}
//获取规格数据
function getTbProductSpec() {
$productSpec.get({
page: 0,
size: 200,
sort: "id"
}).then(res => {
FormData.specList = res.content.map(item => {
return {
...item,
specList: item.specList.map(spe => {
return {
...spe,
selectSpecResult: [],
value: spe.value.map(v => {
return {
text: v,
value: v
}
})
}
})
}
})
})
}
//表单验证
const rules = {
salePrice: {
rules: [{
required: true,
errorMessage: '售价必填'
}]
},
memberPrice: {
rules: [{
required: true,
errorMessage: '会员价必填'
}]
},
costPrice: {
rules: [{
required: true,
errorMessage: '成本价必填'
}]
},
originPrice: {
rules: [{
required: true,
errorMessage: '原价必填'
}]
},
suit: {
rules: [{
required: true,
errorMessage: '起售数量必填'
},
{
validateFunction: function(rule, value, data, callback) {
if (value < 1) {
callback('起售数量至少为1个')
}
return true
}
}
]
}
}
//页面滚动到最底部
@@ -514,23 +517,12 @@
let emitName = ''
function triggerEvent(emitName, data) {
if (emitName) {
uni.$emit(emitName, data)
}
}
//生成name
function returnSpecSnap(names) {
const specSnap = Object.keys(names).reduce((prve, cur) => {
const specInfo = Object.keys(names).reduce((prve, cur) => {
return prve + names[cur] + ','
}, '')
return specSnap.substring(0, specSnap.length - 1)
return specInfo.substring(0, specInfo.length - 1)
}
// 允许修改商品库存
let disabledStock = ref(false)
@@ -545,34 +537,7 @@
}
}
onShow(() => {
canEditGoodsStock()
})
onLoad(opt => {
Object.assign(option, opt)
getTbProductSpec()
const obj = uni.getStorageSync('guige')
if (obj && JSON.stringify(obj) !== '{}') {
console.log(obj.selectSpec);
option.productId = opt.productId
Object.assign(FormData, obj)
for (let i of obj.result) {
const key = returnSpecSnap(i.names)
originSpecMap[key] = i
}
nextTick(() => {
FormData.result = obj.result
console.log(FormData.result);
})
}
console.log(opt);
if (opt && JSON.stringify(opt) !== '{}' && opt.emitName) {
emitName = opt.emitName
}
})
function emitspecificationsSave() {
// emitspecificationsSave 触发规格保存事件将数据给到添加商品页面
// guigeEdit 触发规格保存事件将数据给到添加规格页面
@@ -613,7 +578,7 @@
//判断验证是否通过
console.log('pass');
const item = FormData.specList.find(v => v.id === FormData.specId)
FormData.specsInfoName = item ? item.name : ''
FormData.specName = item ? item.name : ''
console.log(FormData);
emitspecificationsSave()

View File

@@ -80,7 +80,7 @@
},
{
text: '起售数量',
key: 'suit',
key: 'suitNum',
value: 1
},
// {
@@ -88,11 +88,7 @@
// key: 'stockNumber',
// value: ''
// },
{
text: '分销金额',
key: 'firstShared',
value: ''
}
]
const list = ref([...arr])

View File

@@ -33,8 +33,7 @@ export const $defaultSku = {
costPrice: '',
originPrice: '',
// stockNumber: '',
firstShared: '',
suit: 1,
suitNum: 1,
barCode: `${uni.getStorageSync("shopId")}${dayjs().valueOf()}`,
}

View File

@@ -1,120 +0,0 @@
<template>
<view>
<view class="category " :style="getCompouteStyle()">
<scroll-view scroll-y="true" :style="{height:props.height+'rpx'}">
<view class="list">
<view v-if="showAllText" class="font-bold item border-bottom u-font-28" @tap="cateClick({id:'',name:'全部分类'})">全部分类</view>
<view v-for="(item,index) in category.list" :key="index">
<view class="item font-bold border-bottom" @tap="cateClick(item)">
{{item.name}}
</view>
<view class="item border-bottom" @tap="cateClick(child)"
v-for="(child,childIndex) in item.childrenList"
:key="childIndex" >
<text>&nbsp;&nbsp;</text>
{{child.name}}
</view>
</view>
</view>
</scroll-view>
</view>
</view>
</template>
<script setup>
import {
ref, warn, watch, watchEffect,
onMounted,reactive
} from 'vue';
import {$tbShopCategory} from '@/http/yskApi/goods.js'
const emite=defineEmits(['cateClick','change'])
const props = defineProps({
showAllText:{
type:Boolean,
default:true
},
width: {
type: [Number, String],
default: 264
},
height: {
type: [Number, String],
default: 420
},
right: {
type: [Number, String],
default: 30
},
bottom: {
type: [Number, String],
default: 0
}
})
let show = ref(false)
watch(()=>show.value,(newval)=>{
emite('change',newval)
})
function open() {
show.value = true
}
function close() {
show.value = false
}
function toggle() {
show.value = !show.value
}
function cateClick(item){
emite('cateClick',item)
close()
}
function getCompouteStyle() {
return {
width: props.width + 'rpx',
height: props.height + 'rpx',
right: props.right + 'rpx',
bottom: props.bottom + 'rpx',
transform:`scaleY(${show.value?1:0})`
}
}
const category=reactive({
list:[],
categoryId:'',
categoryName:'',
})
onMounted(()=>{
$tbShopCategory({
page:0,size:200
}).then(res=>{
category.list=res.content
})
})
defineExpose({
open,
close,toggle
})
</script>
<style lang="scss" scoped>
.category {
background: #FFFFFF;
box-shadow: 0rpx 6rpx 12rpx 2rpx rgba(0, 0, 0, 0.16);
border-radius: 14rpx 14rpx 14rpx 14rpx;
position: fixed;
font-size: 24rpx;
color: #333;
.list{
box-sizing: border-box;
.item{
padding: 24rpx 24rpx 24rpx 48rpx;
}
}
}
</style>

View File

@@ -1,93 +0,0 @@
<template>
<view>
<view class="category " :style="getCompouteStyle()">
<scroll-view scroll-y="true" :style="{height:props.height+'rpx'}">
<view class="list">
<view class="item" @tap="cateClick(item)" v-for="(item,index) in 20" :key="index">
分类
</view>
</view>
</scroll-view>
</view>
</view>
</template>
<script setup>
import {
ref, warn, watch, watchEffect,
onMounted
} from 'vue';
import {$tbShopCategory} from '@/http/yskApi/goods.js'
const emite=defineEmits(['cateClick'])
const props = defineProps({
width: {
type: [Number, String],
default: 264
},
height: {
type: [Number, String],
default: 420
},
right: {
type: [Number, String],
default: 30
},
bottom: {
type: [Number, String],
default: 0
}
})
let show = ref(false)
function open() {
show.value = true
}
function close() {
show.value = false
}
function toggle() {
show.value = !show.value
}
function cateClick(item){
emite('cateClick',item)
}
function getCompouteStyle() {
return {
width: props.width + 'rpx',
height: props.height + 'rpx',
right: props.right + 'rpx',
bottom: props.bottom + 'rpx',
transform:`scaleY(${show.value?1:0})`
}
}
onMounted(()=>{
$tbShopCategory({
page:0,size:200
})
})
defineExpose({
open,
close,toggle
})
</script>
<style lang="scss" scoped>
.category {
background: #FFFFFF;
box-shadow: 0rpx 6rpx 12rpx 2rpx rgba(0, 0, 0, 0.16);
border-radius: 14rpx 14rpx 14rpx 14rpx;
position: fixed;
font-size: 24rpx;
color: #333;
.list{
box-sizing: border-box;
.item{
padding: 24rpx 24rpx 24rpx 48rpx;
}
}
}
</style>

View File

@@ -3,11 +3,8 @@
</template>
<script setup>
import {
ref, warn, watch, watchEffect,
onMounted,reactive
} from 'vue';
import {$tbShopCategory} from '@/http/yskApi/goods.js'
import { ref, watch,onMounted,reactive } from 'vue';
import { getCategoryList } from '@/api/product.js'
const emite=defineEmits(['change','update:isShow','confirm'])
const props = defineProps({
showAllText:{
@@ -35,7 +32,28 @@
default:false
}
})
const category=reactive({
list:[],
})
onMounted(()=>{
getCategoryList({
page:1,size:200
}).then(res=>{
res.unshift({
name:'全部',
id:'',
childrenList:[]
})
category.list=[res.reduce((prve, cur) => {
prve.push(...[{
...cur,
name: '' + cur.name,
childrenList:undefined
}])
return prve
}, [])]
})
})
let show = ref(props.isShow)
watch(()=>show.value,(newval)=>{
@@ -43,49 +61,19 @@
emite('update:isShow',newval)
})
watch(()=>props.isShow,(newval)=>{
console.log(newval);
show.value=newval
})
function confirm(e){
console.log(e.value[0]);
show.value = false
emite('confirm',e.value[0])
}
function close() {
console.log('close');
show.value = false
}
const category=reactive({
list:[],
})
onMounted(()=>{
$tbShopCategory({
page:0,size:200
}).then(res=>{
res.content.unshift({
name:'全部',
id:'',
childrenList:[]
})
category.list=[res.content.reduce((prve, cur) => {
prve.push(...[{
...cur,
name: '' + cur.name,
childrenList:undefined
}, ...cur.childrenList.map(v => {
return {
...v,
name: '' + v.name
}
})])
return prve
}, [])]
console.log(category.list);
})
})
</script>
<style lang="scss" scoped>

View File

@@ -31,23 +31,17 @@
</template>
<script setup>
import {
reactive,
ref,
watch
} from 'vue';
import {
returnSkuSnap,
returnTypeEnum,
returnCategory
} from '@/pageProduct/util.js'
import { reactive, ref, watch } from 'vue';
import {
$updateGrounding,
$updateProductStatus,$updateProductData,
$tbProskuConV2
} from '@/http/yskApi/goods.js'
import {hasPermission} from '@/commons/utils/hasPermission.js'
import { hasPermission } from '@/commons/utils/hasPermission.js'
import infoBox from '@/commons/utils/infoBox.js'
import { productOnOff,productMarkIsSoldOut } from '@/api/product.js'
const props = defineProps({
show: {
type: Boolean,
@@ -86,8 +80,8 @@
watch(() => props.show, (newval) => {
popShow.value = newval
if (newval) {
console.log(props.goods);
data.value = props.goods
console.log(props.goods)
isPauseSale.value = props.goods.isPauseSale
isGrounding.value = props.goods.isGrounding
}
@@ -131,9 +125,11 @@
if(!canShangXiaJia.value){
return
}
await upDateGoods({
key:'grounding',
value: e
console.log(e);
await productOnOff({
id: data.value.id,
type:'sku',
isSale: e
})
emits('isGroundingChange', e)
infoBox.showToast('更新成功')
@@ -144,9 +140,10 @@
return
}
console.log(e);
await upDateGoods({
key:'pauseSale',
value: e
await productMarkIsSoldOut({
id: data.value.id,
type:'sku',
isSoldOut: e
})
emits('isPauseSaleChange', e)
infoBox.showToast('更新成功')

View File

@@ -12,7 +12,6 @@
</view>
</view>
<view>
<!-- <text class="u-font-28 color-666" @click="changeClick">修改</text> -->
<text class="u-font-28 color-666" @click="changePrice">改价</text>
<text class="u-font-28 color-red u-m-l-24" @click="baosun">报损</text>
</view>
@@ -37,7 +36,7 @@
custom-style="background-color: #318AFE;" :text="data.typeEnum"></uni-tag> -->
</view>
<view class="u-font-32">
<text v-if="data.typeEnum=='单规格'">¥</text>
<text v-if="data.type=='single'">¥</text>
<text>{{data.lowPrice}}</text>
<!-- <text>¥</text>
<text>{{data.lowPrice}}</text>
@@ -50,18 +49,11 @@
<view class="u-font-24 info-p-l u-m-t-6">规格</view>
<view class="skd" v-for="(item,index) in data.skuList" :key="index"
@click="guigeClick(index)">
<text>{{item.specSnap||item.name}}</text>
<text>{{item.specInfo}}</text>
<view class="tag-primary tag" v-if="item.isGrounding">上架中</view>
<view class="tag-gray tag" v-if="item.isPauseSale">已售罄</view>
<view class="tag-gray tag" v-if="!item.isGrounding">已下架</view>
<!-- <template v-if="item.isPauseSale">
<view class="tag-gray tag" >已售罄</view>
</template>
<template v-else>
<view class="tag-primary tag" v-if="item.isGrounding">上架中</view>
<view class="tag-gray tag" v-else>已下架</view>
</template> -->
</view>
</view>
@@ -89,23 +81,15 @@
</view>
</view>
<!-- <view class="u-m-t-16 skus u-text-center" v-if="data.skuList.length>=2">
<view class="u-flex u-flex-wrap skds">
<view class="skd" v-for="(item,index) in data.skuList" :key="index"><text>{{item.specSnap}}</text>
<view class="tag-primary tag">上架中</view>
</view>
</view>
</view> -->
<view class="u-m-t-24 u-flex u-row-between">
<view class="u-flex">
<view class="u-flex">
<view class="u-m-r-18 color-999">售罄</view>
<my-switch disabled v-model="isPauseSale" :openDisabledClass="false" @click="isPauseSaleChange"></my-switch>
<my-switch disabled v-model="isSoldStock" :openDisabledClass="false" @click="isSoldStockChange"></my-switch>
</view>
<view class="u-flex u-m-l-30">
<view class="u-m-r-18 color-999">上架产品</view>
<my-switch disabled v-model="isGrounding" :openDisabledClass="false" @click="isGroundingChange"></my-switch>
<my-switch disabled v-model="isSale" :openDisabledClass="false" @click="isSaleChange"></my-switch>
</view>
</view>
<view class="u-flex">
@@ -119,21 +103,11 @@
</template>
<script setup>
import {
computed,
ref,
watch,
watchEffect
} from 'vue';
import {
$goodsIsHot,
$tbProskuConV2,$updateProductData
} from '@/http/yskApi/goods.js'
import { computed, ref, watch } from 'vue';
import { updateProduct,productOnOff,productMarkIsSoldOut } from '@/api/product.js'
import go from '@/commons/utils/go.js';
import {hasPermission} from '@/commons/utils/hasPermission.js';
import {
ColorMain
} from '@/commons/color.js'
import { ColorMain } from '@/commons/color.js'
const emits = defineEmits(['radioClick', 'changeClick', 'xiajia', 'del', 'changePrice', 'baosun', 'guigeClick','update',
'editStock'
])
@@ -175,7 +149,8 @@
const max=247;
for(let i in props.data.skuList){
const sku=props.data.skuList[i]
width+=(fontSize*sku.name.length+boxWith+gap)
console.log(sku)
width+=(fontSize*sku.specInfo.length+boxWith+gap)
if(width>max){
isOne=false
break;
@@ -189,10 +164,8 @@
}
async function upDateGoods(par) {
const res = await $updateProductData([{
const res = await updateProduct([{
id: props.data.id,
isSku: 0,
shopId: uni.getStorageSync('shopId'),
...par
}])
uni.showToast({
@@ -202,34 +175,58 @@
emits('update')
}
let isPauseSale=ref(props.data.isPauseSale)
let isGrounding=ref(props.data.isGrounding)
watch(() => props.data.isPauseSale, (newval) => {
isPauseSale.value=newval
let isSoldStock=ref(props.data.isSoldStock)
let isSale=ref(props.data.isSale)
watch(() => props.data.isSoldStock, (newval) => {
isSoldStock.value=newval
})
watch(() => props.data.isGrounding, (newval) => {
isGrounding.value=newval
watch(() => props.data.isSale, (newval) => {
isSale.value=newval
})
async function isPauseSaleChange(e) {
/**
* 修改售罄
* @param {Object} e
*/
async function isSoldStockChange(e) {
const res=await hasPermission('允许售罄商品')
if(!res){
return
}
upDateGoods({
key: 'pauseSale',
value: isPauseSale.value?0:1
let res2 = await productMarkIsSoldOut({
id: props.data.id,
type: 'product',
isSoldOut: isSoldStock.value?0:1
})
uni.showToast({
title: '修改成功',
icon: 'none'
})
emits('update')
}
async function isGroundingChange(e) {
/**
* 修改上下价
* @param {Object} e
*/
async function isSaleChange(e) {
const res=await hasPermission('允许上下架商品')
if(!res){
return
}
upDateGoods({
key: 'grounding',
value: isGrounding.value?0:1
let res2 = await productOnOff({
id: props.data.id,
type: 'product',
isSale: isSale.value?0:1
})
uni.showToast({
title: '修改成功',
icon: 'none'
})
emits('update')
}
let checked = ref(false)

View File

@@ -2,9 +2,6 @@
<view class="safe-page min-page">
<up-sticky>
<view class="bg-fff u-p-l-30 u-p-b-30">
<!-- <view class="myTabs ">
<myTabs :list="tabsList" @change="tabsChange"></myTabs>
</view> -->
<view class="input-wrapper">
<view class="input-main">
<view class="u-flex u-p-r-30 u-font-28" @click="onCategoryShowChange(true)">
@@ -36,7 +33,7 @@
</view>
<view class="u-flex u-col-center" @click="go.to('PAGES_PRODUCT_SPECIF_TEMPLATE')">
<image src="/pageProduct/static/images/icon-guige.svg" class="icon-guige" />
<text class="color-666 u-m-l-12 u-font-24">规格模版</text>
<text class="color-666 u-m-l-12 u-font-24">规格</text>
</view>
</view>
@@ -56,7 +53,7 @@
<my-img-empty tips="未找到相关商品"></my-img-empty>
</template>
<template v-if="pageData.goodsList.length">
<my-pagination :page="pageData.query.page+1" :totalElements="pageData.totalElements" :size="pageData.query.size"
<my-pagination :page="pageData.query.page" :totalElements="pageData.totalElements" :size="pageData.query.size"
@change="pageChange"></my-pagination>
</template>
@@ -77,7 +74,7 @@
<view>
<view class="">排序:</view>
<view class="u-m-t-24">
<uni-easyinput v-model="goodsStockData.sort" placeholder="请输入排序"></uni-easyinput>
<uni-easyinput v-model="goodsStockData.orderBy" placeholder="请输入排序"></uni-easyinput>
</view>
</view>
<view class="u-flex u-m-t-32">
@@ -95,13 +92,13 @@
<view class="u-flex u-m-t-32">
<view class="">售罄:</view>
<view class="u-m-l-46 ">
<my-switch v-model="goodsStockData.isPauseSale"></my-switch>
<my-switch v-model="goodsStockData.isSoldStock"></my-switch>
</view>
</view>
<view class="u-flex u-m-t-32">
<view class="">上架:</view>
<view class="u-m-l-46 ">
<my-switch v-model="goodsStockData.isGrounding"></my-switch>
<my-switch v-model="goodsStockData.isSale"></my-switch>
</view>
</view> -->
@@ -176,6 +173,11 @@
$tbProductV2,
$updateProductData
} from "@/http/yskApi/goods.js"
import {
getProductList,
getCategoryList
} from '@/api/product.js'
import {
returnAllCategory
} from '@/pageProduct/util.js'
@@ -195,15 +197,13 @@
totalPage: 0,
goodsList: [],
query: {
page: 0,
page: 1,
size: 10,
createdAt: [],
id: "",
categoryId: '',
name: '',
isPauseSale: '',
sort: "createdAt,desc",
isGrounding: ''
orderBy: "create_time desc",
isSoldStock: '',
isSale: ''
},
category: '',
categoryList: [], //分类列表
@@ -214,10 +214,10 @@
watch(() => pageData.query.categoryId, (newval) => {
getGoodsList()
})
watch(() => pageData.query.isPauseSale, (newval) => {
watch(() => pageData.query.isSoldStock, (newval) => {
getGoodsList()
})
watch(() => pageData.query.isGrounding, (newval) => {
watch(() => pageData.query.isSale, (newval) => {
getGoodsList()
})
const popup = reactive({
@@ -237,7 +237,47 @@
show: false
}
})
onShow(() => {
// getGoodsList()
watchEmitInit()
})
onLoad(() => {
getGoodsList()
getCategory()
})
/**
* 获取商品列表
*/
function getGoodsList() {
pageData.hasAjax = false
getProductList(pageData.query).then(res => {
pageData.hasAjax = true
pageData.goodsList = res.records.map(v => {
return {
...v,
isSellNone: false,
checked: false,
showDetail: false
}
})
pageData.totalElements = res.totalRow
})
}
/**
* 获取商品分类列表
*/
function getCategory () {
getCategoryList({
page: 1,
size: 200
}).then(res => {
pageData.categoryList = returnAllCategory(res)
console.log(pageData.categoryList);
})
}
//报损弹窗展示
function baosunShow(index) {
pageData.selGoodsIndex = index
@@ -246,17 +286,22 @@
popup.baosun.show = true
}
// 修改价格弹窗展示
/**
* 修改价格弹窗展示
* @param {Object} index
*/
function changePriceShow(index) {
pageData.selGoodsIndex = index
const goods = pageData.goodsList[index]
console.log(goods)
goods.skuList = goods.skuList.map(v => {
return {
...v,
_lowPrice: v.lowPrice
}
})
const lowPrice = goods.lowPrice.replace('¥', '') * 1
console.log(goods)
const lowPrice = goods.lowPrice.toString().replace('¥', '') * 1
pageData.selGoods = {
...goods,
lowPrice,
@@ -354,27 +399,31 @@
//修改规格上下架,售罄
function editGuigeShow(goodsIndex, guigeIndex) {
console.log(goodsIndex, guigeIndex);
const goodsGuige = pageData.goodsList[goodsIndex].skuList[guigeIndex]
console.log(goodsIndex, guigeIndex);
popup.guige.data = goodsGuige
popup.guige.goodsIndex = goodsIndex
popup.guige.guigeIndex = guigeIndex
popup.guige.show = true
}
/**
* 规格上下架
* @param {Object} e
*/
function isGroundingChange(e) {
const {
goodsIndex,
guigeIndex
} = popup.guige
const { goodsIndex, guigeIndex } = popup.guige
console.log(goodsIndex,guigeIndex)
pageData.goodsList[goodsIndex].skuList[guigeIndex].isGrounding = e
}
/**
* 规格已售罄
* @param {Object} e
*/
function isPauseSaleChange(e) {
const {
goodsIndex,
guigeIndex
} = popup.guige
const { goodsIndex, guigeIndex } = popup.guige
console.log(goodsIndex,guigeIndex)
pageData.goodsList[goodsIndex].skuList[guigeIndex].isPauseSale = e
}
@@ -388,22 +437,6 @@
pageData.categoryName = category.name
}
function getGoodsList() {
pageData.hasAjax = false
$tbProductV2(pageData.query).then(res => {
pageData.hasAjax = true
console.log(res);
pageData.goodsList = res.content.map(v => {
return {
...v,
isSellNone: false,
checked: false,
showDetail: false
}
})
pageData.totalElements = res.totalElements
})
}
function watchEmitInit() {
uni.$off('update:productIndex')
@@ -419,20 +452,7 @@
})
}
onShow(() => {
// getGoodsList()
watchEmitInit()
})
onLoad(() => {
getGoodsList()
$tbShopCategory({
page: 0,
size: 200
}).then(res => {
pageData.categoryList = returnAllCategory(res.content)
console.log(pageData.categoryList);
})
})
const tabsList = ['简洁', '详情']
const statesTabsList = ['全部', '已售罄', '在售中', '已下架']
@@ -451,7 +471,7 @@
sort: 0,
isStock: false,
isDistribute: false,
isPauseSale: false,
isSoldStock: false,
isGrounding: false,
stockNumber: 0,
})
@@ -516,7 +536,7 @@
function resetQuery() {
pageData.totalElements = 0;
pageData.query.page = 0;
pageData.query.page = 1;
}
async function toGoodsDetail(id) {
@@ -535,23 +555,23 @@
resetQuery()
console.log(index);
if (index == 0) {
pageData.query.isPauseSale = ''
pageData.query.isGrounding = ''
pageData.query.isSoldStock = ''
pageData.query.isSale = ''
return
}
if (index == 1) {
pageData.query.isPauseSale = 1
pageData.query.isGrounding = ''
pageData.query.isSoldStock = 1
pageData.query.isSale = ''
return
}
if (index == 2) {
pageData.query.isPauseSale = ''
pageData.query.isGrounding = 1
pageData.query.isSoldStock = ''
pageData.query.isSale = 1
return
}
if (index == 3) {
pageData.query.isPauseSale = ''
pageData.query.isGrounding = 0
pageData.query.isSoldStock = ''
pageData.query.isSale = 0
return
}
}
@@ -638,7 +658,7 @@
// 页数改变事件
function pageChange(page) {
console.log(page);
pageData.query.page = page - 1
pageData.query.page = page
getGoodsList()
}

View File

@@ -1,128 +0,0 @@
<template>
<view class="item">
<view class="u-flex u-row-between">
<view>#{{index+1}} {{data.name}}</view>
<view class="color-666 u-font-24 id">ID:{{data.id}}</view>
</view>
<view class="u-m-t-16 color-666 u-font-24 u-p-b-24 border-bottom">
添加时间
<uni-dateformat :date="data.createdAt"></uni-dateformat>
</view>
<view class="u-m-t-24">
<view v-for="(spec,specIndex) in data.specList" :key="specIndex">
<view class="font-bold " :class="{'u-m-t-32':specIndex>0}"> {{spec.name}}</view>
<view class="u-m-t-24 bg-gray u-flex u-flex-wrap options u-p-24">
<view class="u-flex option" v-for="(option,optionIndex) in spec.value" :key="optionIndex" @tap="statusClick(optionIndex)">
{{option}}
<!-- <view class="sellout" v-if="option.sellOut">已售罄</view>
<view class="tag-primary tag" v-if="option.status">上架中</view>
<view class="tag-gray tag" v-else>上架中</view> -->
</view>
</view>
</view>
</view>
<view class="u-m-t-20 u-flex u-row-right btns">
<my-button @tap="del" :plain="btnProps.plain" :fontSize="btnProps.fontSize" :width="btnProps.width" :height="btnProps.height" type="cancel" :shape="btnProps.shape" >删除</my-button>
<my-button @tap="edit" :plain="btnProps.plain" :fontSize="btnProps.fontSize" :width="btnProps.width" :height="btnProps.height" :shape="btnProps.shape">编辑</my-button>
</view>
</view>
</template>
<script setup>
import { reactive, ref } from 'vue';
import myButton from "@/components/my-components/my-button.vue"
import go from '@/commons/utils/go.js'
const props=defineProps({
index:{
type:Number,
},
data:{
type:Object,
default:()=>{
return {}
}
}
})
const emits=defineEmits(['del','edit','statusClick'])
function del(){
emits('del',props.index)
}
function edit(){
uni.$emit('edit:spec',props.data)
uni.setStorageSync('spec',props.data)
go.to('PAGES_PRODUCT_GUIGE_ADD', {
type: 'edit'
})
// emits('edit',props.index)
}
function statusClick(optionIndex){
emits('statusClick',[props.index,optionIndex])
}
const btnProps=reactive({
shape:'circle',
width:120,
height:48,
fontSize:24,
plain:true
})
</script>
<style lang="scss" scoped>
.btns{
gap: 0 20rpx;
}
.item{
background: #FFFFFF;
padding: 32rpx 24rpx;
border-radius: 18rpx 18rpx 18rpx 18rpx;
margin-bottom: 30rpx;
.id{
background: #F4F4F4;
padding: 6rpx 10rpx;
border-radius: 8rpx 8rpx 8rpx 8rpx;
}
.options{
gap: 10rpx 50rpx;
.option{
padding: 12rpx 40rpx;
background: #F0F2F5;
border-radius: 4rpx;
font-size: 24rpx;
position: relative;
color: #666;
overflow: hidden;
.tag{
position: absolute;
right: 0;
top: 0;
font-size: 12rpx;
right: 0;
padding: 2rpx 4rpx;
border-radius: 0rpx 4rpx 4rpx 4rpx;
}
.sellout{
position: absolute;
left: 0;
right: 0;
bottom: 0;
background-color: rgb(147, 147, 153);
color: #fff;
text-align: center;
font-size: 20rpx;
}
.tag-primary{
background-color: $my-main-color;
color: #fff;
}
.tag-gray{
background-color: rgb(147, 147, 153);
color: #fff;
}
}
}
}
</style>

View File

@@ -0,0 +1,56 @@
<template>
<view style="display: flex;line-height: 60rpx;align-items: center;justify-content: space-between;" @click="clickNode(data)">
<view style="display: flex;align-items: center;">
<view v-if="data.children && data.children.length">
<uni-icons v-if="data.isOpen" type="bottom" size="16" color="#2A5EFF"></uni-icons>
<uni-icons v-else type="forward" size="16"></uni-icons>
</view>
<view style="padding-left: 10px;">{{ data.name }}</view>
</view>
<view style="display: flex;align-items: center;justify-content: space-between;">
<view @tap.stop="del" style="font-size:24rpx;color: #999;">删除</view>
<view @tap.stop="edit" style="font-size:24rpx;color: #318AFE;margin-left: 20rpx;">编辑</view>
</view>
</view>
<view v-if="data.children && data.children.length && data.isOpen" style="margin-left: 16px;padding: 10rpx;line-height: 60rpx;">
<tree-item v-for="(child,index) in data.children" :key="child.id" :data="child"
@clickNode="clickNode"></tree-item>
</view>
</template>
<script setup>
import { reactive, ref } from 'vue';
import treeItem from './tree-item.vue'
import go from '@/commons/utils/go.js'
const props=defineProps({
data:{
type:Object,
default:()=>{
return {}
}
}
})
const emits=defineEmits(['del','edit'])
function clickNode(item) {
item.isOpen = !item.isOpen
}
function del(){
emits('del',props.index)
}
function edit(){
uni.setStorageSync('spec',props.data)
go.to('PAGES_PRODUCT_GUIGE_ADD', {
type: 'edit'
})
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -1,37 +1,16 @@
<template>
<view class="u-p-30 min-page bg-gray">
<view v-for="(item,index) in pageData.list" :key="index">
<specifications-item @statusClick="specificationsStatusClick" @del="delSpecifications" @edit="editSpecifications" :data="item" :index="index"></specifications-item>
<view class="min-page bg-gray" style="padding: 30rpx 30rpx 200rpx 30rpx;">
<view style="background-color: #fff;border-radius: 10rpx;">
<view style="padding: 10px 10px 0 10px;">
<uni-easyinput suffixIcon="search" v-model="pageData.query.name" placeholder="请输入规格搜索" @iconClick="search"
@blur="search" trim></uni-easyinput>
</view>
<view v-for="(item,index) in pageData.list" :key="index" style="padding: 10rpx;" v-if="pageData.loading">
<tree-item @del="delSpecifications(index)" :data="item" ></tree-item>
</view>
</view>
<view class="u-m-t-44">
<my-pagination :size="pageData.query.size" :totalElements="pageData.totalElements" @change="pageChange"></my-pagination>
<view style="height: 200rpx;"></view>
</view>
<my-model :showBtn="modelData.showBtn" ref="model" @confirm="modelConfirm" :title="modelData.title" :desc="modelData.desc">
<template #desc>
<view class="u-p-30 u-m-t-40 u-p-b-60" v-if="specificationsData">
<view class="u-flex u-row-between">
<view>当前状态</view>
<view class="u-flex-1 u-p-l-60">
<uni-data-checkbox v-model="specificationsData.status"
@change="specificationsStatusChange"
:localdata="statusData"></uni-data-checkbox>
</view>
</view>
<view class="u-m-t-30 u-p-t-30" style="border-top: 1px solid rgb(245, 245, 245);">
<view class="u-flex u-row-between">
<view>售罄</view>
<my-switch @change="specificationsSellOutChange" v-model="specificationsData.sellOut"></my-switch>
</view>
</view>
</view>
</template>
</my-model>
<view class="fixed-b">
<my-button @tap="toAdd" shape="circle">添加规格组</my-button>
</view>
@@ -39,82 +18,97 @@
</template>
<script setup>
import {
reactive,
ref
} from 'vue';
import { reactive, ref } from 'vue';
import {onLoad,onShow} from '@dcloudio/uni-app'
import go from '@/commons/utils/go.js';
import myPagination from '@/components/my-components/my-pagination.vue'
import myModel from '@/components/my-components/my-model.vue'
import myButton from '@/components/my-components/my-button.vue'
import mySwitch from '@/components/my-components/my-switch.vue'
import specificationsItem from './components/specifications-item.vue'
import {$productSpec} from '@/http/yskApi/goods.js'
import treeItem from './components/tree-item.vue'
import { getSpecList,delSpec } from '@/api/product.js'
const statusData=[
{
text: '上架中',
value: 1
},
{
text: '已下架',
value: 0
}
]
const model = ref(null)
const specificationsData=reactive({
index:null,
optionIndex:null,
status:1,
sellOut:false
})
function specificationsSellOutChange(isSellOut){
const {index,optionIndex}=specificationsData
if(index!==null&&optionIndex!==null){
pageData.list[index].options[optionIndex].sellOut=isSellOut
}
}
function specificationsStatusChange(e){
const {index,optionIndex}=specificationsData
if(index!==null&&optionIndex!==null){
pageData.list[index].options[optionIndex].status=e.detail.value
}
}
function modelOpen(){
model.value.open()
}
function modelClose(){
model.value.close()
}
function modelConfirm(){
console.log('modelConfirm');
modelClose()
}
const modelData = reactive({
title: '',
desc: '',
showBtn:true
})
const pageData = reactive({
loading: true,
query:{
page: 0,
size:10
name: ""
},
totalElements:0,
list: []
})
onShow(()=>{
init()
})
function init(){
getSpecList(pageData.query).then(res=>{
pageData.list=res
})
pageData.list.map(item=>{
filterData(item)
})
}
/**
* 搜索
*/
function search() {
if( pageData.query.name == ""){
init()
return false;
}
pageData.loading = false
pageData.list = filterSearch(pageData.list, pageData.query.name || '')
setTimeout(() => {
pageData.loading = true
}, 10)
}
/**
* 搜索数据处理
* @param {Object} data
* @param {Object} keyword
*/
function filterSearch(data, keyword) {
return data.filter(node => {
// 判断当前节点是否匹配筛选条件
if (node.name.includes(keyword)) {
if(!node.type){
node.isOpen=true
}
return true;
}
// 递归过滤子节点
if (node.children && node.children.length) {
node.children = filterSearch(node.children, keyword);
node.isOpen=true
return node.children.length > 0;
}
return false;
});
}
/**
* 请求获取数据处理
* @param {Object} item
*/
function filterData (item) {
item.isOpen = false
if( item.children && item.children.length > 0 ){
item.children.map(item=>{
filterData(item)
})
}
}
/**
* 删除规格
* @param {Object} index
*/
function delSpecifications(index){
uni.showModal({
title: '提示',
content: '删除后使用此模板的商品将取消此规格,是否继续?',
content: '删除后使用此规格的商品将取消此规格,是否继续?',
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
$productSpec.del([pageData.list[index].id]).then(res=>{
delSpec(pageData.list[index].id).then(res=>{
uni.showToast({
title:'删除成功',
icon:'none'
@@ -125,52 +119,15 @@
}
});
}
function specificationsStatusClick(arr){
console.log(arr);
modelData.title=pageData.list[arr[0]].name
modelData.desc=''
modelData.showBtn=false
specificationsData.status=1
specificationsData.sellOut=false
specificationsData.index=arr[0]
specificationsData.optionIndex=arr[1]
// modelOpen()
}
function pageChange(page) {
pageData.query.page=page-1
init()
}
let emitName = 'guigeEdit'
uni.$on(emitName, function(data) {
console.log(data);
})
function editSpecifications(index){
uni.setStorageSync('guige', pageData.list[index])
emitName='guigeEdit'
go.to('PAGES_PRODUCT_GUIGE_ADD', {
emitName: emitName
})
}
/**
* 新增规格
*/
function toAdd() {
// uni.setStorageSync('guige', FormData.specificationsGroup)
go.to('PAGES_PRODUCT_GUIGE_ADD')
}
function init(){
$productSpec.get(pageData.query).then(res=>{
console.log(res);
pageData.list=res.content
pageData.totalElements=res.totalElements
})
}
onShow(()=>{
init()
})
</script>
<style lang="scss">

View File

@@ -29,12 +29,14 @@ export function returnAllCategory(arr) {
...cur,
name: '' + cur.name,
childrenList: undefined
}, ...cur.childrenList.map(v => {
return {
...v,
name: '' + v.name
}
})])
},
// ...cur.childrenList.map(v => {
// return {
// ...v,
// name: '' + v.name
// }
// })
])
return prve
}, [])
return result