update 经营

This commit is contained in:
qijq 2025-07-11 00:19:56 +08:00
parent 7d852a9a10
commit d8c90bd3a1
45 changed files with 7977 additions and 493 deletions

View File

@ -4,24 +4,20 @@
"version" : "0.0",
"configurations" : [
{
"app-plus" :
{
"launchtype" : "remote"
},
"default" :
{
"launchtype" : "local"
},
"h5" :
{
"launchtype" : "local"
},
"mp-weixin" :
{
"launchtype" : "local"
},
"provider" : "aliyun",
"type" : "uniCloud"
"app-plus" : {
"launchtype" : "remote"
},
"default" : {
"launchtype" : "local"
},
"h5" : {
"launchtype" : "local"
},
"mp-weixin" : {
"launchtype" : "local"
},
"provider" : "aliyun",
"type" : "uniCloud"
},
{
"playground" : "custom",

View File

@ -25,6 +25,95 @@ export function GetOrderList(params) {
});
}
/**
* 获取退货订单列表
* @author Seven
* @data 2025-3-28
* @param {
* storeId: 1, //店铺Id
* keyword: 'DD-', //搜索订单关键字
* pageNum: 1, //页码
* pageSize: 10, //页大小
* delivery: 1, // 1-同城配送2-物流配送
* status: 1, 1-进行中2-超时的订单3-退款的订单
* }
* @returns { }
* @see https://mall.gpxscs.cn/api/admin/shop/shop-order-return/list?pageNum=1&pageSize=20&order_id=&return_id=&startDate=&endDate=&source_lang=zh_CN
*/
export function GetSalesReturnOrderList(params) {
return http({
url: "/shop/shop-order-return/list",
method: "get",
params,
baseURL: config.adminApi,
});
}
/**
* 获取退货订单详情
* @author Seven
* @data 2025-3-28
* @param {
* return_id: FX-20241223-4 退货订单编号
* }
* @returns { }
* @see https://mall.gpxscs.cn/api/admin/shop/shop-order-return/get?return_id=FX-20241223-4&source_lang=zh_CN
*/
export function GetSalesReturnOrderDetails(params) {
return http({
url: "/shop/shop-order-return/get",
method: "get",
params,
baseURL: config.adminApi,
});
}
/**
* 退货订单不通过
* @author Seven
* @data 2025-3-28
* @param {
* return_store_message: "" , 备注
* return_id: FX-20241223-4 退货订单编号
* }
* @returns { }
* @see https://mall.gpxscs.cn/api/admin/shop/shop-order-return/refused?source_lang=zh_CN
*/
export function GetSalesReturnOrderNoPass(params) {
return http({
url: "/shop/shop-order-return/refused",
method: "post",
params,
baseURL: config.adminApi,
});
}
/**
* 退货订单不通过
* @author Seven
* @data 2025-3-28
* @param {
* return_flag 0 不用退货 1需要退货
* return_store_message: "" , 备注
* receiving_address2
* return_id: FX-20241223-4 退货订单编号
* }
* @returns { }
* @see https://mall.gpxscs.cn/api/admin/shop/shop-order-return/review?source_lang=zh_CN
*/
export function GetSalesReturnOrderPass(params) {
return http({
url: "/shop/shop-order-return/review",
method: "post",
params,
baseURL: config.adminApi,
});
}
/**
* 获取订单列表 模拟数据
**/

View File

@ -0,0 +1,72 @@
import http from "../../utils/http";
import config from "../../config/config";
/**
*
* @author Seven
* @data 2025-7-4
* @returns { }
* @see https://mall.gpxscs.cn/api/admin/shop/shop-base-product-category/tree?source_lang=zh_CN
*/
export function GetProductCategoryTree() {
return http({
url: "/shop/shop-base-product-category/tree",
method: "get",
baseURL: config.adminApi,
});
}
/**
*
* @author Seven
* @data 2025-7-4
* @param { pageNum pageSize kind_id product_src category_id }
* @returns { }
* @see https://mall.gpxscs.cn/api/admin/shop/shop-product-base/list?pageNum=1&pageSize=20&kind_id=1201,1202,1203&product_src=false&category_id=&source_lang=zh_CN
*/
export function GetProductList(params) {
return http({
url: "/shop/shop-product-base/list",
method: "get",
params,
baseURL: config.adminApi,
});
}
/**
*
* @author Seven
* @data 2025-7-6
* @param { pageNum pageSize kind_id product_src category_id }
* @returns { }
* @see https://mall.gpxscs.cn/api/admin/shop/shop-product-base/editState?source_lang=zh_CN
*/
export function UpdateProductPutaway(params) {
return http({
url: "/shop/shop-product-base/editState",
method: "post",
params,
baseURL: config.adminApi,
});
}
/**
*
* @author Seven
* @data 2025-7-6
* @param { product_id }
* @returns { }
* @see https://mall.gpxscs.cn/api/admin/shop/shop-product-base/deleteBatch
*/
export function DelectCommodity(params) {
return http({
url: "/shop/shop-product-base/deleteBatch",
method: "post",
params,
baseURL: config.adminApi,
});
}

View File

@ -25,6 +25,22 @@
color="#000"
></u-icon>
</u-tabbar-item>
<u-tabbar-item text="经营" name="warehouse">
<u-icon
class="u-icon"
custom-prefix="custom-icon-jingyingguanli custom-icon"
size="22"
slot="active-icon"
color="#fe4119"
></u-icon>
<u-icon
class="u-icon"
custom-prefix="custom-icon-jingyingguanli custom-icon"
size="22"
slot="inactive-icon"
color="#000"
></u-icon>
</u-tabbar-item>
<u-tabbar-item text="消息" name="IM" :badge="weiduNum">
<u-icon
class="u-icon"
@ -142,8 +158,14 @@ export default {
url: "/pages/order/order",
});
break;
case "warehouse":
uni.switchTab({
url: "/pages/warehouse/warehouse",
});
break;
case "IM":
// #ifdef APP-PLUS
//
let result = await permission.premissionCheck(
"CAMERA_EXTERNAL_STORAGE_RECORD_AUDIO"
); //使

View File

@ -0,0 +1,212 @@
<template>
<view class="tui-gallery" :class="{'tui-gallery_show':show}" @tap="hideGallery">
<view class="tui-gallery__info">{{currentIndex+1}}/{{getLen}}</view>
<swiper class="tui-gallery__img__wrap" :indicator-dots="false" @change="change" :current="defCurIndex"
:autoplay="false" :duration="500">
<swiper-item v-for="(item,index) in imgUrls" :key="index">
<image mode="aspectFit" class="tui-gallery__img" :src="item[srcField]"></image>
</swiper-item>
</swiper>
<view class="tui-gallery__desc" v-if="!showDelete">
{{getDesc(currentIndex,imgUrls)}}
</view>
<view class="tui-gallery__operate" hover-class="tui-opacity__del" :hover-start-time="150" @tap.stop="deleteImg"
v-if="showDelete">
删除
</view>
</view>
</template>
<script>
export default {
name: 'tuiGallery',
emits: ['change', 'delete', 'hide'],
props: {
urls: {
type: Array,
default () {
return []
}
},
srcField: {
type: String,
default: 'src'
},
descField: {
type: String,
default: 'desc'
},
showDelete: {
type: Boolean,
default: false
},
show: {
type: Boolean,
default: false
},
current: {
type: Number,
default: 0
},
hideOnClick: {
type: Boolean,
default: true
}
},
computed: {
getLen() {
return this.imgUrls.length
}
},
watch: {
urls(newVal, oldVal) {
this.imgUrls = newVal
},
current(newVal) {
this.defCurIndex = this.currentIndex;
let val = Number(newVal)
setTimeout(() => {
this.defCurIndex = val;
this.currentIndex = val;
}, 20)
}
},
mounted() {
this.defCurIndex = Number(this.current);
this.currentIndex = this.defCurIndex;
this.imgUrls = this.urls;
},
data() {
return {
imgUrls: [],
currentIndex: 0,
defCurIndex: 0
};
},
methods: {
getDesc(index, imgUrls) {
let desc = ''
let item = imgUrls[index]
if (item) {
desc = item[this.descField]
}
return desc
},
change(e) {
this.currentIndex = e.detail.current
this.$emit('change', {
current: e.detail.current
});
},
deleteImg() {
const imgs = this.imgUrls;
const url = imgs.splice(this.current, 1);
this.$emit('delete', {
url: url[0],
index: this.current
});
if (imgs.length === 0) {
this.hideGallery();
return;
}
this.currentIndex = 0;
this.imgUrls = imgs
},
hideGallery() {
if (this.hideOnClick) {
this.$emit('hide', {});
}
}
}
}
</script>
<style scoped>
.tui-gallery {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #000;
z-index: 1000;
display: none;
}
.tui-gallery__img,
.tui-gallery__operate,
.tui-gallery__desc {
position: absolute;
left: 0;
left: constant(safe-area-inset-left);
left: env(safe-area-inset-left);
right: 0;
right: constant(safe-area-inset-right);
right: env(safe-area-inset-right)
}
.tui-gallery__img {
width: 100%;
height: 100%;
top: 0;
top: constant(safe-area-inset-top);
top: env(safe-area-inset-top);
bottom: 60px;
bottom: calc(60px + constant(safe-area-inset-bottom));
bottom: calc(60px + env(safe-area-inset-bottom));
background: 50% no-repeat;
background-size: contain
}
.tui-gallery__operate,
.tui-gallery__desc {
position: absolute;
bottom: 0;
padding-bottom: 0;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
background-color: #0d0d0d;
color: #fff;
line-height: 60px;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding: 0 30rpx;
box-sizing: border-box;
z-index: 10;
}
.tui-gallery__info {
color: #fff;
font-size: 17px;
line-height: 60px;
min-height: 60px;
text-align: center
}
.tui-gallery__img__wrap {
-webkit-box-flex: 1;
-webkit-flex: 1;
flex: 1;
position: relative;
font-size: 0
}
.tui-gallery__operate {
position: static
}
.tui-gallery_show {
display: flex !important;
flex-direction: column !important;
flex-wrap: nowrap !important;
}
.tui-opacity__del {
opacity: 0.5;
}
</style>

View File

@ -0,0 +1,258 @@
<template>
<view class="tui-navigation-bar"
:class="{ 'tui-bar-line': opacity > 0.85 && splitLine, 'tui-navbar-fixed': isFixed, 'tui-backdrop__filter': backdropFilter && dropDownOpacity > 0 }"
:style="{ height: height + 'px', background: isOpacity? `rgba(${background},${opacity})`:background, opacity: dropDownOpacity, zIndex: isFixed ? zIndex : 'auto' }">
<view class="tui-status-bar" :style="{ height: statusBarHeight + 'px' }" v-if="isImmersive"></view>
<view class="tui-navigation_bar-title"
:style="{ opacity: transparent || opacity >= maxOpacity ? 1 : opacity, color: color, paddingTop: top - statusBarHeight + 'px' }"
v-if="title && !isCustom">
{{ title }}
</view>
<slot></slot>
</view>
</template>
<script>
export default {
name: 'tuiNavigationBar',
emits: ['init', 'change'],
props: {
//NavigationBar
title: {
type: String,
default: ''
},
//NavigationBar
color: {
type: String,
default: '#333'
},
//NavigationBar,rgb
backgroundColor: {
type: String,
default: '#fff'
},
//线
splitLine: {
type: Boolean,
default: false
},
//
isOpacity: {
type: Boolean,
default: true
},
// 0-1
maxOpacity: {
type: [Number, String],
default: 1
},
// isOpacitymaxOpacity
transparent: {
type: Boolean,
default: false
},
//
scrollTop: {
type: [Number, String],
default: 0
},
/*
isOpacity 为true时生效
opacity=scrollTop /windowWidth * scrollRatio
*/
scrollRatio: {
type: [Number, String],
default: 0.3
},
//header
isCustom: {
type: Boolean,
default: false
},
//
isImmersive: {
type: Boolean,
default: true
},
isFixed: {
type: Boolean,
default: true
},
//[]
backdropFilter: {
type: Boolean,
default: false
},
//NavigationBarios
dropDownHide: {
type: Boolean,
default: false
},
//z-index
zIndex: {
type: [Number, String],
default: 996
}
},
watch: {
scrollTop(newValue, oldValue) {
if (this.isOpacity && !this.transparent) {
this.opacityChange();
}
},
backgroundColor(val) {
if (val) {
if (this.isOpacity) {
this.background = this.hexToRgb(val);
} else {
this.background = this.transparent ? 'rgba(0, 0, 0, 0)' : val
}
}
}
},
data() {
return {
width: 375, //header
left: 375, //
height: 44, //header
top: 0,
scrollH: 1, //,opacity
opacity: 1, //0-1
statusBarHeight: 0, //
background: '255,255,255', //header
dropDownOpacity: 1
};
},
created() {
this.dropDownOpacity = this.backdropFilter && 0;
this.opacity = this.isOpacity || this.transparent ? 0 : this.maxOpacity;
if (this.isOpacity) {
this.background = this.hexToRgb(this.backgroundColor);
} else {
this.background = this.transparent ? 'rgba(0, 0, 0, 0)' : this.backgroundColor
}
let obj = {};
// #ifdef MP-WEIXIN
obj = wx.getMenuButtonBoundingClientRect();
// #endif
// #ifdef MP-BAIDU
obj = swan.getMenuButtonBoundingClientRect();
// #endif
// #ifdef MP-ALIPAY
my.hideAddToDesktopMenu();
// #endif
uni.getSystemInfo({
success: res => {
this.statusBarHeight = res.statusBarHeight;
this.width = res.windowWidth;
this.left = obj.left || res.windowWidth;
if (this.isImmersive) {
this.height = obj.top ? obj.top + obj.height + 8 : res.statusBarHeight + 44;
}
this.scrollH = res.windowWidth * this.scrollRatio;
this.top = obj.top ? obj.top + (obj.height - 32) / 2 : res.statusBarHeight + 6;
this.$emit('init', {
width: this.width,
height: this.height,
left: this.left,
top: this.top,
statusBarHeight: this.statusBarHeight,
opacity: this.opacity,
windowHeight: res.windowHeight
});
}
});
},
methods: {
hexToRgb(hex) {
let rgb = '255,255,255';
if (hex && ~hex.indexOf('#')) {
if (hex.length === 4) {
let text = hex.substring(1, 4);
hex = '#' + text + text;
}
let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
if (result) {
rgb = `${parseInt(result[1], 16)},${parseInt(result[2], 16)},${parseInt(result[3], 16)}`;
}
}
return rgb;
},
opacityChange() {
if (this.dropDownHide) {
if (this.scrollTop < 0) {
if (this.dropDownOpacity > 0) {
this.dropDownOpacity = 1 - Math.abs(this.scrollTop) / 30;
}
} else {
this.dropDownOpacity = 1;
}
}
let scroll = this.scrollTop <= 1 ? 0 : this.scrollTop;
let opacity = scroll / this.scrollH;
if ((this.opacity >= this.maxOpacity && opacity >= this.maxOpacity) || (this.opacity == 0 && opacity ==
0)) {
return;
}
this.opacity = opacity > this.maxOpacity ? this.maxOpacity : opacity;
if (this.backdropFilter) {
this.dropDownOpacity = this.opacity >= this.maxOpacity ? 1 : this.opacity;
}
this.$emit('change', {
opacity: this.opacity
});
}
}
};
</script>
<style scoped>
.tui-navigation-bar {
width: 100%;
transition: opacity 0.4s;
}
.tui-backdrop__filter {
/* Safari for macOS & iOS */
-webkit-backdrop-filter: blur(15px);
/* Google Chrome */
backdrop-filter: blur(15px);
}
.tui-navbar-fixed {
position: fixed;
left: 0;
top: 0;
transform: translateZ(0);
}
.tui-status-bar {
width: 100%;
}
.tui-navigation_bar-title {
width: 100%;
font-size: 17px;
line-height: 17px;
/* #ifndef APP-PLUS */
font-weight: 500;
/* #endif */
height: 32px;
display: flex;
align-items: center;
justify-content: center;
}
.tui-bar-line::after {
content: '';
position: absolute;
border-bottom: 1rpx solid #eaeef1;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
bottom: 0;
right: 0;
left: 0;
}
</style>

View File

@ -0,0 +1,613 @@
<template>
<view class="tui-upload__container">
<view class="tui-upload-box">
<view class="tui-image-item" :style="{width:width+'rpx',height:height+'rpx',borderRadius:radius+'rpx'}"
v-for="(item,index) in imageList" :key="index">
<image :src="item" class="tui-item-img"
:style="{width:width+'rpx',height:height+'rpx',borderRadius:radius+'rpx'}"
@tap.stop="previewImage(index)" mode="aspectFill"></image>
<view v-if="!forbidDel" class="tui-img-del" :style="{background:getDelColor}"
@tap.stop="delImage(index)">
</view>
<view v-if="statusArr[index]!=1" class="tui-upload-mask">
<view class="tui-upload-loading" v-if="statusArr[index]==2"></view>
<text class="tui-tips">{{statusArr[index]==2?'上传中...':'上传失败'}}</text>
<view class="tui-mask-btn" v-if="statusArr[index]==3" @tap.stop="reUpLoad(index)"
hover-class="tui-btn-hover" :hover-stay-time="150">重新上传</view>
</view>
</view>
<view v-if="isShowAdd" class="tui-upload-add"
:class="[borderColor!=='transparent'?'tui-upload__border':'tui-upload__unborder']"
:style="{width:width+'rpx',height:height+'rpx',background:background,borderRadius:radius+'rpx',borderColor:borderColor,borderStyle:borderSytle}"
@tap="chooseImage">
<slot>
<view class="tui-upload-icon tui-icon-plus" :style="{color:addColor,fontSize:addSize+'rpx'}"></view>
</slot>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'tuiUpload',
emits: ['remove', 'complete', 'reupload'],
props: {
//
width: {
type: [Number, String],
default: 218
},
//
height: {
type: [Number, String],
default: 218
},
//
value: {
type: Array,
default () {
return []
}
},
//2.3.0+
radius: {
type: [Number, String],
default: 0
},
//2.3.0+
background: {
type: String,
default: '#F7F7F7'
},
//2.3.0+
borderColor: {
type: String,
default: 'transparent'
},
//2.3.0+
//soliddasheddotted
borderSytle: {
type: String,
default: 'dashed'
},
//2.3.0+
delColor: {
type: String,
default: ''
},
//
delConfirm: {
type: Boolean,
default: false
},
//
forbidDel: {
type: Boolean,
default: false
},
//V2.9.6+ @complete
delTrigger:{
type: Boolean,
default: true
},
//2.3.0+
addColor: {
type: String,
default: '#888'
},
//2.3.0+
addSize: {
type: [Number, String],
default: 68
},
//
forbidAdd: {
type: Boolean,
default: false
},
//
serverUrl: {
type: String,
default: ""
},
//
limit: {
type: Number,
default: 9
},
//original compressed
sizeType: {
type: Array,
default () {
return ['original', 'compressed']
}
},
//album camera 使使
sourceType: {
type: Array,
default () {
return ['album', 'camera']
}
},
// Array<String> ['jpg','png','gif']
imageFormat: {
type: Array,
default () {
return []
}
},
// MB
size: {
type: Number,
default: 4
},
//key file
fileKeyName: {
type: String,
default: "file"
},
//HTTP Header, header Referer
header: {
type: Object,
default () {
return {}
}
},
//HTTP form data
formData: {
type: Object,
default () {
return {}
}
},
//
params: {
type: [Number, String],
default: 0
}
},
data() {
return {
//
imageList: [],
tempFiles: [],
//1- 2- 3-
statusArr: [],
//
callUpload: false
}
},
created() {
this.initImages()
},
watch: {
value(val) {
if (val) {
this.initImages()
}
}
},
computed: {
isShowAdd() {
let isShow = true;
if (this.forbidAdd || (this.limit && this.imageList.length >= this.limit)) {
isShow = false;
}
return isShow
},
getDelColor() {
return this.delColor || (uni && uni.$tui && uni.$tui.color.danger) || '#EB0909';
}
},
methods: {
initImages() {
this.statusArr = [];
this.imageList = [...this.value];
let tempFiles = []
for (let item of this.imageList) {
this.statusArr.push("1")
tempFiles.push({
path: item
})
}
this.tempFiles = tempFiles;
},
//
reUpLoad(index) {
this.$set(this.statusArr, index, "2")
this.$emit('reupload', {
index
})
if (!this.callUpload) {
this.uploadImage(index, this.imageList[index]).then(() => {
this.change()
}).catch(() => {
this.change()
})
}
},
/**
* @param manual 是否手动上传
**/
change(manual = false) {
let status = ~this.statusArr.indexOf("2") ? 2 : 1
if (status != 2 && ~this.statusArr.indexOf("3")) {
//
status = 3
}
this.$emit('complete', {
status: status,
imgArr: this.imageList,
params: this.params,
manual: manual
})
},
toast(text) {
text && uni.showToast({
title: text,
icon: "none"
});
},
chooseImage: function() {
let _this = this;
uni.chooseImage({
count: _this.limit - _this.imageList.length,
sizeType: _this.sizeType,
sourceType: _this.sourceType,
success: function(e) {
let imageArr = [];
for (let i = 0; i < e.tempFiles.length; i++) {
let len = _this.imageList.length;
if (len >= _this.limit) {
_this.toast(`最多可上传${_this.limit}张图片`);
break;
}
//
let path = e.tempFiles[i].path;
if (_this.imageFormat.length > 0) {
let format = ""
// #ifdef H5
let type = e.tempFiles[i].type;
format = type.split('/')[1]
// #endif
// #ifndef H5
format = path.split(".")[(path.split(".")).length - 1];
// #endif
if (_this.imageFormat.indexOf(format) == -1) {
let text = `只能上传 ${_this.imageFormat.join(',')} 格式图片!`
_this.toast(text);
continue;
}
}
//
let size = e.tempFiles[i].size;
if (_this.size * 1024 * 1024 < size) {
let err = `单张图片大小不能超过:${_this.size}MB`
_this.toast(err);
continue;
}
imageArr.push(path)
_this.imageList.push(path)
_this.tempFiles.push(e.tempFiles[i])
_this.statusArr.push("2")
}
_this.change()
let start = _this.imageList.length - imageArr.length
for (let j = 0; j < imageArr.length; j++) {
let index = start + j
//
if (_this.serverUrl) {
_this.uploadImage(index, imageArr[j]).then(() => {
_this.change()
}).catch(() => {
_this.change()
})
} else {
//
_this.$set(_this.statusArr, index, "1")
_this.change()
}
}
}
})
},
uploadImage: function(index, url, serverUrl) {
let _this = this;
return new Promise((resolve, reject) => {
uni.uploadFile({
url: this.serverUrl || serverUrl,
name: this.fileKeyName,
header: this.header,
formData: this.formData,
filePath: url,
success: function(res) {
if (res.statusCode == 200) {
//
let d = JSON.parse(res.data.replace(/\ufeff/g, "") || "{}")
//code
if (d.code % 100 === 0) {
// d.url
d.url && (_this.imageList[index] = d.url)
_this.$set(_this.statusArr, index, d.url ? "1" : "3")
} else {
//
_this.$set(_this.statusArr, index, "3")
}
resolve(index)
} else {
_this.$set(_this.statusArr, index, "3")
reject(index)
}
},
fail: function(res) {
_this.$set(_this.statusArr, index, "3")
reject(index)
}
})
})
},
delImage: function(index) {
let that = this
if (this.delConfirm) {
uni.showModal({
title: '提示',
content: '确认删除该图片吗?',
showCancel: true,
cancelColor: "#555",
confirmColor: "#eb0909",
confirmText: "确定",
success(res) {
if (res.confirm) {
that.imageList.splice(index, 1)
that.tempFiles.splice(index, 1)
that.statusArr.splice(index, 1)
that.$emit("remove", {
index: index,
params: that.params
})
that.delTrigger && that.change()
}
}
})
} else {
that.imageList.splice(index, 1)
that.tempFiles.splice(index, 1)
that.statusArr.splice(index, 1)
that.$emit("remove", {
index: index,
params: that.params
})
that.delTrigger && that.change()
}
},
previewImage: function(index) {
if (!this.imageList.length) return;
uni.previewImage({
current: this.imageList[index],
loop: true,
urls: this.imageList
})
},
/**
* 当属性serverUrl传空时父级调用该方法一次性上传所有图片
* @param serverUrl 服务器接口地址
**/
uploadAllImage(serverUrl) {
if (!serverUrl) {
this.toast('服务器接口地址不能为空!');
return;
}
let imageArr = [...this.imageList]
const len = imageArr.length
for (let i = 0; i < len; i++) {
//
if (imageArr[i].startsWith('https')) {
continue;
} else {
this.$set(this.statusArr, i, "2")
this.uploadImage(i, imageArr[i], serverUrl).then(() => {
if (i === len - 1) {
this.change(true)
}
}).catch(() => {
if (i === len - 1) {
this.change(true)
}
})
}
}
},
upload(callback, index) {
// Promise
//1- 2- 3-
this.callUpload = true;
if (index === undefined || index === null) {
let urls = [...this.imageList]
const len = urls.length
for (let i = 0; i < len; i++) {
if (urls[i].startsWith('https')) {
continue;
} else {
this.$set(this.statusArr, i, "2")
if (typeof callback === 'function') {
callback(this.tempFiles[i]).then(res => {
this.$set(this.statusArr, i, '1')
this.imageList[i] = res
this.change(true)
}).catch(err => {
this.$set(this.statusArr, i, '3')
})
}
}
}
} else {
//index
this.$set(this.statusArr, index, "2")
if (typeof callback === 'function') {
callback(this.tempFiles[index]).then(res => {
this.$set(this.statusArr, index, '1')
this.imageList[index] = res
this.change(true)
}).catch(err => {
this.$set(this.statusArr, index, '3')
})
}
}
}
}
}
</script>
<style scoped>
@font-face {
font-family: 'tuiUpload';
src: url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAATcAA0AAAAAByQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAAEwAAAABoAAAAciR52BUdERUYAAASgAAAAHgAAAB4AKQALT1MvMgAAAaAAAABCAAAAVjxvR/tjbWFwAAAB+AAAAEUAAAFK5ibpuGdhc3AAAASYAAAACAAAAAj//wADZ2x5ZgAAAkwAAADXAAABAAmNjcZoZWFkAAABMAAAAC8AAAA2FpiS+WhoZWEAAAFgAAAAHQAAACQH3QOFaG10eAAAAeQAAAARAAAAEgwAACBsb2NhAAACQAAAAAwAAAAMAEoAgG1heHAAAAGAAAAAHwAAACABEgA2bmFtZQAAAyQAAAFJAAACiCnmEVVwb3N0AAAEcAAAACgAAAA6OMUs4HjaY2BkYGAAYo3boY/i+W2+MnCzMIDAzb3qdQj6fwPzf+YGIJeDgQkkCgA/KAtvAHjaY2BkYGBu+N/AEMPCAALM/xkYGVABCwBZ4wNrAAAAeNpjYGRgYGBl0GJgZgABJiDmAkIGhv9gPgMADTABSQB42mNgZGFgnMDAysDA1Ml0hoGBoR9CM75mMGLkAIoysDIzYAUBaa4pDA7PGJ9xMjf8b2CIYW5gaAAKM4LkANt9C+UAAHjaY2GAABYIVmBgAAAA+gAtAAAAeNpjYGBgZoBgGQZGBhBwAfIYwXwWBg0gzQakGRmYnjE+4/z/n4EBQksxSf6GqgcCRjYGOIeRCUgwMaACRoZhDwCiLwmoAAAAAAAAAAAAAAAASgCAeNpdjkFKw0AARf/vkIR0BkPayWRKQZtYY90ohJju2kOIbtz0KD1HVm50UfEmWXoAr9ADOHFARHHzeY//Fx8Ci+FJfIgdJFa4AhgiMshbrCuIsLxhFJZVs+Vl1bT1GddtbXTC3OhohN4dg4BJ3zMJAnccyfm468ZzHXddrH9ZKbHzdf9n/vkY/xv9sPQXgGEvBrHHwst5kTbXLE+YpYVPkxepPmW94W16UbdNJd6f3SAzo5W7m1jaKd+8ZZIvk5nlKw9SK6Wle7BLS3f/bTzQLmfAF2T1NsQAeNp9kD1OAzEQhZ/zByQSQiCoXVEA2vyUKRMp9Ailo0g23pBo1155nUg5AS0VB6DlGByAGyDRcgpelkmTImvt6PObmeexAZzjGwr/3yXuhBWO8ShcwREy4Sr1F+Ea+V24jhY+hRvUf4SbuFUD4RYu1BsdVO2Eu5vSbcsKZxgIV3CKJ+Eq9ZVwjfwqXMcVPoQb1L+EmxjjV7iFa2WpDOFhMEFgnEFjig3jAjEcLJIyBtahOfRmEsxMTzd6ETubOBso71dilwMeaDnngCntPbdmvkon/mDLgdSYbh4FS7YpjS4idCgbXyyc1d2oc7D9nu22tNi/a4E1x+xRDWzU/D3bM9JIbAyvkJI18jK3pBJTj2hrrPG7ZynW814IiU68y/SIx5o0dTr3bmniwOLn8owcfbS5kj33qBw+Y1kIeb/dTsQgil2GP5PYcRkAAAB42mNgYoAALjDJyIAOWMGiTIxMjMxsKak5qSWpbFmZiRmJ+QAmgAUIAAAAAf//AAIAAQAAAAwAAAAWAAAAAgABAAMABAABAAQAAAACAAAAAHjaY2BgYGQAgqtL1DlA9M296nUwGgA+8QYgAAA=) format('woff');
font-weight: normal;
font-style: normal;
}
.tui-upload-icon {
font-family: "tuiUpload" !important;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
padding: 10rpx;
}
.tui-icon-delete:before {
content: "\e601";
}
.tui-icon-plus:before {
content: "\e609";
}
.tui-upload-box {
width: 100%;
display: flex;
flex-wrap: wrap;
}
.tui-upload-add {
font-weight: 100;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
overflow: hidden;
box-sizing: border-box;
/* #ifdef H5 */
cursor: pointer;
/* #endif */
}
.tui-upload__unborder {
border-width: 0;
}
.tui-upload__border {
border-width: 1px;
}
.tui-image-item {
position: relative;
margin-right: 20rpx;
margin-bottom: 20rpx;
flex-shrink: 0;
}
.tui-item-img {
display: block;
}
.tui-img-del {
width: 36rpx;
height: 36rpx;
position: absolute;
right: -12rpx;
top: -12rpx;
border-radius: 50%;
color: white;
font-size: 34rpx;
z-index: 5;
/* #ifdef H5 */
cursor: pointer;
/* #endif */
}
.tui-img-del::before {
content: '';
width: 16rpx;
height: 1px;
position: absolute;
left: 10rpx;
top: 18rpx;
background-color: #fff;
}
.tui-upload-mask {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40rpx 0;
box-sizing: border-box;
background-color: rgba(0, 0, 0, 0.6);
z-index: 3;
}
.tui-upload-loading {
width: 28rpx;
height: 28rpx;
border-radius: 50%;
border: 2px solid;
border-color: #B2B2B2 #B2B2B2 #B2B2B2 #fff;
animation: tui-rotate 0.7s linear infinite;
}
@keyframes tui-rotate {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
.tui-tips {
font-size: 26rpx;
color: #fff;
}
.tui-mask-btn {
padding: 4rpx 16rpx;
border-radius: 40rpx;
text-align: center;
font-size: 24rpx;
color: #fff;
border: 1px solid #fff;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
margin-top: 26rpx;
}
.tui-btn-hover {
opacity: 0.8;
}
</style>

View File

@ -1,6 +1,5 @@
{
"pages": [
//pageshttps://uniapp.dcloud.io/collocation/pages
{
"path": "pages/login/launch",
"style": {
@ -91,8 +90,6 @@
"path": "pages/order/order",
"style": {
"navigationStyle": "custom"
// "onReachBottomDistance": 105,
// "enablePullDownRefresh": true
}
},
{
@ -197,6 +194,42 @@
"navigationBarTitleText": "网址"
}
},
{
"path": "pages/warehouse/warehouse",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/warehouse/manage/productList",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/warehouse/manage/brandList",
"style": {
"navigationBarTitleText": "品牌管理"
}
},
{
"path": "pages/warehouse/manage/photoGallery",
"style": {
"navigationBarTitleText": "商品图库"
}
},
{
"path": "pages/warehouse/manage/classifyList",
"style": {
"navigationBarTitleText": "分类管理"
}
},
{
"path": "pages/warehouse/manage/batch",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/my/versions",
"style": {
@ -232,6 +265,17 @@
},
"text": "工作台"
},
{
"pagePath": "pages/warehouse/warehouse",
"iconfont": {
"text": "\ue606",
"selectedText": "\ue606",
"selectedColor": "#fe4119",
"color": "#000",
"fontSize": "20px"
},
"text": "经营"
},
{
"pagePath": "pages/IM/IM",
"iconfont": {

View File

@ -315,10 +315,9 @@
class="id-radio-group"
@change="handelRaddio"
>
<view v-for="(item, index) in radioItems">
<view v-for="(item, index) in radioItems" :key="index">
<tui-radio
class="id-radio"
:key="index"
:checked="item.checked"
:value="item.value"
color="#07c160"
@ -368,12 +367,12 @@
placeholder="搜索开户银行关键词"
@change="onBranchBankChange"
/>
<div class="branch_list">
<view class="branch_list">
<template v-if="bankList.length">
<view
class="branch_list_item"
v-for="(item, index) in bankList"
:key="item.id"
:key="item.id + index"
@click="onBankSelect(item, $event)"
>
{{ item.branch_bank_name }}
@ -387,7 +386,7 @@
<view class="tit">数据加载中...</view>
</template>
</view>
</div>
</view>
</u-popup>
<u-datetime-picker
:show="showStartTime"
@ -580,17 +579,11 @@ export default {
async getAuditInfo() {
if (this.isContractSigningaPageTo) return;
var params = {};
let isContain = this.userInfo.user_mobile.indexOf("86");
if (isContain != -1 && this.userInfo.user_mobile.length > 11) {
params.mobile = this.userInfo.user_mobile.slice(2);
} else {
params.mobile = this.userInfo.user_mobile;
}
params.mobile = this.userInfo.user_mobile.startsWith("+86")
? this.userInfo.user_mobile.replace("+86", "")
: this.userInfo.user_mobile;
let res = await GetAuditInfo(params);
if (res && res.status == 200) {
@ -602,11 +595,11 @@ export default {
approval_invalid_col: [],
};
if(this.isPassAudit){
uni.switchTab({
url: "/pages/order/order",
});
return
if (this.isPassAudit) {
uni.switchTab({
url: "/pages/order/order",
});
return;
}
if (!res.data || res.data.approval_status == 4) {
@ -818,7 +811,7 @@ export default {
var ocr = await this.getOcrText(
imgUrl,
fileImg,
orcImgTypeConf.ID_CARD_FRONT
orcImgTypeConf.FR_ID_CARD_FRONT
);
this.auditInfo.approval_invalid_col.forEach((item) => {
if (
@ -1058,23 +1051,24 @@ export default {
const batchNoRes = await batchNoApi(filePath, file, type);
const batchNo = batchNoRes.batchNo;
//
let formDataStr;
//#ifdef H5
const formData = new FormData();
let formDataStr = "";
formData.append("batchNo", batchNo);
formData.append("imgType", type);
formDataStr = new URLSearchParams(formData).toString();
//#endif
//#ifdef APP-PLUS
formDataStr = `batchNo=${encodeURIComponent(
batchNo
)}&imgType=${encodeURIComponent(type)}`;
//#endif
clearTimeout(this.orcTimeout);
this.orcTimeout = setTimeout(async () => {
formData.forEach((value, key) => {
if (formDataStr !== "") {
formDataStr += "&";
}
formDataStr +=
encodeURIComponent(key) + "=" + encodeURIComponent(value);
});
const imgOcrRes = await imgOcrResultApi(formDataStr);
clearTimeout(this.orcTimeout);
resolve(imgOcrRes?.data);

View File

@ -166,7 +166,6 @@ export default {
this.searchAddressList.forEach((item) => {
if (item.name.indexOf(value) >= 0) {
console.log("aa");
item.searchName = item.name.replace(
new RegExp(value, "g"),
"<font style='color:#ee852f;padding:0 4px'>" + value + "</font>"

View File

@ -326,15 +326,9 @@ export default {
let userInfo = uni.getStorageSync("userInfo");
let locationItem = uni.getStorageSync("locationItem");
// userInfo.user_mobile = userInfo.user_mobile.slice(2);
let isContain = userInfo.user_mobile.indexOf("86");
if (isContain != -1 && userInfo.user_mobile.length > 11) {
params.mobile = userInfo.user_mobile.slice(2);
} else {
params.mobile = userInfo.user_mobile;
}
params.mobile = userInfo.user_mobile.startsWith("+86")
? userInfo.user_mobile.replace("+86", "")
: userInfo.user_mobile;
const storeArea =
locationItem.administrativeRegion.label[0] +

View File

@ -483,7 +483,7 @@ const orcImgTypeConf = {
ID_CARD_FRONT: "ID_CARD_FRONT", //
ID_CARD_BEHIND: "ID_CARD_BEHIND", //
BUSINESS_LICENCE: "BUSINESS_LICENCE", //
BANK_CARD: "BANK_CARD",
BANK_CARD: "BANK_CARD", //
};
export default {
@ -558,7 +558,7 @@ export default {
action: "",
limitType: ["png", "jpg", "jpeg"], //
fileMaxSize: 1 * 1024 * 1024, // 1M
maxSize: 20 * 1024 * 1024, //20M
maxSize: 10 * 1024 * 1024, //10M
fileMinSize: 5 * 1024, // 5KB
fileList: [],
fileList2: [],
@ -723,7 +723,7 @@ export default {
uni.navigateBack();
},
overSize(e) {
uni.$u.toast("上传图片大小不能超过20MB!");
uni.$u.toast("上传图片大小不能超过10MB!");
},
compressImage(url) {
return new Promise((reslove, reject) => {
@ -733,6 +733,7 @@ export default {
src: tempFilePath,
quality: 75, //
success: (res) => {
console.log("压缩成功", res);
reslove(res.tempFilePath); //
},
fail: (error) => {
@ -742,13 +743,13 @@ export default {
});
});
},
async getOcrText(filePath, file, type) {
return new Promise(async (resolve, reject) => {
this.loading = true;
//#ifdef APP-PLUS
try {
filePath = await this.compressImage(filePath);
console.log("路径", filePath);
} catch (error) {
console.log(error);
}
@ -764,87 +765,94 @@ export default {
console.log("OCR上图图片压缩后为", size);
//#endif
const batchNoRes = await batchNoApi(filePath, file, type);
if (!batchNoRes) {
this.loading = false;
reject(batchNoRes);
}
const batchNo = batchNoRes.batchNo;
const formData = new FormData();
let formDataStr = "";
formData.append("batchNo", batchNo);
formData.append("imgType", type);
clearTimeout(this.orcTimeout);
this.orcTimeout = setTimeout(async () => {
formData.forEach((value, key) => {
if (formDataStr !== "") {
formDataStr += "&";
}
formDataStr +=
encodeURIComponent(key) + "=" + encodeURIComponent(value);
});
const imgOcrRes = await imgOcrResultApi(formDataStr);
if (imgOcrRes.status == 250) {
switch (type) {
case "FR_ID_CARD_FRONT":
uni.showToast({
title: "上传身份证正面图片错误,请重新上传",
icon: "error",
duration: 2000,
});
this.form.legal_person_id_images == "";
this.fileList3 = [];
break;
case "FR_ID_CARD_BEHIND":
uni.showToast({
title: "上传身份证反面图片错误,请重新上传",
icon: "error",
duration: 2000,
});
this.form.legal_person_id_images2 == "";
this.fileList4 = [];
break;
case "ID_CARD_FRONT":
uni.showToast({
title: "上传身份证正面图片错误,请重新上传",
icon: "error",
duration: 2000,
});
this.form2.individual_id_images == "";
this.fileList5 = [];
break;
case "ID_CARD_BEHIND":
uni.showToast({
title: "上传身份证反面图片错误,请重新上传",
icon: "error",
duration: 2000,
});
this.form2.individual_id_images2 == "";
this.fileList6 = [];
break;
case "BUSINESS_LICENCE":
uni.showToast({
title: "营业图片上传有误,请重新上传",
icon: "error",
duration: 2000,
});
this.form.biz_license_image == "";
this.fileList = [];
break;
}
try {
const batchNoRes = await batchNoApi(filePath, file, type);
console.log("batchNoRes", batchNoRes);
if (!batchNoRes) {
this.loading = false;
reject(batchNoRes);
}
const batchNo = batchNoRes.batchNo;
//
let formDataStr;
//#ifdef H5
const formData = new FormData();
formData.append("batchNo", batchNo);
formData.append("imgType", type);
formDataStr = new URLSearchParams(formData).toString();
//#endif
//#ifdef APP-PLUS
formDataStr = `batchNo=${encodeURIComponent(
batchNo
)}&imgType=${encodeURIComponent(type)}`;
//#endif
clearTimeout(this.orcTimeout);
this.loading = false;
resolve(imgOcrRes?.data);
}, 1000);
this.orcTimeout = setTimeout(async () => {
const imgOcrRes = await imgOcrResultApi(formDataStr);
console.log("imgOcrRes", imgOcrRes);
if (imgOcrRes.status == 250) {
switch (type) {
case "FR_ID_CARD_FRONT":
uni.showToast({
title: "上传身份证正面图片错误,请重新上传",
icon: "none",
duration: 2000,
});
this.form.legal_person_id_images = "";
this.fileList3.splice(0, 1);
console.log(this.fileList3);
break;
case "FR_ID_CARD_BEHIND":
uni.showToast({
title: "上传身份证反面图片错误,请重新上传",
icon: "none",
duration: 2000,
});
this.form.legal_person_id_images2 = "";
this.fileList4.splice(0, 1);
break;
case "ID_CARD_FRONT":
uni.showToast({
title: "上传身份证正面图片错误,请重新上传",
icon: "none",
duration: 2000,
});
this.form2.individual_id_images = "";
this.fileList5.splice(0, 1);
break;
case "ID_CARD_BEHIND":
uni.showToast({
title: "上传身份证反面图片错误,请重新上传",
icon: "none",
duration: 2000,
});
this.form2.individual_id_images2 = "";
this.fileList6.splice(0, 1);
break;
case "BUSINESS_LICENCE":
uni.showToast({
title: "营业图片上传有误,请重新上传",
icon: "none",
duration: 2000,
});
this.form.biz_license_image = "";
this.fileList.splice(0, 1);
break;
}
}
clearTimeout(this.orcTimeout);
this.loading = false;
resolve(imgOcrRes?.data);
}, 1000);
} catch (error) {
console.log(error);
}
});
},
/**判断文件类型是否正确 */
@ -942,8 +950,9 @@ export default {
var ocr = await this.getOcrText(
imgUrl,
item,
orcImgTypeConf.ID_CARD_FRONT
orcImgTypeConf.FR_ID_CARD_FRONT
);
this.form.legal_person_name = ocr.name;
this.form.legal_person_id_number = ocr.idNumber;
this.form.legal_person_id_addr = ocr.address;
@ -1367,5 +1376,15 @@ page {
margin-right: 20rpx;
width: 240rpx;
}
::v-deep.u-upload__deletable {
width: 40rpx;
height: 40rpx;
.uicon-close {
font-size: 28rpx !important;
top: 8rpx !important;
}
}
}
</style>

View File

@ -120,12 +120,12 @@
placeholder="搜索开户银行关键词"
@change="onBranchBankChange"
/>
<div class="branch_list">
<view class="branch_list">
<template v-if="bankList.length">
<view
class="branch_list_item"
v-for="(item, index) in bankList"
:key="item.id"
:key="item.id + index"
@click="onBankSelect(item, $event)"
>
{{ item.branch_bank_name }}
@ -139,7 +139,7 @@
<view class="tit">数据加载中...</view>
</template>
</view>
</div>
</view>
</u-popup>
<view class="btn-content">
@ -261,7 +261,7 @@ export default {
},
limitType: ["png", "jpg", "jpeg"], //
fileMaxSize: 1 * 1024 * 1024, // 1M
maxSize: 5 * 1024 * 1024, //20M
maxSize: 10 * 1024 * 1024, //20M
fileMinSize: 5 * 1024, // 5KB
showTips: false,
};
@ -288,7 +288,7 @@ export default {
uni.navigateBack();
},
overSize(e) {
uni.$u.toast("上传图片大小不能超过20MB!");
uni.$u.toast("上传图片大小不能超过10MB!");
},
compressImage(url) {
return new Promise((reslove, reject) => {
@ -331,24 +331,24 @@ export default {
this.bankCardOcrLoaded = true;
reject(batchNoRes);
}
//
let formDataStr;
//#ifdef H5
const formData = new FormData();
let formDataStr = "";
formData.append("batchNo", batchNo);
formData.append("imgType", type);
formDataStr = new URLSearchParams(formData).toString();
//#endif
//#ifdef APP-PLUS
formDataStr = `batchNo=${encodeURIComponent(
batchNo
)}&imgType=${encodeURIComponent(type)}`;
//#endif
clearTimeout(this.orcTimeout);
this.orcTimeout = setTimeout(async () => {
formData.forEach((value, key) => {
if (formDataStr !== "") {
formDataStr += "&";
}
formDataStr +=
encodeURIComponent(key) + "=" + encodeURIComponent(value);
});
const imgOcrRes = await imgOcrResultApi(formDataStr);
if (imgOcrRes?.status == 200) {

View File

@ -32,13 +32,10 @@ export default {
onShow() {
if (this.userInfo && Object.keys(this.userInfo).length > 0) {
var _userinfo = JSON.parse(JSON.stringify(this.userInfo));
var mobile = "";
let isContain = _userinfo.user_mobile.indexOf("86");
if (isContain != -1 && _userinfo.user_mobile.length > 11) {
mobile = _userinfo.user_mobile.slice(2);
} else {
mobile = _userinfo.user_mobile;
}
let mobile = "";
mobile = _userinfo.user_mobile.startsWith("+86")
? _userinfo.user_mobile.replace("+86", "")
: _userinfo.user_mobile;
this.checkAccountIsPass({ userInfo: _userinfo, mobile: mobile });
}
},
@ -131,7 +128,7 @@ export default {
border: none;
}
}
.btn-register {
&::after {
border: none;

View File

@ -110,10 +110,7 @@
:maxlength="4"
>
<template slot="prefix">
<u-icon
class="input_icon"
name="file-text"
></u-icon>
<u-icon class="input_icon" name="file-text"></u-icon>
</template>
<template slot="suffix">
<u--image
@ -134,12 +131,13 @@
<view class="btn-content">
<view class="tool">
<view v-if="loginType == 0" class="left" @click="skipuForgetPwd"
>忘记密码</view
>
<view class="right" @click="skipuRegister"
>没有店铺? <text>立即开店</text></view
>
<view v-if="loginType == 0" class="left" @click="skipuForgetPwd">
忘记密码
</view>
<view class="right" @click="skipuRegister">
没有店铺?
<text>立即开店</text>
</view>
</view>
<u-button
class="btn-login"
@ -203,15 +201,10 @@ export default {
if (this.userInfo && Object.keys(this.userInfo).length > 0) {
console.log(this.userInfo);
var _userinfo = JSON.parse(JSON.stringify(this.userInfo));
var mobile = "";
let isContain = _userinfo.user_mobile.indexOf("86");
if (isContain != -1 && _userinfo.user_mobile.length > 11) {
mobile = _userinfo.user_mobile.slice(2);
} else {
mobile = _userinfo.user_mobile;
}
let mobile = "";
mobile = _userinfo.user_mobile.startsWith("+86")
? _userinfo.user_mobile.replace("+86", "")
: _userinfo.user_mobile;
this.checkAccountIsPass({ userInfo: _userinfo, mobile: mobile });

View File

@ -4,7 +4,7 @@
<u--image
class="qr-code-img"
:showLoading="true"
:src="accountInfo.store_info.wx_qrcode"
:src="dashboardInfo.store_info.wx_qrcode"
width="250px"
height="250px"
></u--image>
@ -22,7 +22,7 @@ export default {
},
onShow() {},
computed: {
...mapState("account", ["accountInfo"]),
...mapState("user", ["dashboardInfo"]),
},
methods: {
save() {
@ -31,7 +31,7 @@ export default {
});
//
uni.downloadFile({
url: this.accountInfo.store_info.wx_qrcode,
url: this.dashboardInfo.store_info.wx_qrcode,
success: (res) => {
if (res.statusCode === 200) {
//

View File

@ -3,7 +3,7 @@
<uni-popup ref="popup" type="bottom" :safe-area="false">
<view class="custom-picker">
<view class="custom-picker__header">
<view class="cancel" :style="{ color: canceColor }" >
<view class="cancel" :style="{ color: canceColor }">
<!-- {{ cancelText }} -->
</view>
<view class="title">{{ title }}</view>
@ -48,7 +48,7 @@
<picker-view-column>
<view
class="picker-view__item"
v-for="(item, index) in rangeList[2]"
v-for="(item, index) in rangeList[3]"
:key="index"
>
{{ item }}
@ -57,7 +57,7 @@
<picker-view-column>
<view
class="picker-view__item"
v-for="(item, index) in rangeList[3]"
v-for="(item, index) in rangeList[4]"
:key="index"
>
{{ item }}
@ -69,7 +69,7 @@
<view class="bottom-time">
<view class="">
<text>{{ startTime }}</text>
<text style="padding: 0 6rpx;"></text>
<text style="padding: 0 6rpx"></text>
<text>{{ endTime }}</text>
</view>
<view class="">{{ totalTime }}</view>
@ -85,7 +85,6 @@
确认
</u-button>
</view>
</view>
</uni-popup>
</template>
@ -169,88 +168,99 @@ export default {
},
data() {
return {
rangeList: [],
pickerValue: [0, 0, 0, 0],
rangeList: [[], [], [], [], []], // 5
pickerValue: [0, 0, 0, 0, 0], // 5
isScoll: false, //
startTime:"",
endTime:"",
totalTime:""
startTime: "00:00",
endTime: "00:00",
totalTime: "共0小时0分",
isValidTime: false,
};
},
created() {
this.generateRangeLists();
},
watch: {
//
maxStartHour() {
this.generateRangeLists();
},
maxStartMinute() {
this.generateRangeLists();
},
maxEndHour() {
this.generateRangeLists();
},
maxEndMinute() {
this.generateRangeLists();
},
this.initTimeRanges();
this.setInitialValue();
},
methods: {
generateRangeLists() {
const ranges = [[], [], [], []];
initTimeRanges() {
// (0-23)
this.rangeList[0] = Array.from({ length: 24 }, (_, i) =>
i.toString().padStart(2, "0")
);
// (0 - maxStartHour)
for (let i = 0; i <= this.maxStartHour; i++) {
ranges[0].push(i >= 10 ? String(i) : `0${i}`);
// (0-59)
this.rangeList[1] = Array.from({ length: 60 }, (_, i) =>
i.toString().padStart(2, "0")
);
//
this.rangeList[2] = [this.segmentation];
// (0-24)
this.rangeList[3] = Array.from({ length: 25 }, (_, i) =>
i.toString().padStart(2, "0")
);
// (00-59)
this.rangeList[4] = Array.from({ length: 60 }, (_, i) =>
i.toString().padStart(2, "0")
);
},
setInitialValue() {
// value5使
if (!Array.isArray(this.value) || this.value.length !== 5) {
this.pickerValue = [0, 0, 0, 0, 0];
return;
}
// (0 - maxStartMinute)
for (let i = 0; i <= this.maxStartMinute; i++) {
ranges[1].push(i >= 10 ? String(i) : `0${i}`);
// valuepickerValue
this.pickerValue = [
Math.max(this.rangeList[0].indexOf(this.value[0]), 0), //
Math.max(this.rangeList[1].indexOf(this.value[1]), 0), //
0, // 0
Math.max(this.rangeList[3].indexOf(this.value[3]), 0), //
Math.max(this.rangeList[4].indexOf(this.value[4]), 0), //
];
// 24:00
if (this.value[3] === "24") {
this.pickerValue[4] = 0;
this.rangeList[4] = ["00"];
}
// (0 - maxEndHour)
for (let i = 0; i <= this.maxEndHour; i++) {
ranges[2].push(i >= 10 ? String(i) : `0${i}`);
}
//
this.$nextTick(() => {
this.calculateTimeDifference();
});
},
handle24HourSelection() {
this.pickerValue[4] = 0; // 00
this.rangeList[4] = ["00"]; // 00
},
// (0 - maxEndMinute)
// 2400
if (
this.pickerValue &&
this.pickerValue[2] === this.rangeList[2]?.length - 1
) {
ranges[3] = ["00"];
} else {
for (let i = 0; i <= this.maxEndMinute; i++) {
ranges[3].push(i >= 10 ? String(i) : `0${i}`);
}
restoreMinuteOptions() {
this.rangeList[4] = Array.from({ length: 60 }, (_, i) =>
i.toString().padStart(2, "0")
);
},
generateMinutesRange() {
const minutes = [];
for (let i = 0; i <= 59; i++) {
minutes.push(i.toString().padStart(2, "0"));
}
this.rangeList = ranges;
return minutes;
},
/**
* 开启弹窗
*/
open() {
this.generateRangeLists();
if (Array.isArray(this.value) && this.value.length) {
this.pickerValue = this.value.map((item, index) => {
const i = this.rangeList[index].findIndex(
(child) => Number(child) == Number(this.value[index])
);
return i > -1 ? i : 0;
});
// If initial end hour is 24, ensure minute is 00
if (this.pickerValue[2] === this.rangeList[2]?.length - 1) {
this.pickerValue[3] = 0;
this.generateRangeLists();
}
} else {
this.pickerValue = [0, 0, 0, 0];
}
this.setInitialValue();
this.$refs.popup.open();
// picker-view
setTimeout(() => {
this.calculateTimeDifference();
}, 100);
},
/**
* 关闭弹窗
@ -264,16 +274,23 @@ export default {
* 点击确定
*/
onConfirm() {
if (!this.isScoll) {
let data = this.value || ["00", "00", "00", "00"];
if (this.pickerValue && this.pickerValue.length) {
data = this.pickerValue.map((item, index) =>
String(this.rangeList[index][item])
);
}
this.$emit("confirm", data);
this.close();
if (!this.isValidTime) {
uni.showToast({
title: "开始时间和结束时间至少相差半小时",
icon: "none",
});
return;
}
const result = [
this.rangeList[0][this.pickerValue[0]],
this.rangeList[1][this.pickerValue[1]],
this.rangeList[3][this.pickerValue[3]],
this.rangeList[4][this.pickerValue[4]],
];
this.$emit("confirm", result);
this.close();
},
/**
* 点击取消
@ -298,48 +315,84 @@ export default {
* @param {Object} e
*/
bindChange(e) {
const newValue = [...e.detail.value];
// pickerValue
// 24
if (newValue[3] === this.rangeList[3].length - 1) {
// 24
newValue[4] = 0; // 00
this.rangeList[4] = ["00"];
} else if (this.pickerValue[3] === this.rangeList[3].length - 1) {
// 24
this.rangeList[4] = Array.from({ length: 60 }, (_, i) =>
i.toString().padStart(2, "0")
);
}
this.pickerValue = newValue;
this.calculateTimeDifference();
},
calculateTimeDifference() {
//
const getValidNumber = (val) => (isNaN(val) ? 0 : val);
// startTime (: )
const startHour = this.rangeList[0][newValue[0]];
const startMinute = this.rangeList[1][newValue[1]];
const startTime = `${startHour}:${startMinute}`;
const startHour = getValidNumber(
parseInt(this.rangeList[0][this.pickerValue[0]])
);
const startMinute = getValidNumber(
parseInt(this.rangeList[1][this.pickerValue[1]])
);
const endHour = getValidNumber(
parseInt(this.rangeList[3][this.pickerValue[3]])
);
let endMinute = getValidNumber(
parseInt(this.rangeList[4][this.pickerValue[4]])
);
// endTime (: )
const endHour = this.rangeList[3][newValue[3]];
const endMinute = this.rangeList[4][newValue[4]];
const endTime = `${endHour}:${endMinute}`;
// totalTime
const startDate = new Date(2000, 0, 1, parseInt(startHour), parseInt(startMinute));
const endDate = new Date(2000, 0, 1, parseInt(endHour), parseInt(endMinute));
// 23:0001:00
if (endDate < startDate) {
endDate.setDate(endDate.getDate() + 1);
// 24:00
if (endHour === 24) {
endMinute = 0;
this.endTime = "24:00";
} else {
this.endTime = `${endHour.toString().padStart(2, "0")}:${endMinute
.toString()
.padStart(2, "0")}`;
}
const diffMs = endDate - startDate;
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
const diffMinutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));
const totalTime = `${diffHours}小时${diffMinutes}`;
// data便
this.startTime = startTime;
this.endTime = endTime;
this.totalTime = totalTime;
this.startTime = `${startHour.toString().padStart(2, "0")}:${startMinute
.toString()
.padStart(2, "0")}`;
// 24:0000
if (newValue[3] === this.rangeList[3]?.length - 1) { // 24
newValue[4] = 0; // 00
this.pickerValue = newValue;
this.generateRangeLists();
//
const startTotal = startHour * 60 + startMinute;
const endTotal = endHour * 60 + endMinute;
let diffMinutes = endTotal - startTotal;
//
if (diffMinutes < 0) {
diffMinutes += 1440; // 24*60
}
//
if (diffMinutes === 0) {
this.totalTime = "开始时间需早于结束时间";
this.isValidTime = false;
} else if (diffMinutes < 30) {
this.totalTime = "时间差需至少30分钟";
this.isValidTime = false;
} else {
const hours = Math.floor(diffMinutes / 60);
const minutes = diffMinutes % 60;
this.totalTime = `${hours}小时${minutes}`;
this.isValidTime = true;
}
},
pickstart() {
this.isScoll = true;
},
pickend() {
this.isScoll = false;
},
},
};
@ -433,15 +486,15 @@ export default {
line-height: 80rpx;
}
::v-deep .picker-view{
::v-deep .picker-view {
height: 60%;
}
.bottom-content{
.bottom-content {
background: #fff;
box-shadow: 0 0 4rpx 4rpx rgba(0, 0, 0, 0.1);
box-shadow: 0 0 28rpx 4rpx rgba(0, 0, 0, 0.1);
.bottom-time{
.bottom-time {
display: flex;
justify-content: space-between;
padding: 20rpx 28rpx;
@ -449,10 +502,10 @@ export default {
font-weight: bold;
}
.bottom-btn{
.bottom-btn {
padding: 28rpx 40rpx 80rpx;
.btn-time{
.btn-time {
background: $base-color;
color: #fff;
@ -461,8 +514,5 @@ export default {
}
}
}
}
</style>

View File

@ -11,16 +11,28 @@
</view>
<view class="business-time-content" @click="showTimePopup">
<view class="time-box">
<view calss="time">23:30</view>
<view calss="time">{{ storeBaseInfo.info.store_opening_hours }}</view>
<view></view>
<view calss="time">23:30</view>
<view calss="time">{{ storeBaseInfo.info.store_close_hours }}</view>
</view>
</view>
<view class="business-time-bottm">
<u-button
class="btn-time"
:hairline="true"
:plain="true"
shape="circle"
@click="updateStoreBizState"
>
确认修改
</u-button>
</view>
<ozTimePicker
ref="timePickerPopupRef"
title="设置营业时间段"
segmentation="至"
:value="['00', '00', '00', '00']"
:value="timeValue"
@confirm="handerConfirmTiem"
indicator-class="picker-view__indicator acitve"
></ozTimePicker>
</view>
@ -31,6 +43,7 @@ import { GetAccountDashboard } from "../../../api/user";
import { UpdateStoreBizState } from "../../../api/store";
import tuiDatetime from "./tui-datetime/tui-datetime.vue";
import ozTimePicker from "./oz-timePicker/oz-timePicker.vue";
import { GetShopBaseInfo, UpdataShopInfo } from "@/api/shop";
export default {
components: {
tuiDatetime,
@ -71,6 +84,13 @@ export default {
},
showPopup: false,
dateTime: "",
storeBaseInfo: {
info: {
store_opening_hours: "",
store_close_hours: "",
},
},
timeValue: ["00", "00", "至", "00", "00"],
};
},
computed: {
@ -79,9 +99,20 @@ export default {
},
},
onShow() {
this.getShopBaseInfo();
this.getAccountDashboard();
},
methods: {
async getShopBaseInfo() {
let res = await GetShopBaseInfo();
if (res && res.status == 200) {
this.storeBaseInfo = res.data;
const startTime =
this.storeBaseInfo.info.store_opening_hours.split(":");
const endTime = this.storeBaseInfo.info.store_close_hours.split(":");
this.timeValue = [...startTime, "至", ...endTime];
}
},
async getAccountDashboard() {
let res = await GetAccountDashboard();
if (res && res.status == 200) {
@ -95,6 +126,26 @@ export default {
closeTimePopup() {
this.showPopup = false;
},
handerConfirmTiem(e) {
this.storeBaseInfo.info.store_opening_hours = e[0] + ":" + e[1];
this.storeBaseInfo.info.store_close_hours = e[2] + ":" + e[3];
},
async updateStoreBizState() {
var params = {
store_id: this.storeBaseInfo.store_id,
store_opening_hours: this.storeBaseInfo.info.store_opening_hours,
store_close_hours: this.storeBaseInfo.info.store_close_hours,
store_biz_state: this.storeBaseInfo.store_biz_state,
};
let res = await UpdateStoreBizState(params);
if (res && res.status == 200) {
uni.showToast({
title: "修改成功",
icon: "success",
});
}
},
},
};
</script>
@ -150,6 +201,7 @@ export default {
padding: 36rpx 40rpx;
border-radius: 24rpx;
background: #f5f6fa;
font-weight: 500;
}
}
@ -166,5 +218,25 @@ export default {
}
}
}
.business-time-bottm {
position: fixed;
left: 0;
bottom: 0;
width: 90%;
background: #fff;
box-shadow: 0 0 28rpx 4rpx rgba(0, 0, 0, 0.1);
padding: 28rpx 40rpx 80rpx;
.btn-time {
background: $base-color;
color: #fff;
border: none;
&::after {
border: none;
}
}
}
}
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,810 @@
<template>
<view class="batch-search-container">
<navBar
class="nav-bar"
:statusBar="true"
:border="false"
:fixed="true"
:height="'44px'"
rightWidth="0"
:leftWidth="30"
backgroundColor="#fff"
>
<block slot="left">
<u-icon
name="arrow-left"
color="#000"
size="20"
@click="pageBack()"
></u-icon>
</block>
<block slot="default">
<u-search
v-model="inputSearch"
class="search"
placeholder="请输入商品名称查找"
:showAction="false"
@change="handerSearch"
bgColor="#eeeeee"
></u-search>
</block>
</navBar>
<view class="commodity-status" v-if="searchCommodityList.length > 0">
<u-tabs
class="u-tabs"
ref="tabsRef"
:list="searchCommodityStatusList"
@click="handerCommodityStatus"
itemStyle="padding-left: 15px; padding-right: 15px; height: 57px;"
activeStyle="font-weight: bold;color: #000;"
inactiveStyle="color:#999999;"
lineColor="#e41f19"
></u-tabs>
</view>
<view
class="no-data"
v-if="searchCommodityList.length <= 0 && isNoCommodityData"
>
<view class="no-data-bg"></view>
<view class="no-data-tips">暂无商品</view>
</view>
<favorite-loading
class="commodity-loading"
v-show="loadingCommodityData"
:color="'#fe4119'"
text=""
animation="spinner15"
></favorite-loading>
<scroll-view
v-if="searchCommodityList.length > 0 && !loadingCommodityData"
scroll-y
class="batch-search-scroll"
:show-scrollbar="false"
@scrolltolower="handerScrolltolower"
refresher-enabled
:refresher-triggered="isRefreshing"
@refresherrefresh="handleRefresh"
>
<u-checkbox-group
class="commodity-list"
v-model="checkboxList"
placement="column"
@change="handleSingleCheckboxChange($event, true)"
>
<view
class="commodity-item"
v-for="(item, index) of searchCommodityList"
:key="index"
>
<u-checkbox
class="commodity-checkbox"
:key="index"
:name="item.product_id"
></u-checkbox>
<view
class="commodity-info"
@click="handleSingleCheckboxChange([item.product_id])"
>
<view
:class="[
'commodity-img',
{ 'commodity-img-sold-out': item.product_state_id == 1002 },
]"
>
<u--image
:src="item.product_image"
radius="8"
width="60px"
height="60px"
@click="handlerShowImg(item.product_image)"
></u--image>
</view>
<view class="commodity-info-box">
<view class="commodity-name" v-html="item.searchName"></view>
<view class="commodity-inventory">
库存{{ item.itemQuantity }}
</view>
<view class="commodity-price">
<block class="currency">¥</block>
{{ item.product_unit_price }}
</view>
</view>
</view>
</view>
</u-checkbox-group>
<view
class="m-loading-box"
v-if="searchCommodityList.length > 0 && !isNoCommodityData"
>
<block v-if="loadingDownCommodityData">
<view class="u-loadmore">
<view class="u-loading"></view>
<text class="u-loadmore-tips">正在加载...</text>
</view>
</block>
<block v-else>
<view class="u-loadmore u-loadmore-line">
<text class="u-loadmore-tips">没有更多商品了 ~</text>
</view>
</block>
</view>
</scroll-view>
<view class="bottom" v-if="searchCommodityList.length > 0">
<u-checkbox-group
v-model="checkboxAllList"
placement="column"
@change="handleSelectAll($event, true)"
>
<u-checkbox
class="commodity-checkbox"
:name="'select-all'"
label="全选"
></u-checkbox>
</u-checkbox-group>
<u-button
class="commodity-btn-item"
:hairline="true"
:plain="true"
shape="circle"
@click="affirmSelect"
>
确定选择
</u-button>
</view>
<u-popup
class="affirm-popup"
zIndex="10077"
:show="showBackPopup"
mode="center"
>
<view class="affirm-popup-content">
<view class="affirm-popup-title">确认退出</view>
<view class="affirm-popup-tips">
您搜索后选择或取消选择商品的操作暂未保存现在退出将全部失效确认退出么
</view>
<view class="popup-btn-list">
<u-button
class="btn-item"
:hairline="true"
:plain="true"
shape="circle"
@click="showBackPopup = false"
>
取消
</u-button>
<u-button
class="btn-item btn-item-2"
:hairline="true"
:plain="true"
shape="circle"
@click="handerPageBack"
>
确认
</u-button>
</view>
</view>
</u-popup>
<tui-gallery
:urls="showImgList"
:show="showImg"
@hide="hideImg"
></tui-gallery>
<u-toast ref="uToast"></u-toast>
</view>
</template>
<script>
import { GetProductList } from "@/api/warehouse/productList";
import navBar from "@/components/uni-nav-bar/uni-nav-bar";
import tuiCollapse from "../manage/components/tui-collapse/tui-collapse.vue";
import favoriteLoading from "@/components/favorite-loading/favorite-loading.vue";
import tuiGallery from "@/components/tui-gallery/tui-gallery.vue";
export default {
name: "batchSearch",
props: {
selectCommodityList: {
type: Array,
default: [],
},
},
components: {
navBar,
tuiCollapse,
favoriteLoading,
tuiGallery,
},
data() {
return {
height: 0, //scroll-view
top: 0,
searchCommodityStatusList: [
{
value: null,
name: "全部",
badge: {
value: 0,
},
},
{
// 1001-;1002-;1000-
value: 1001,
name: "销售中",
badge: {
value: 0,
},
},
{
value: 1002,
name: "仓库中",
badge: {
value: 0,
},
},
{
value: 1000,
name: "违规禁售",
badge: {
value: 0,
},
},
{
value: 1003,
name: "待审核",
badge: {
value: 0,
},
},
],
searchCommodityList: [],
pageNum: 1,
pageSize: 20,
loadingCommodityData: false,
loadingDownCommodityData: false,
isNoCommodityData: false,
isNoDownCommodityData: false,
isRefreshing: false,
time: null,
searchTime: null,
showImgList: [],
showImg: false,
inputSearch: "",
checkboxList: [],
checkboxAllList: [],
showBackPopup: false,
};
},
computed: {
allSelectedExistInCurrentPage() {
if (this.selectCommodityList.length === 0) return false;
// ID
const currentPageIds = this.searchCommodityList.map(
(item) => item.product_id
);
// selectCommodityList
return this.selectCommodityList.every((selectedItem) =>
currentPageIds.includes(selectedItem.product_id)
);
},
},
onLoad: function (options) {
setTimeout(() => {
uni.getSystemInfo({
success: (res) => {
let header = 60;
let top = 0;
//#ifdef H5
top = 44;
//#endif
this.height = res.windowHeight - uni.upx2px(header);
this.top = top + uni.upx2px(header);
},
});
}, 50);
},
onReady() {},
onShow() {
this.getProductCategoryTree();
},
mounted() {},
methods: {
pageBack() {
if (this.checkboxList.length > 0) {
this.showBackPopup = true;
} else {
this.$emit("pageBack");
}
},
handerPageBack() {
this.$emit("pageBack");
},
//
swichNav: function (e) {
let cur = e.currentTarget.dataset.current;
if (this.currentTab == cur) {
return false;
} else {
this.currentTab = cur;
this.checkCor();
}
},
//tab
checkCor: function () {
if (this.currentTab > 6) {
this.scrollViewId = `id_${this.currentTab - 2}`;
} else {
this.scrollViewId = `id_0`;
}
},
handerSearch() {
clearTimeout(this.searchTime);
this.searchTime = setTimeout(() => {
if (this.inputSearch.length == 0) {
this.pageNum = 1;
this.searchCommodityList = [];
this.checkboxList = [];
this.checkboxAllList = [];
return;
}
this.getProductList();
}, 500);
},
async getProductList() {
this.isNoCommodityData = false;
if (this.loadingDownCommodityData) {
this.loadingCommodityData = false;
} else {
this.loadingCommodityData = true;
}
if (this.isRefreshing) {
this.pageNum = 1;
this.isNoCommodityData = false;
this.isNoDownCommodityData = false;
}
let params = {
kind_id: "1201,1202,1203",
pageNum: this.pageNum,
pageSize: this.pageSize,
product_state_id: this.currProductStateId,
product_name: this.inputSearch,
openCount: true,
};
let res = await GetProductList(params);
if (res && res.status == 200) {
if (this.loadingDownCommodityData) {
if (res.data.items.length <= 0) {
this.loadingDownCommodityData = false;
this.isNoDownCommodityData = true;
return;
} else {
this.searchCommodityList = [
...this.searchCommodityList,
...res.data.items,
];
}
} else {
this.searchCommodityList = res.data.items;
}
if (this.searchCommodityList.length <= 0) {
this.isNoCommodityData = true;
}
// selectCommodityList
this.checkboxList = [
...this.checkboxList,
...this.searchCommodityList
.filter((item) =>
this.selectCommodityList.some(
(selected) => selected.product_id === item.product_id
)
)
.map((item) => item.product_id),
];
if (this.allSelectedExistInCurrentPage) {
this.checkboxAllList = ["select-all"];
} else {
this.checkboxAllList = [];
}
this.searchCommodityList.forEach((item) => {
if (item.product_name.indexOf(this.inputSearch) >= 0) {
item.searchName = item.product_name.replace(
new RegExp(this.inputSearch, "g"),
"<font style='color:#fe4119;padding:0 4px'>" +
this.inputSearch +
"</font>"
);
} else {
item.searchName = item.name;
}
});
var {
allRecords,
normalRecords,
offRecords,
illegalRecords,
unCheckedRecords,
} = res.data;
this.searchCommodityStatusList[0].badge.value = allRecords;
this.searchCommodityStatusList[1].badge.value = normalRecords;
this.searchCommodityStatusList[2].badge.value = offRecords;
this.searchCommodityStatusList[3].badge.value = illegalRecords;
this.searchCommodityStatusList[4].badge.value = unCheckedRecords;
this.$nextTick(() => {
this.$refs.tabsRef.init();
});
}
this.loadingDownCommodityData = false;
this.loadingCommodityData = false;
this.isRefreshing = false;
},
handleRefresh() {
this.isRefreshing = true;
this.getProductList();
},
handerScrolltolower() {
clearTimeout(this.time);
this.checkboxAllList = [];
if (this.isNoDownCommodityData) return;
this.loadingDownCommodityData = true;
this.time = setTimeout(() => {
this.pageNum = this.pageNum + 1;
this.getProductList();
}, 500);
},
handerCommodityStatus(e) {
this.pageNum = 1;
this.pageSize = 20;
this.isNoDownCommodityData = false;
this.isNoCommodityData = false;
this.currProductStateId = e.value;
this.searchCommodityList = [];
this.getProductList();
},
handerSearchCommodityStatus() {},
emptySelectAll() {
this.showAffirmEmptyPopup = true;
},
affirmSelect() {
//
const totalSelected = [
...new Set([
...this.selectCommodityList.map((item) => item.product_id),
...this.checkboxList,
]),
].length;
if (totalSelected > 100) {
uni.showToast({
title: `总数不能超过100个当前${totalSelected}`,
icon: "none",
});
return;
}
// searchCommodityList
const selectedCommodities = this.searchCommodityList.filter((item) =>
this.checkboxList.includes(item.product_id)
);
// selectCommodityList
const newSelectedCommodities = selectedCommodities.filter(
(item) =>
!this.selectCommodityList.some(
(selected) => selected.product_id === item.product_id
)
);
//
this.$emit("searchCommodity", newSelectedCommodities);
this.$emit("pageBack");
},
hideImg() {
this.showImg = false;
},
handlerShowImg(url) {
if (!url) return;
this.showImg = true;
this.showImgList = [
{
src: url,
desc: "", // You can add description if needed
},
];
},
handleSelectAll(list) {
// ID
const currentPageIds = this.searchCommodityList.map(
(item) => item.product_id
);
if (list.length > 0) {
//
if (currentPageIds.length + this.checkboxList.length > 100) {
//
const remaining = 100 - this.checkboxList.length;
const toSelect = currentPageIds.slice(
0,
remaining > 0 ? remaining : 0
);
this.checkboxList = [...this.checkboxList, ...toSelect];
if (remaining <= 0) {
this.$refs.uToast.show({
message: "已达到100个商品上限",
type: "error",
duration: 1000,
});
}
//
setTimeout(() => {
this.checkboxAllList = [];
}, 0);
} else {
//
this.checkboxList = [
...new Set([...this.checkboxList, ...currentPageIds]),
];
}
} else {
//
this.checkboxList = this.checkboxList.filter(
(id) => !currentPageIds.includes(id)
);
}
},
handleSingleCheckboxChange(list, isFromCheckbox = false) {
const remaining = 100 - this.selectCommodityList.length;
const currentSelected = this.checkboxList.length;
//
if (!isFromCheckbox) {
const productId = list[0];
const isAlreadySelected = this.checkboxList.includes(productId);
//
if (isAlreadySelected) {
this.checkboxList = this.checkboxList.filter(
(id) => id !== productId
);
return;
}
//
if (currentSelected >= remaining) {
this.$refs.uToast.show({
message: "最多可选100个商品超出的商品无法选中",
type: "error",
duration: 1000,
});
return;
}
this.checkboxList = [...this.checkboxList, productId];
return;
}
//
if (list.length - currentSelected > remaining) {
return;
}
this.checkboxList = list;
},
},
};
</script>
<style lang="scss" scoped>
@import "@/styles/variables.scss";
.batch-search-container {
width: 100vw;
height: 100vh;
background: #fff;
.nav-bar {
padding-top: 10px;
}
.batch-search-scroll {
height: calc(100vh - 230px);
}
.commodity-list {
padding: 48rpx 52rpx 0;
.commodity-item {
display: flex;
align-items: center;
margin-bottom: 40rpx;
.commodity-checkbox {
margin-bottom: 20px;
margin-right: 20rpx;
}
.commodity-info {
display: flex;
.commodity-img {
position: relative;
margin-right: 20rpx;
width: 60px;
height: 60px;
border: 1px solid #ebebeb;
border-radius: 16rpx;
}
.commodity-img-sold-out {
&::before {
position: absolute;
bottom: 0;
width: 100%;
height: 20px;
line-height: 20px;
content: "已下架";
text-align: center;
background: rgba(0, 0, 0, 0.6);
color: #fff;
z-index: 99;
font-size: 14px;
border-bottom-left-radius: 16rpx;
border-bottom-right-radius: 16rpx;
}
}
.commodity-info-box {
display: flex;
flex-flow: column;
justify-content: space-between;
.commodity-name {
font-weight: bold;
font-size: 18px;
word-break: break-all; /* 允许在任意字符间断行 */
overflow-wrap: break-word; /* 优先在单词间断行 */
display: -webkit-box;
-webkit-line-clamp: 2; /* 限制最多2行 */
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis; /* 超出部分显示省略号 */
}
.commodity-inventory {
font-size: 28rpx;
color: #626262;
margin: 6rpx 0;
}
.commodity-price {
font-size: 32rpx;
font-weight: bold;
color: #ea3938;
.currency {
margin-right: 4px;
font-size: 24rpx;
}
}
}
}
}
}
.commodity-loading {
margin: 70% auto;
display: flex;
}
.m-loading-box {
text-align: center;
padding: 40rpx;
color: #aaaa;
font-size: 28rpx;
}
.bottom {
position: fixed;
width: 92%;
bottom: 0;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20px;
margin: 40px 0;
.commodity-btn-item {
margin: 0;
margin-right: 20rpx;
width: 360rpx;
height: 38px;
font-size: 28rpx;
border: none;
color: #fff;
background: $base-color;
&::after {
border: none;
}
}
}
.affirm-popup {
::v-deep.u-popup__content {
border-radius: 16rpx;
}
::v-deep.u-fade-enter-to {
z-index: 10076 !important;
}
.affirm-popup-content {
width: 600rpx;
.affirm-popup-title {
padding: 40rpx;
text-align: center;
font-weight: 500;
}
.affirm-popup-tips {
padding: 0 60rpx;
font-size: 28rpx;
text-align: center;
}
.popup-btn-list {
display: flex;
margin: 50rpx;
.btn-item {
width: 46%;
height: 80rpx;
border-color: #909193;
&::after {
border: none;
}
}
.btn-item-2 {
background: $base-color;
color: #fff;
border: none;
}
}
}
}
.no-data {
.no-data-bg {
margin: 60% auto;
margin-bottom: 0;
width: 300rpx;
height: 200rpx;
background-image: url("../../../static/no-commodity.png");
background-size: 100%;
}
.no-data-tips {
margin: 80rpx auto;
color: #aaaaaa;
text-align: center;
}
}
}
</style>

View File

@ -0,0 +1,187 @@
<template>
<view class="tui-collapse" :style="{ backgroundColor: bgColor }">
<view
class="tui-collapse-head"
:style="{ backgroundColor: hdBgColor }"
@tap.stop="handleClick"
>
<view class="tui-header" :class="{ 'tui-opacity': disabled }">
<view
class="tui-collapse-icon tui-icon-arrow"
:class="{ 'tui-icon-active': isOpen }"
:style="{ color: arrowColor }"
v-if="arrow"
></view>
<slot name="title"></slot>
</view>
</view>
<view
class="tui-collapse-body_box"
:style="{ backgroundColor: bdBgColor, height: isOpen ? height : '0rpx' }"
>
<view
class="tui-collapse-body"
:class="{
'tui-collapse-transform': height == 'auto',
'tui-collapse-body_show': isOpen && height == 'auto',
}"
>
<slot name="content"></slot>
</view>
</view>
</view>
</template>
<script>
export default {
name: "tuiCollapse",
emits: ["click"],
props: {
//collapse
bgColor: {
type: String,
default: "transparent",
},
//collapse-head
hdBgColor: {
type: String,
default: "#fff",
},
//collapse-body
bdBgColor: {
type: String,
default: "transparent",
},
//collapse-body open使
height: {
type: String,
default: "auto",
},
//
index: {
type: Number,
default: 0,
},
//index==current
current: {
type: Number,
default: -1,
},
//
disabled: {
type: [Boolean, String],
default: false,
},
//
arrow: {
type: [Boolean, String],
default: true,
},
//
arrowColor: {
type: String,
default: "#333",
},
},
watch: {
current() {
this.updateCurrentChange();
},
},
created() {
this.updateCurrentChange();
},
data() {
return {
isOpen: false,
};
},
methods: {
updateCurrentChange() {
this.isOpen = this.index == this.current;
},
handleClick() {
if (this.disabled) return;
this.$emit("click", {
index: Number(this.index),
});
},
},
};
</script>
<style scoped>
@font-face {
font-family: "tuiCollapse";
src: url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAAQ4AA0AAAAABlgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAAEHAAAABoAAAAciRx3B0dERUYAAAP8AAAAHgAAAB4AKQAKT1MvMgAAAaAAAABCAAAAVjxuR/JjbWFwAAAB9AAAAD4AAAFCAA/pq2dhc3AAAAP0AAAACAAAAAj//wADZ2x5ZgAAAkAAAABEAAAARCs1U/toZWFkAAABMAAAADAAAAA2FpaT+mhoZWEAAAFgAAAAHQAAACQHngOFaG10eAAAAeQAAAAPAAAAEAwAAEBsb2NhAAACNAAAAAoAAAAKACIAAG1heHAAAAGAAAAAHwAAACABDwAdbmFtZQAAAoQAAAFJAAACiCnmEVVwb3N0AAAD0AAAACMAAAA1DunpUnjaY2BkYGAAYja/oO54fpuvDNwsDCBwc4/6fzjtwNDNfICpBMjlYGACiQIAGVAKZnjaY2BkYGBu+N/AEMPCAALMBxgYGVABCwBVNgMsAAAAeNpjYGRgYGBhEGQA0QwMTEDMBYQMDP/BfAYACnYBLQB42mNgZGFgnMDAysDA1Ml0hoGBoR9CM75mMGLkAIoysDIzYAUBaa4pDA7PGJ4xMDf8b2CIYW5gaAAKM4LkANq9C9sAAHjaY2GAABYIdgAAAMAATQB42mNgYGBmgGAZBkYGELAB8hjBfBYGBSDNAoRA/jOG//8hpBQzVCUDIxsDjMnAyAQkmBhQASPDsAcAMCAGoQAAAAAAAAAAAAAAIgAAAAEAQACLA8ACdAAQAAAlASYiBhQXARYyNwE2NCYiBwIA/oYNIBkMAZcNIA0BlwwZIA3uAXoMGSAN/mkMDAGXDSAZDAB42n2QPU4DMRCFn/MHJBJCIKhdUQDa/JQpEyn0CKWjSDbekGjXXnmdSDkBLRUHoOUYHIAbINFyCl6WSZMia+3o85uZ57EBnOMbCv/fJe6EFY7xKFzBETLhKvUX4Rr5XbiOFj6FG9R/hJu4VQPhFi7UGx1U7YS7m9JtywpnGAhXcIon4Sr1lXCN/CpcxxU+hBvUv4SbGONXuIVrZakM4WEwQWCcQWOKDeMCMRwskjIG1qE59GYSzExPN3oRO5s4GyjvV2KXAx5oOeeAKe09t2a+Sif+YMuB1JhuHgVLtimNLiJ0KBtfLJzV3ahzsP2e7ba02L9rgTXH7FENbNT8Pdsz0khsDK+QkjXyMrekElOPaGus8btnKdbzXgiJTrzL9IjHmjR1OvduaeLA4ufyjBx9tLmSPfeoHD5jWQh5v91OxCCKXYY/k9hxGQAAAHjaY2BigAAuMMnIgA5YwKJMjExciUVF+eW6KfnleQAZ0wQyAAAAAAH//wACAAEAAAAMAAAAFgAAAAIAAQADAAMAAQAEAAAAAgAAAAB42mNgYGBkAIKrS9Q5QPTNPer/YTQAQ+0HIAAA)
format("woff");
font-weight: normal;
font-style: normal;
}
.tui-collapse-icon {
font-family: "tuiCollapse" !important;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.tui-icon-arrow:before {
content: "\e600";
}
.tui-icon-arrow {
font-size: 20rpx;
transform: rotate(0);
transform-origin: center center;
transition: all 0.3s;
position: absolute;
top: 50%;
margin-top: -10rpx;
left: 20rpx;
z-index: 9;
}
.tui-arrow-padding {
padding-right: 62rpx;
box-sizing: border-box;
}
.tui-icon-active {
transform: rotate(180deg);
transform-origin: center center;
}
.tui-header {
position: relative;
z-index: 2;
}
.tui-collapse-body_box {
transition: all 0.25s;
overflow: hidden;
}
.tui-collapse-body {
transition: all 0.25s;
overflow: hidden;
position: relative;
z-index: 1;
}
.tui-collapse-transform {
opacity: 0;
visibility: hidden;
-webkit-transform: translateY(-40%);
transform: translateY(-40%);
}
.tui-collapse-body_show {
opacity: 1;
visibility: visible;
-webkit-transform: translateY(0);
transform: translateY(0);
}
.tui-opacity {
opacity: 0.6;
}
</style>

View File

@ -0,0 +1,974 @@
<template>
<view class="productList-container">
<navBar
class="nav-bar"
:statusBar="true"
:border="false"
:fixed="true"
:height="'44px'"
rightWidth="0"
:leftWidth="30"
backgroundColor="#f5f6fa"
>
<block slot="left">
<u-icon
name="arrow-left"
color="#000"
size="20"
@click="pageBack()"
></u-icon>
</block>
<block slot="default">
<u-search
class="search"
placeholder="请输入商品名称查找"
:showAction="false"
bgColor="#fff"
></u-search>
</block>
</navBar>
<view class="productList-content">
<scroll-view
scroll-y
scroll-with-animation
class="tab-view"
:scroll-into-view="scrollViewId"
:style="{ height: height - 130 + 'px', top: top + 'px' }"
>
<block v-for="(item, index) of tabbar" :key="index">
<tui-collapse
:index="index"
:current="current"
hdBgColor="f5f6fa"
:arrow="item.children.length > 0 ? true : false"
@click="handerCollApse"
>
<template v-slot:title>
<view
class="tab-bar-item"
:class="[
{ active: currentTab === index },
{ active2: current === index },
]"
>
{{ item.label }}
</view>
</template>
<template v-slot:content v-if="item.children.length > 0">
<view
class="tab-bar-item tab-bar-item-2"
:class="[currentTab == group.id ? 'active' : '']"
v-for="(group, index2) of item.children"
@click="handerCollApseChildren(index, index2)"
>
{{ group.label }}
</view>
</template>
</tui-collapse>
</block>
</scroll-view>
<view
class="right-box"
:style="{ height: height + 'px', top: top + 'px' }"
>
<view class="commodity-status">
<u-tabs
class="u-tabs"
ref="tabsRef"
:list="commodityStatusList"
@click="handerCommodityStatus"
itemStyle="padding-left: 15px; padding-right: 15px; height: 57px;"
activeStyle="font-weight: bold;color: #000;"
inactiveStyle="color:#999999;"
lineColor="#e41f19"
></u-tabs>
</view>
<favorite-loading
class="commodity-loading"
v-show="loadingCommodityData"
:color="'#fe4119'"
text=""
animation="spinner15"
></favorite-loading>
<view
class="no-data"
v-if="commodityList.length <= 0 && isNoCommodityData"
>
<view class="no-data-bg"></view>
<view class="no-data-tips">暂无商品</view>
</view>
<scroll-view
v-if="commodityList.length > 0 && !loadingCommodityData"
scroll-y
:style="{ height: height - 200 + 'px', top: top + 'px' }"
:show-scrollbar="false"
@scrolltolower="handerScrolltolower"
refresher-enabled
:refresher-triggered="isRefreshing"
@refresherrefresh="handleRefresh"
>
<view class="commodity-list">
<view
class="commodity-item"
v-for="(item, index) of commodityList"
:key="index"
>
<view class="commodity-info">
<view
:class="[
'commodity-img',
{ 'commodity-img-sold-out': item.product_state_id == 1002 },
]"
>
<u--image
:src="item.product_image"
radius="8"
width="68px"
height="68px"
></u--image>
</view>
<view class="commodity-info-box">
<view class="commodity-name">
{{ item.product_name }}
</view>
<view class="commodity-inventory">
库存{{ item.itemQuantity }}
</view>
<view class="commodity-price">
<text class="currency">¥</text>
{{ item.product_unit_price }}
</view>
</view>
</view>
<view class="commodity-btn-content">
<u-button
class="commodity-btn-item"
:hairline="true"
:plain="true"
shape="circle"
>
价格/库存
</u-button>
<u-button
v-if="item.product_state_id == 1002"
class="commodity-btn-item commodity-btn-item-2"
:hairline="true"
:plain="true"
shape="circle"
@click="updateProductPutaway(item, index, 1001)"
>
上架
</u-button>
<u-button
v-if="item.product_state_id == 1001"
class="commodity-btn-item commodity-btn-item-2"
:hairline="true"
:plain="true"
shape="circle"
@click="updateProductPutaway(item, index, 1002)"
>
下架
</u-button>
<u-button
class="commodity-btn-item commodity-btn-item-2"
:hairline="true"
:plain="true"
shape="circle"
>
编辑
</u-button>
</view>
</view>
</view>
<view
class="m-loading-box"
v-if="commodityList.length > 0 && !isNoCommodityData"
>
<block v-if="loadingDownCommodityData">
<view class="u-loadmore">
<view class="u-loading"></view>
<text class="u-loadmore-tips">正在加载...</text>
</view>
</block>
<block v-else>
<view class="u-loadmore u-loadmore-line">
<text class="u-loadmore-tips">没有更多商品了 ~</text>
</view>
</block>
</view>
</scroll-view>
</view>
</view>
<view class="productList-bottom">
<view class="bottom-item">分类管理</view>
<view class="bottom-item">
<u-icon
class="u-icon"
custom-prefix="custom-icon-piliangcaozuo custom-icon"
size="14"
color="#000"
></u-icon>
<view class="bottom-item-name" @click="skipuBatch">批量操作</view>
</view>
<view class="bottom-item">
<u-icon
class="u-icon"
custom-prefix="custom-icon-xinjiantuopu custom-icon"
size="16"
color="#000"
></u-icon>
<view class="bottom-item-name">商品新建</view>
</view>
</view>
</view>
</template>
<script>
import {
GetProductCategoryTree,
GetProductList,
UpdateProductPutaway,
} from "@/api/warehouse/productList";
import navBar from "@/components/uni-nav-bar/uni-nav-bar";
import tuiCollapse from "../manage/components/tui-collapse/tui-collapse.vue";
import favoriteLoading from "@/components/favorite-loading/favorite-loading.vue";
export default {
name: "productList",
components: {
navBar,
tuiCollapse,
favoriteLoading,
},
data() {
return {
tabbar: [
{
id: null,
label: "全部",
children: [],
},
],
height: 0, //scroll-view
top: 0,
currentTab: 0, //
current: -1,
scrollViewId: "id_0",
commodityStatusList: [
{
value: null,
name: "全部",
badge: {
value: 0,
},
},
{
// 1001-;1002-;1000-
value: 1001,
name: "销售中",
badge: {
value: 0,
},
},
{
value: 1002,
name: "仓库中",
badge: {
value: 0,
},
},
{
value: 1000,
name: "违规禁售",
badge: {
value: 0,
},
},
{
value: 1003,
name: "待审核",
badge: {
value: 0,
},
},
],
commodityList: [],
pageNum: 1,
pageSize: 20,
currCategoryId: null,
collApseIndex: 0,
currTabChildrenIndex: 0,
currProductStateId: null,
loadingCommodityData: false,
loadingDownCommodityData: false,
isNoCommodityData: false,
isNoDownCommodityData: false,
isRefreshing: false,
time: null,
time2: null,
};
},
computed: {},
onLoad: function (options) {
setTimeout(() => {
uni.getSystemInfo({
success: (res) => {
let header = 60;
let top = 0;
//#ifdef H5
top = 44;
//#endif
this.height = res.windowHeight - uni.upx2px(header);
this.top = top + uni.upx2px(header);
},
});
}, 50);
},
onReady() {},
onShow() {
this.getProductCategoryTree();
this.getProductList();
},
mounted() {},
methods: {
pageBack() {
uni.navigateBack();
},
//
swichNav: function (e) {
let cur = e.currentTarget.dataset.current;
if (this.currentTab == cur) {
return false;
} else {
this.currentTab = cur;
this.checkCor();
}
},
//tab
checkCor: function () {
if (this.currentTab > 6) {
this.scrollViewId = `id_${this.currentTab - 2}`;
} else {
this.scrollViewId = `id_0`;
}
},
async getProductCategoryTree() {
let res = await GetProductCategoryTree();
if (res && res.status == 200) {
// var list = res.data.map((item) => ({
// ...item,
// current: -1,
// }));
this.tabbar = [...this.tabbar, ...res.data];
}
},
async getProductList() {
if (this.loadingDownCommodityData) {
this.loadingCommodityData = false;
} else {
this.loadingCommodityData = true;
}
if (this.isRefreshing) {
this.pageNum = 1;
this.isNoCommodityData = false;
this.isNoDownCommodityData = false;
}
let params = {
kind_id: "1201,1202,1203",
pageNum: this.pageNum,
pageSize: this.pageSize,
product_state_id: this.currProductStateId,
category_id: this.currCategoryId,
openCount: true,
};
let res = await GetProductList(params);
if (res && res.status == 200) {
if (this.loadingDownCommodityData) {
if (res.data.items.length <= 0) {
this.loadingDownCommodityData = false;
this.isNoDownCommodityData = true;
return;
} else {
this.commodityList = [...this.commodityList, ...res.data.items];
}
} else {
this.commodityList = res.data.items;
}
if (this.commodityList.length <= 0) {
this.isNoCommodityData = true;
}
var {
allRecords,
normalRecords,
offRecords,
illegalRecords,
unCheckedRecords,
} = res.data;
this.commodityStatusList[0].badge.value = allRecords;
this.commodityStatusList[1].badge.value = normalRecords;
this.commodityStatusList[2].badge.value = offRecords;
this.commodityStatusList[3].badge.value = illegalRecords;
this.commodityStatusList[4].badge.value = unCheckedRecords;
this.$nextTick(() => {
this.$refs.tabsRef.init();
});
}
this.loadingDownCommodityData = false;
this.loadingCommodityData = false;
this.isRefreshing = false;
},
handleRefresh() {
this.isRefreshing = true;
this.getProductList();
},
updateProductPutaway(item, index, type) {
clearTimeout(this.time2);
let params = {
product_id: item.product_id,
product_state_id: type,
};
this.time2 = setTimeout(async () => {
let res = await UpdateProductPutaway(params);
if (res && res.status) {
uni.$u.toast("操作成功");
this.commodityList[index].product_state_id = type;
let params = {
kind_id: "1201,1202,1203",
pageNum: this.pageNum,
pageSize: this.pageSize,
product_state_id: this.currProductStateId,
category_id: this.currCategoryId,
openCount: true,
};
let result = await GetProductList(params);
if (result && result.status == 200) {
var {
allRecords,
normalRecords,
offRecords,
illegalRecords,
unCheckedRecords,
} = result.data;
this.commodityStatusList[0].badge.value = allRecords;
this.commodityStatusList[1].badge.value = normalRecords;
this.commodityStatusList[2].badge.value = offRecords;
this.commodityStatusList[3].badge.value = illegalRecords;
this.commodityStatusList[4].badge.value = unCheckedRecords;
}
}
}, 500);
},
handerScrolltolower() {
clearTimeout(this.time);
if (this.isNoDownCommodityData) return;
this.loadingDownCommodityData = true;
this.time = setTimeout(() => {
this.pageNum = this.pageNum + 1;
this.getProductList();
}, 500);
},
handerCommodityStatus(e) {
this.pageNum = 1;
this.pageSize = 10;
this.isNoDownCommodityData = false;
this.isNoCommodityData = false;
this.currProductStateId = e.value;
this.commodityList = [];
this.getProductList();
},
handerCollApse(e) {
let index = e.index;
// -1 ==
const oldCategoryId = this.currCategoryId;
this.current = this.current == index ? -1 : e.index;
// current
if (this.current != -1 && this.tabbar[index].children.length > 0) {
this.currentTab =
this.tabbar[index].children[this.currTabChildrenIndex].id;
this.currCategoryId =
this.tabbar[index].children[this.currTabChildrenIndex].id;
} else {
this.currentTab = index;
this.currCategoryId = this.tabbar[index].id;
if (this.current != -1) {
this.currTabChildrenIndex = 0;
}
}
this.pageNum = 1;
this.pageSize = 20;
if (this.collApseIndex == index) {
return;
}
if (this.currCategoryId != oldCategoryId && this.current != -1) {
this.getProductList();
this.collApseIndex = index;
}
},
//
handerCollApseChildren(index1, index2) {
const oldCategoryId = this.currCategoryId;
//
this.currTabChildrenIndex = index2;
//active
this.currentTab = this.tabbar[index1].children[index2].id;
//id
this.currCategoryId = this.tabbar[index1].children[index2].id;
if (this.currCategoryId != oldCategoryId) {
this.getProductList();
}
},
detail(e) {
uni.navigateTo({
url: "../productDetail/productDetail",
});
},
productList(e) {
let key = e.currentTarget.dataset.key;
uni.navigateTo({
url: "../productList/productList?searchKey=" + key,
});
},
search: function () {
uni.navigateTo({
url: "../../news/search/search",
});
},
skipuBatch() {
uni.navigateTo({
url: "/pages/warehouse/manage/batch",
});
},
},
};
</script>
<style lang="scss" scoped>
@import "@/styles/variables.scss";
.productList-container {
height: calc(100vh);
background: #f5f6fa;
.nav-bar {
padding-top: 20rpx;
}
::-webkit-scrollbar {
width: 0;
height: 0;
color: transparent;
}
.tui-searchbox {
width: 100%;
height: 92rpx;
padding: 0 30rpx;
box-sizing: border-box;
background: #fff;
display: flex;
align-items: center;
justify-content: center;
position: fixed;
left: 0;
top: 0;
/* #ifdef H5 */
top: 44px;
/* #endif */
z-index: 100;
}
.tui-searchbox::after {
content: "";
position: absolute;
border-bottom: 1rpx solid #d2d2d2;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
bottom: 0;
right: 0;
left: 0;
}
.tui-search-input {
width: 100%;
height: 60rpx;
background: #f1f1f1;
border-radius: 30rpx;
font-size: 26rpx;
color: #999;
display: flex;
align-items: center;
justify-content: center;
}
.tui-search-text {
padding-left: 16rpx;
}
.tab-view {
/* height: 100%; */
width: 200rpx;
position: fixed;
left: 0;
z-index: 10;
}
.tab-bar-item {
width: 200rpx;
min-height: 57px;
background: #f5f6fa;
box-sizing: border-box;
display: flex;
align-items: center;
flex-wrap: wrap;
font-size: 30rpx;
color: #666666;
font-weight: 400;
padding: 12rpx;
padding-left: 28px;
padding-right: 32rpx;
word-wrap: break-word;
word-break: break-all;
}
.active {
position: relative;
color: #000;
font-weight: 600;
background: #fff;
}
.tab-bar-item-2 {
font-size: 28rpx;
background: #fff !important;
}
.active2 {
background: #fff;
}
.active::before {
content: "";
position: absolute;
border-left: 8rpx solid #e41f19;
height: 30rpx;
left: 0;
}
/* 左侧导航布局 end*/
.right-box {
width: 100%;
position: fixed;
padding-left: 210rpx;
box-sizing: border-box;
left: 0;
background: #fff;
}
.page-view {
width: 100%;
overflow: hidden;
padding-top: 20rpx;
padding-right: 20rpx;
box-sizing: border-box;
padding-bottom: env(safe-area-inset-bottom);
}
.swiper {
width: 100%;
height: 220rpx;
border-radius: 12rpx;
overflow: hidden;
transform: translateZ(0);
}
/* #ifdef MP-WEIXIN */
.swiper .wx-swiper-dot {
width: 8rpx;
height: 8rpx;
display: inline-flex;
background: none;
justify-content: space-between;
}
.swiper .wx-swiper-dot::before {
content: "";
flex-grow: 1;
background: rgba(255, 255, 255, 0.8);
border-radius: 16rpx;
overflow: hidden;
}
.swiper .wx-swiper-dot-active::before {
background: #fff;
}
.swiper .wx-swiper-dot.wx-swiper-dot-active {
width: 16rpx;
}
/* #endif */
/* #ifndef MP-WEIXIN */
::v-deep .swiper .uni-swiper-dot {
width: 8rpx;
height: 8rpx;
display: inline-flex;
background: none;
justify-content: space-between;
}
::v-deep .swiper .uni-swiper-dot::before {
content: "";
flex-grow: 1;
background: rgba(255, 255, 255, 0.8);
border-radius: 16rpx;
overflow: hidden;
}
::v-deep .swiper .uni-swiper-dot-active::before {
background: #fff;
}
::v-deep .swiper .uni-swiper-dot.uni-swiper-dot-active {
width: 16rpx;
}
/* #endif */
.slide-image {
width: 100%;
height: 220rpx;
}
.class-box {
padding-top: 30rpx;
}
.class-item {
background: #fff;
width: 100%;
box-sizing: border-box;
padding: 20rpx;
margin-bottom: 20rpx;
border-radius: 12rpx;
}
.class-name {
font-size: 22rpx;
}
.g-container {
/* padding-top: 20rpx; */
display: flex;
display: -webkit-flex;
justify-content: flex-start;
flex-direction: row;
flex-wrap: wrap;
}
.g-box {
width: 33.3333%;
text-align: center;
padding-top: 40rpx;
}
.g-image {
width: 120rpx;
height: 120rpx;
}
.g-title {
font-size: 22rpx;
}
.tui-content {
padding: 20rpx 30rpx;
background-color: #fff;
color: #555;
font-size: 26rpx;
}
.u-tabs {
border-bottom: 1px solid #f3f3f3;
}
.commodity-status {
position: sticky;
top: 0;
left: 0;
width: 100%;
z-index: 99;
background: #fff;
}
.m-loading-box {
text-align: center;
margin: 40rpx;
color: #aaaa;
font-size: 28rpx;
}
.commodity-list {
padding: 20rpx;
.commodity-item {
margin-bottom: 60rpx;
.commodity-info {
display: flex;
margin-bottom: 40rpx;
.commodity-img {
position: relative;
margin-right: 20rpx;
width: 68px;
height: 68px;
border: 1px solid #ebebeb;
border-radius: 16rpx;
}
.commodity-img-sold-out {
&::before {
position: absolute;
bottom: 0;
width: 100%;
height: 20px;
line-height: 20px;
content: "已下架";
text-align: center;
background: rgba(0, 0, 0, 0.6);
color: #fff;
z-index: 99;
font-size: 14px;
border-bottom-left-radius: 16rpx;
border-bottom-right-radius: 16rpx;
}
}
.commodity-info-box {
display: flex;
flex-flow: column;
justify-content: space-between;
.commodity-name {
font-weight: bold;
font-size: 36rpx;
word-break: break-all; /* 允许在任意字符间断行 */
overflow-wrap: break-word; /* 优先在单词间断行 */
display: -webkit-box;
-webkit-line-clamp: 2; /* 限制最多2行 */
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis; /* 超出部分显示省略号 */
}
.commodity-inventory {
font-size: 28rpx;
color: #626262;
}
.commodity-price {
font-size: 32rpx;
font-weight: bold;
color: #ea3938;
.currency {
margin-right: 4px;
font-size: 24rpx;
}
}
}
}
.commodity-btn-content {
display: flex;
justify-content: flex-end;
.commodity-btn-item {
margin: 0;
margin-right: 20rpx;
width: 160rpx;
height: 60rpx;
font-size: 24rpx;
border-color: #d2d2d2;
color: #000;
&::after {
border: none;
}
}
.commodity-btn-item-2 {
width: 104rpx;
}
}
}
}
.no-data {
.no-data-bg {
margin: 60% auto;
margin-bottom: 0;
width: 300rpx;
height: 200rpx;
background-image: url("../../../static/no-commodity.png");
background-size: 100%;
}
.no-data-tips {
margin: 80rpx auto;
color: #aaaaaa;
text-align: center;
}
}
.productList-bottom {
position: fixed;
bottom: 0;
z-index: 99;
display: flex;
padding: 40rpx;
width: 100%;
background: #fff;
border-top: 2px solid #f3f3f3;
// box-shadow: 0 0px 6px 0 rgba(0, 0, 0, 0.1);
.bottom-item {
display: flex;
align-items: center;
margin-bottom: 40rpx;
margin-right: 80rpx;
.u-icon {
margin-right: 8rpx;
}
}
}
.commodity-loading {
margin: 70% auto;
display: flex;
}
}
</style>

View File

@ -0,0 +1,129 @@
<template>
<view class="warehouse-container">
<status-bar :backgroundColor="'#fff'" v-if="true"></status-bar>
<view class="shop-name">{{ dashboardInfo.store_info.store_name }}</view>
<view class="warehouse-list">
<view class="warehouse-item" @click="skipu('productList')">
<view class="warehouse-item-img">
<u--image
src="../../static/warehouse/brand-2.png"
:width="44"
:height="44"
></u--image>
</view>
<view class="warehouse-item-name">商品管理</view>
</view>
<view class="warehouse-item" @click="skipu('brandList')">
<view class="warehouse-item-img">
<u--image
src="../../static/warehouse/brand-3.png"
:width="44"
:height="44"
></u--image>
</view>
<view class="warehouse-item-name">品牌管理</view>
</view>
<view class="warehouse-item" @click="skipu('photoGallery')">
<view class="warehouse-item-img">
<u--image
src="../../static/warehouse/classify.png"
:width="44"
:height="44"
></u--image>
</view>
<view class="warehouse-item-name">分类管理</view>
</view>
<view class="warehouse-item" @click="skipu('classifyList')">
<view class="warehouse-item-img">
<u--image
src="../../static/warehouse/photo-gallery-1.png"
:width="44"
:height="44"
></u--image>
</view>
<view class="warehouse-item-name">商品图库</view>
</view>
</view>
<tabbar tabbarName="warehouse"></tabbar>
</view>
</template>
<script>
import tabbar from "@/components/tabbar/tabbar.vue";
import statusBar from "@/components/status-bar.vue";
import { GetAccountDashboard } from "../../api/user";
import { mapState } from "vuex";
export default {
name: "warehouse",
components: {
statusBar,
tabbar,
},
data() {
return {
dashboardInfo: {
store_info: {
store_name: "",
},
},
};
},
computed: {},
onReady() {},
onShow() {
this.getAccountDashboard();
},
mounted() {},
methods: {
async getAccountDashboard() {
let res = await GetAccountDashboard();
if (res && res.status == 200) {
this.dashboardInfo = res.data;
}
},
skipu(url) {
uni.navigateTo({
url: `/pages/warehouse/manage/${url}`,
});
},
},
};
</script>
<style lang="scss" scoped>
@import "@/styles/variables.scss";
.warehouse-container {
height: calc(100vh - 120rpx);
background: #f5f6fa;
.shop-name {
padding: 40rpx 24px;
font-size: 40rpx;
font-weight: bold;
background: #fff;
}
.warehouse-list {
display: flex;
align-items: center;
justify-content: space-between;
margin: 10px;
padding: 20px;
background: #fff;
box-shadow: 0 12rpx 16rpx 0 rgba(0, 0, 0, 0.1);
border-radius: 24rpx;
.warehouse-item {
display: flex;
flex-flow: column;
align-items: center;
.warehouse-item-img {
margin-bottom: 20rpx;
}
}
}
}
</style>

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "custom-icon"; /* Project id 4805967 */
src: url('@/static/font/iconfont.woff2?t=1736404172628') format('woff2'),
url('@/static/font/iconfont.woff?t=1736404172628') format('woff'),
url('@/static/font/iconfont.ttf?t=1736404172628') format('truetype');
src: url("@/static/font/iconfont.woff2?t=1736404172628") format("woff2"),
url("@/static/font/iconfont.woff?t=1736404172628") format("woff"),
url("@/static/font/iconfont.ttf?t=1736404172628") format("truetype");
}
.custom-icon {
@ -21,6 +21,50 @@
-moz-osx-font-smoothing: grayscale;
}
.custom-icon-jianhao:before {
content: "\e664";
}
.custom-icon-xinjiantuopu:before {
content: "\e83a";
}
.custom-icon-piliangcaozuo:before {
content: "\e66a";
}
.custom-icon-gongzuotai1:before {
content: "\e660";
}
.custom-icon-shangpinguanli:before {
content: "\e666";
}
.custom-icon-shangpinpinpai:before {
content: "\e6e6";
}
.custom-icon-xiangcetuku:before {
content: "\e63c";
}
.custom-icon-fenlei:before {
content: "\fc7d";
}
.custom-icon-mianxingtuku:before {
content: "\e60a";
}
.custom-icon-icon_shangpindangan_shangpinpinpai:before {
content: "\e60f";
}
.custom-icon-yingyezhuangtai:before {
content: "\e605";
}
.custom-icon-shipin:before {
content: "\e629";
}
@ -120,4 +164,3 @@
.custom-icon-password:before {
content: "\e61d";
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -1,7 +1,6 @@
import Vue from "vue";
import Vuex from "vuex";
import user from "./modules/user";
import account from "./modules/account";
import order from "./modules/order";
import audit from "./modules/audit";
@ -10,7 +9,6 @@ Vue.use(Vuex);
const store = new Vuex.Store({
modules: {
user,
account,
order,
audit,
},

View File

@ -1,44 +0,0 @@
const defaultState = () => {
return {
accountInfo: uni.getStorageSync('accountDashboard') || {
data: {},
notice: {},
order: {},
product: {
illegal_num: 0,
normal_num: 0,
off_num: 0,
total_num: 0,
verify_passed_off_num: 0,
verify_refused_num: 0,
verify_waiting_num: 0,
},
return: {
fin_num: 0,
review_num: 0,
total_num: 0,
un_fin_num: 0,
},
store_info: {
store_id: 1,
wx_qrcode: '',
},
},
};
};
const state = defaultState();
const getters = {};
const mutations = {};
const actions = {};
export default {
namespaced: true,
state,
getters,
mutations,
actions,
};

View File

@ -20,6 +20,30 @@ const defaultState = () => {
socket: {},
getMsg: {},
imWeidu: {},
dashboardInfo: uni.getStorageSync("accountDashboard") || {
data: {},
notice: {},
order: {},
product: {
illegal_num: 0,
normal_num: 0,
off_num: 0,
total_num: 0,
verify_passed_off_num: 0,
verify_refused_num: 0,
verify_waiting_num: 0,
},
return: {
fin_num: 0,
review_num: 0,
total_num: 0,
un_fin_num: 0,
},
store_info: {
store_id: "",
wx_qrcode: "",
},
},
};
};
@ -46,6 +70,7 @@ const mutations = {
state.socket = {};
state.getMsg = {};
state.imWeidu = {};
state.dashboardInfo = {};
},
CONNECT_SOCKET(state, { socket }) {
state.socket = socket;
@ -101,13 +126,9 @@ const actions = {
if (res && res.status == 200) {
let mobile = "";
let isContain = res.data.user_mobile.indexOf("86");
if (isContain != -1 && res.data.user_mobile.length > 11) {
mobile = res.data.user_mobile.slice(2);
} else {
mobile = res.data.user_mobile;
}
mobile = res.data.user_mobile.startsWith("+86")
? res.data.user_mobile.replace("+86", "")
: res.data.user_mobile;
const userInfo = res.data;
@ -148,13 +169,9 @@ const actions = {
if (res && res.status == 200) {
let mobile = "";
let isContain = res.data.user_mobile.indexOf("86");
if (isContain != -1 && res.data.user_mobile.length > 11) {
mobile = res.data.user_mobile.slice(2);
} else {
mobile = res.data.user_mobile;
}
mobile = res.data.user_mobile.startsWith("+86")
? res.data.user_mobile.replace("+86", "")
: res.data.user_mobile;
const userInfo = res.data;

View File

@ -167,7 +167,8 @@
.slice(0, this.innerCurrent)
.reduce((total, curr) => total + curr.rect.width, 0);
// 线px
const lineWidth = uni.$u.getPx(this.lineWidth);
const lineWidth = uni.$u.getPx(uni.$u.addUnit(this.lineWidth));
this.lineOffsetLeft = lineOffsetLeft + (tabItem.rect.width - lineWidth) / 2
// #ifdef APP-NVUE
//

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,262 @@
/**
* imageUtil.js
*解决图片旋转的问题
* **/
import EXIF from "./exif.js";
async function compressImage(path) {
let imageInfo = await getImageInfo(path);
let systemInfo = await getSystemInfo();
return new Promise(function (resolve, reject) {
// #ifdef APP-PLUS || APP-NVUE
appCompressImage(path, imageInfo)
.then((res) => {
resolve(res);
})
.catch((e) => {
reject(e);
});
// #endif
// #ifdef H5
let orientation = 1;
let img = document.createElement("img");
img.src = path;
img.onload = function () {
EXIF.getData(img, function () {
orientation = EXIF.getTag(this, "Orientation");
canvasImg(path, orientation, imageInfo, systemInfo)
.then((res) => {
debugger;
resolve(res);
})
.catch((e) => {
reject(e);
});
});
};
img.onerror = function () {
reject(path);
};
// #endif
});
}
// app处理旋转图片
function appCompressImage(src, imageInfo) {
return new Promise(function (resolve, reject) {
let orientation = imageInfo.orientation;
let rotate = 0;
let quality = 80;
if (plus.os.name == "iOS") {
rotate = 0;
quality = 25;
} else {
switch (orientation) {
case "up": //exif:1 不旋转
rotate = 0;
break;
case "down": //exif:3 旋转180度
rotate = 180;
break;
case "right": //exif:6 旋转90度
rotate = 90;
break;
case "left": //exif:8 旋转270度
rotate = 270;
break;
default:
rotate = 0;
break;
}
}
plus.zip.compressImage(
{
src: src,
dst:
"_doc/uniapp_temp" + "/compressed/" + Math.round(new Date()) + ".png",
format: "png",
quality: quality,
width: "auto",
height: "auto",
rotate: rotate,
},
function (event) {
resolve(event.target);
},
function (error) {
reject(src);
}
);
});
}
// 画图片
function canvasImg(path, or, imageInfo, systemInfo) {
return new Promise(function (resolve, reject) {
let canvasId = "uploadCanvas";
const ctx = uni.createCanvasContext(canvasId);
let scale = imageInfo.width / imageInfo.height;
// 图片参数 start
let maxdestWidth = 1100; // 2000;
let destWidth = imageInfo.width;
let destHeight = imageInfo.height;
let destCompressWidth = imageInfo.width;
let destCompressHeight = imageInfo.height;
// 压缩图片 最大不超过5M 1200
// 当宽大于高的时候
if (imageInfo.width > imageInfo.height) {
if (imageInfo.width > maxdestWidth) {
destCompressWidth = maxdestWidth;
destCompressHeight = Math.floor(destCompressWidth / scale);
} else {
destCompressWidth = (imageInfo.width * 8) / 10;
destCompressHeight = Math.floor(destCompressWidth / scale);
}
}
// 当高大于宽
else {
if (imageInfo.height > maxdestWidth) {
destCompressHeight = maxdestWidth;
destCompressWidth = Math.floor(destCompressHeight * scale);
} else {
destCompressHeight = imageInfo.height * 0.8;
destCompressWidth = Math.floor(destCompressHeight * scale);
}
}
destWidth = destCompressHeight;
destHeight = destCompressWidth;
// 图片参数 end
// 画布参数 start
let maxWidth = 300;
let canvasW = imageInfo.width;
let canvasH = imageInfo.height;
let width = imageInfo.width;
let height = imageInfo.height;
// canvas画布不能超过最大宽
if (canvasW > maxWidth) {
canvasW = maxWidth;
canvasH = Math.floor(canvasW / scale);
}
width = canvasW;
height = canvasH;
// 画布参数 end
// console.log('--or---', or)
//单独处理苹果最新版本
if (
systemInfo.model == "iPhone" &&
systemInfo.system.indexOf("13.4.1") > -1
) {
ctx.drawImage(path, 0, 0, canvasW, canvasH);
destWidth = destCompressWidth;
destHeight = destCompressHeight;
} else {
if (or == 6) {
//逆时针旋转了90
ctx.translate(width, 0);
ctx.rotate(Math.PI / 2);
ctx.drawImage(path, 0, 0, canvasH, canvasW);
} else if (or == 3) {
//逆时针旋转了180
ctx.translate(width, height);
ctx.rotate(Math.PI);
ctx.drawImage(path, 0, 0, canvasH, canvasW);
} else if (or == 8) {
//顺时针旋转90
ctx.translate(0, height);
ctx.rotate(-Math.PI / 2);
ctx.drawImage(path, 0, 0, canvasH, canvasW);
} else {
ctx.drawImage(path, 0, 0, canvasW, canvasH);
// return resolve(path);
destWidth = destCompressWidth;
destHeight = destCompressHeight;
}
}
// console.log('图片原始长宽', imageInfo, maxWidth, canvasW, canvasH, width, height, destWidth, destHeight);
ctx.draw(
true,
setTimeout(() => {
uni.canvasToTempFilePath({
x: 0,
y: 0,
width: width, //画布宽度
height: height,
destWidth: destWidth,
destHeight: destHeight,
fileType: "png",
canvasId: canvasId,
success: (res) => {
resolve(res.tempFilePath);
},
fail: (err) => {
resolve(path);
},
});
}, 200)
);
});
}
// 获取图片信息
function getImageInfo(path) {
return new Promise(function (resolve, reject) {
// #ifdef APP-PLUS
plus.io.getImageInfo({
src: path,
success: function (image) {
// console.log('orientation=' + image.orientation);
resolve(image);
},
fail: function (err) {
console.log("getImageInfoErr: " + JSON.stringify(err));
reject(err);
},
});
// #endif
// #ifdef H5 || MP-WEIXIN
uni.getImageInfo({
src: path,
success: function (image) {
// console.log('orientation=' + image.orientation);
resolve(image);
},
fail: function (err) {
console.log("getImageInfoErr: " + JSON.stringify(err));
reject(err);
},
});
// #endif
});
}
// 获取系统信息
function getSystemInfo(path) {
return new Promise(function (resolve, reject) {
uni.getSystemInfo({
success(res) {
resolve(res);
},
fail(err) {
console.log("getSystemInfoErr: " + JSON.stringify(err));
reject(err);
},
});
});
}
export default compressImage;