update 经营
@ -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",
|
||||
|
||||
@ -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_address:2
|
||||
* 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,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单列表 模拟数据
|
||||
**/
|
||||
|
||||
72
java-mall-app-shop-admin/api/warehouse/productList.js
Normal 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,
|
||||
});
|
||||
}
|
||||
@ -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"
|
||||
); //使用
|
||||
|
||||
212
java-mall-app-shop-admin/components/tui-gallery/tui-gallery.vue
Normal 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>
|
||||
@ -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
|
||||
},
|
||||
//背景透明 【设置该属性,则背景透明,只出现内容,isOpacity和maxOpacity失效】
|
||||
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
|
||||
},
|
||||
//下拉隐藏NavigationBar,主要针对有回弹效果ios端
|
||||
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>
|
||||
613
java-mall-app-shop-admin/components/tui-upload/tui-upload.vue
Normal 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+
|
||||
//solid、dashed、dotted
|
||||
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>
|
||||
@ -1,6 +1,5 @@
|
||||
{
|
||||
"pages": [
|
||||
//pages数组中第一项表示应用启动页,参考:https://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": {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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>"
|
||||
|
||||
@ -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] +
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 });
|
||||
|
||||
|
||||
@ -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) {
|
||||
//鉴权
|
||||
|
||||
@ -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() {
|
||||
// 确保value是有效的5元素数组,否则使用默认值
|
||||
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}`);
|
||||
// 转换value为pickerValue索引
|
||||
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)
|
||||
// 如果结束小时是24,分钟只能是00
|
||||
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:00到01: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:00时分钟只能是00)
|
||||
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>
|
||||
|
||||
@ -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>
|
||||
|
||||
1988
java-mall-app-shop-admin/pages/warehouse/manage/batch.vue
Normal file
810
java-mall-app-shop-admin/pages/warehouse/manage/batchSearch.vue
Normal 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>
|
||||
@ -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>
|
||||
974
java-mall-app-shop-admin/pages/warehouse/manage/productList.vue
Normal 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>
|
||||
129
java-mall-app-shop-admin/pages/warehouse/warehouse.vue
Normal 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>
|
||||
@ -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";
|
||||
}
|
||||
|
||||
|
||||
BIN
java-mall-app-shop-admin/static/no-commodity.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
java-mall-app-shop-admin/static/warehouse/asdsad.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
java-mall-app-shop-admin/static/warehouse/brand-1.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
java-mall-app-shop-admin/static/warehouse/brand-2.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
java-mall-app-shop-admin/static/warehouse/brand-3.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
java-mall-app-shop-admin/static/warehouse/classify.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
java-mall-app-shop-admin/static/warehouse/photo-gallery-1.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
java-mall-app-shop-admin/static/warehouse/photo-gallery.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
@ -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,
|
||||
},
|
||||
|
||||
@ -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,
|
||||
};
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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
|
||||
// 第一次移动滑块,无需过渡时间
|
||||
|
||||
1144
java-mall-app-shop-admin/utils/exif.js
Normal file
262
java-mall-app-shop-admin/utils/tupian.js
Normal 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;
|
||||