Commit b5ca6d69 by liangjianmin

新增快递回单上传页面及相关API,优化首页导航逻辑

parent d093ade7
.page-box {
padding: 15rpx 22rpx;
height: 100vh;
display: flex;
flex-direction: column;
.search-all-box {
margin-top: 15rpx;
}
.tips {
margin-top: 15rpx;
.text {
font-size: 20rpx;
color: #919399;
}
.summary {
font-size: 20rpx;
color: #919399;
}
.blue {
color: #1969f9;
margin: 0 4rpx;
}
}
.list-scroll {
flex: 1;
margin-top: 15rpx;
height: 0;
}
.pick_img_list {
flex: 1;
flex-wrap: wrap;
.img_list {
position: relative;
width: 120rpx;
height: 120rpx;
margin-right: 16rpx;
margin-bottom: 12rpx;
image {
width: 100%;
height: 100%;
border-radius: 8rpx;
}
.delete-btn {
position: absolute;
top: -10rpx;
right: -10rpx;
width: 36rpx;
height: 36rpx;
background: #ff4757;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
.iconfont {
font-size: 20rpx;
color: #ffffff;
}
}
}
.default {
width: 120rpx;
height: 120rpx;
background: #f5f7fa;
border: 2rpx dashed #dcdfe6;
border-radius: 8rpx;
.iconfont {
font-size: 48rpx;
color: #c0c4cc;
}
}
}
}
<template>
<view class="time-interval-box row bothSide verCenter">
<view class="time-interval row verCenter bothSide">
<view class="row verCenter">
<text class="iconfont icon-juxing41"></text>
<picker mode="date" @change="handleDateChange(1, $event)">
<input type="text" class="uni-input" :placeholder="startPlaceholder" placeholder-style="color:#919399" :value="startTime" />
</picker>
</view>
<text class="iconfont icon-jinggao2" @click="clearStartTime" v-if="startTime"></text>
</view>
<view class="time-interval row verCenter bothSide">
<view class="row verCenter">
<text class="iconfont icon-juxing41"></text>
<picker mode="date" @change="handleDateChange(2, $event)">
<input type="text" class="uni-input" :placeholder="endPlaceholder" placeholder-style="color:#919399" :value="endTime" />
</picker>
</view>
<text class="iconfont icon-jinggao2" @click="clearEndTime" v-if="endTime"></text>
</view>
</view>
</template>
<script>
export default {
props: {
// 开始时间
startTime: {
type: String,
default: ''
},
// 结束时间
endTime: {
type: String,
default: ''
},
// 开始时间占位符
startPlaceholder: {
type: String,
default: '请选择开始日期'
},
// 结束时间占位符
endPlaceholder: {
type: String,
default: '请选择结束日期'
},
// 是否自动校验时间范围
autoValidate: {
type: Boolean,
default: true
}
},
methods: {
/**
* 处理日期选择变化
* @param {Number} type 1-起始时间 2-结束时间
* @param {Object} event 事件对象
*/
handleDateChange(type, event) {
var selectedDate = event.detail.value;
var newStartTime = this.startTime;
var newEndTime = this.endTime;
if (type === 1) {
newStartTime = selectedDate;
} else if (type === 2) {
newEndTime = selectedDate;
}
// 时间范围校验
if (this.autoValidate && newStartTime && newEndTime && newStartTime > newEndTime) {
uni.showToast({
title: '开始时间不能大于结束时间',
icon: 'none'
});
return;
}
// 触发更新事件
this.$emit('change', {
startTime: newStartTime,
endTime: newEndTime,
dateRange: this.formatDateRange(newStartTime, newEndTime)
});
},
/**
* 清除开始时间
*/
clearStartTime() {
this.$emit('change', {
startTime: '',
endTime: this.endTime,
dateRange: this.formatDateRange('', this.endTime)
});
},
/**
* 清除结束时间
*/
clearEndTime() {
this.$emit('change', {
startTime: this.startTime,
endTime: '',
dateRange: this.formatDateRange(this.startTime, '')
});
},
/**
* 格式化日期范围
* @param {String} start 开始时间
* @param {String} end 结束时间
*/
formatDateRange(start, end) {
if (start && end) {
return `${start} ~ ${end}`;
} else if (start) {
return `${start} ~ ${start}`;
} else if (end) {
return `${end} ~ ${end}`;
} else {
return '';
}
}
}
};
</script>
<style scoped lang="scss">
.time-interval-box {
.time-interval {
width: 48%;
height: 60rpx;
background: #ffffff;
border-radius: 10rpx;
padding-left: 17rpx;
padding-right: 10rpx;
box-sizing: border-box;
.iconfont {
font-size: 32rpx;
color: #919399;
}
.uni-input {
margin-left: 13rpx;
font-size: 24rpx;
}
}
}
</style>
\ No newline at end of file
<template>
<scroll-view
class="scroll-list"
:scroll-y="true"
:lower-threshold="lowerThreshold"
@scrolltolower="handleLoadMore"
:refresher-enabled="refresherEnabled"
:refresher-triggered="refreshing"
@refresherrefresh="handleRefresh"
>
<!-- 数据列表插槽,使用 key 强制完整渲染,解决 APP 端首次加载 flex 布局计算问题 -->
<view class="slot-wrapper" :key="slotKey">
<slot></slot>
</view>
<!-- 骨架屏 -->
<view class="skeleton-list" v-if="skeleton">
<view class="skeleton-item" v-for="i in skeletonCount" :key="i">
<slot name="skeleton">
<view class="skeleton-checkbox"></view>
<view class="skeleton-content">
<view class="skeleton-row">
<view class="skeleton-line skeleton-line-short"></view>
<view class="skeleton-line skeleton-line-short"></view>
</view>
<view class="skeleton-row">
<view class="skeleton-line skeleton-line-medium"></view>
<view class="skeleton-line skeleton-line-medium"></view>
</view>
<view class="skeleton-row">
<view class="skeleton-line skeleton-line-long"></view>
</view>
<view class="skeleton-row">
<view class="skeleton-line skeleton-line-short"></view>
<view class="skeleton-line skeleton-line-short"></view>
</view>
</view>
<view class="skeleton-btn"></view>
</slot>
</view>
</view>
<!-- 无数据展示 -->
<view class="scroll-list-empty" v-if="showEmpty">
<text class="iconfont icon-wushuju"></text>
<text class="text">{{ emptyText }}</text>
</view>
<!-- 加载更多 -->
<view class="loading-more" v-if="loadingMore">
<view class="loading-icon"></view>
<text class="loading-text">加载中...</text>
</view>
<!-- 数据到底提示 -->
<view class="load-bottom" v-if="showBottom">—— {{ bottomText }} ——</view>
</scroll-view>
</template>
<script>
export default {
name: 'ScrollList',
props: {
// 列表数据
list: {
type: Array,
default: () => []
},
// 骨架屏显示状态
skeleton: {
type: Boolean,
default: false
},
// 下拉刷新状态
refreshing: {
type: Boolean,
default: false
},
// 加载更多状态
loadingMore: {
type: Boolean,
default: false
},
// 数据到底标识
loadBottom: {
type: Boolean,
default: false
},
// 是否还有更多数据
hasMoreData: {
type: Boolean,
default: true
},
// 当前页码
page: {
type: Number,
default: 1
},
// 骨架屏数量
skeletonCount: {
type: Number,
default: 4
},
// 空数据提示文字
emptyText: {
type: String,
default: '查不到当前数据'
},
// 数据到底提示文字
bottomText: {
type: String,
default: '数据已经到底'
},
// 触底距离(单位px)
lowerThreshold: {
type: Number,
default: 100
},
// 是否启用下拉刷新
refresherEnabled: {
type: Boolean,
default: true
}
},
computed: {
// slot 的 key,基于 list 长度和 skeleton 状态生成,强制重新渲染
slotKey() {
return `slot-${this.list.length}-${this.skeleton ? 1 : 0}`;
},
// 显示空数据提示
showEmpty() {
return !this.skeleton && this.list.length === 0 && !this.loadingMore && !this.refreshing;
},
// 显示到底提示:第一页不显示,只有翻页后数据到底才显示
showBottom() {
return this.loadBottom && this.list.length > 0 && !this.loadingMore && this.page > 1;
}
},
methods: {
/**
* 下拉刷新
*/
handleRefresh() {
if (this.refreshing) return;
// #ifdef APP-PLUS
uni.vibrateShort();
// #endif
this.$emit('refresh');
},
/**
* 加载更多
*/
handleLoadMore() {
if (!this.hasMoreData || this.loadingMore || this.loadBottom) return;
this.$emit('loadmore');
}
}
};
</script>
<style scoped lang="scss">
.scroll-list {
flex: 1;
height: 100%;
}
.slot-wrapper {
width: 100%;
}
.skeleton-list {
padding: 0;
.skeleton-item {
display: flex;
flex-wrap: wrap;
position: relative;
padding: 15px 17rpx 18rpx 17rpx;
background: #ffffff;
box-shadow: 0px 3rpx 3rpx 0px rgba(198, 199, 204, 0.3);
border-radius: 10rpx;
margin-bottom: 15rpx;
}
.skeleton-checkbox {
width: 36rpx;
height: 36rpx;
background: linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
border-radius: 6rpx;
margin-right: 10rpx;
}
.skeleton-content {
flex: 1;
}
.skeleton-row {
display: flex;
flex-wrap: wrap;
margin-bottom: 12rpx;
}
.skeleton-line {
height: 24rpx;
background: linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
border-radius: 4rpx;
margin-right: 20rpx;
margin-bottom: 8rpx;
}
.skeleton-line-short {
width: 35%;
}
.skeleton-line-medium {
width: 45%;
}
.skeleton-line-long {
width: 90%;
}
.skeleton-btn {
position: absolute;
right: 17rpx;
bottom: 18rpx;
width: 80rpx;
height: 38rpx;
background: linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
border-radius: 8rpx;
}
}
@keyframes shimmer {
0% {
background-position: -200% 0;
}
100% {
background-position: 200% 0;
}
}
.scroll-list-empty {
padding: 100rpx 0;
.iconfont {
font-size: 160rpx;
color: #ccc;
}
.text {
font-size: 20rpx;
color: #484B59;
margin-top: 20rpx;
}
}
.loading-more {
padding: 30rpx 0;
.loading-icon {
width: 36rpx;
height: 36rpx;
border: 4rpx solid #e5e5e5;
border-top-color: #1969f9;
border-radius: 50%;
animation: spin 0.8s linear infinite;
margin-right: 16rpx;
}
.loading-text {
font-size: 26rpx;
color: #999;
}
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.load-bottom {
padding: 30rpx 0;
font-size: 24rpx;
color: #999;
}
.scroll-list-empty {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.loading-more {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.load-bottom {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
</style>
<template>
<view class="search-box-container row bothSide verCenter">
<!-- 选择器区域 -->
<view class="picker-wrapper row rowCenter verCenter" v-if="showPicker">
<picker @change="handlePickerChange" :value="currentPickerIndex" :range="pickerOptions">
<view class="picker-content row verCenter">
<view class="picker-text">{{ pickerOptions[currentPickerIndex] }}</view>
<view class="picker-arrow"></view>
</view>
</picker>
</view>
<!-- 搜索输入框区域 -->
<view class="input-wrapper row bothSide verCenter" :class="{ 'full-width': !showPicker }">
<view class="input-content row verCenter">
<text class="search-icon iconfont icon-juxing11" @click="handleSearchIconClick"></text>
<input class="search-input" :placeholder="placeholder" :placeholder-style="placeholderStyle" :focus="inputFocus" v-model="inputValue" @input="handleInput" maxlength="-1" />
</view>
<text class="clear-icon iconfont icon-a-juxing111" @click="handleClearInput" v-if="showClearIcon"></text>
</view>
</view>
</template>
<script>
// #ifdef APP-PLUS
import { openScan } from '@/uni_modules/xtf-scanqrcode';
// #endif
export default {
name: 'SearchBoxWithPicker',
props: {
// 是否显示选择器
showPicker: {
type: Boolean,
default: true
},
// 选择器选项数组
pickerOptions: {
type: Array,
default: () => ['全量搜索']
},
// 选择器默认选中索引
pickerIndex: {
type: Number,
default: 0
},
// 输入框占位符
placeholder: {
type: String,
default: '请输入搜索关键词'
},
// 占位符样式
placeholderStyle: {
type: String,
default: 'color:#919399'
},
// 输入框是否自动获取焦点
focus: {
type: Boolean,
default: false
},
// 输入框默认值
value: {
type: String,
default: ''
},
// 是否显示清空图标
showClear: {
type: Boolean,
default: false
},
// 是否启用扫码功能
showScan: {
type: Boolean,
default: false
}
},
data() {
return {
currentPickerIndex: this.pickerIndex,
inputValue: this.value,
inputFocus: this.focus,
showClearIcon: this.showClear
};
},
watch: {
value(newVal) {
this.inputValue = newVal;
},
focus(newVal) {
this.inputFocus = newVal;
},
showClear(newVal) {
this.showClearIcon = newVal;
},
pickerIndex(newVal) {
this.currentPickerIndex = newVal;
}
},
methods: {
/**
* 选择器变化事件
*/
handlePickerChange(e) {
this.currentPickerIndex = e.detail.value;
this.$emit('picker-change', {
index: this.currentPickerIndex,
value: this.pickerOptions[this.currentPickerIndex]
});
},
/**
* 输入框输入事件
*/
handleInput(e) {
const value = e.detail.value;
this.inputValue = value;
this.showClearIcon = !!value;
this.$emit('input', value);
this.$emit('update:value', value);
},
/**
* 清空输入
*/
handleClearInput() {
this.inputValue = '';
this.showClearIcon = false;
this.$emit('clear');
this.$emit('update:value', '');
// 重新获取焦点
this.inputFocus = false;
setTimeout(() => {
this.inputFocus = true;
}, 200);
},
/**
* 搜索图标点击事件
*/
handleSearchIconClick() {
if (!this.showScan) return;
// #ifdef APP-PLUS
openScan({
scanHintText: '请将条码/二维码对准扫描框',
fullScreenScan: true,
isShowBeep: false,
isShowVibrate: true,
isShowLightController: true,
isShowPhotoAlbum: false,
success: (type, data) => {
if (type === 0) {
this.inputValue = data;
this.showClearIcon = true;
this.$emit('update:value', data);
this.$emit('scan', data);
}
}
});
// #endif
// #ifdef MP-WEIXIN
uni.scanCode({
success: (res) => {
var data = res.result;
this.inputValue = data;
this.showClearIcon = true;
this.$emit('update:value', data);
this.$emit('scan', data);
}
});
// #endif
}
}
};
</script>
<style scoped lang="scss">
.search-box-container {
height: 60rpx;
background: #ffffff;
border-radius: 10rpx;
padding: 0 18rpx;
.picker-wrapper {
width: 160rpx;
height: 100%;
border-right: 1px solid #f0f0f2;
padding: 0 12rpx 0 0;
.picker-text {
font-size: 24rpx;
color: #292b33;
font-weight: 600;
}
.picker-arrow {
width: 0;
height: 0;
border-left: 8rpx solid transparent;
border-right: 8rpx solid transparent;
border-top: 11rpx solid #666;
margin-left: 12rpx;
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
transform-origin: center 30%;
&:active {
transform: rotate(180deg) scale(1.1);
border-top-color: #1969f9;
}
}
}
.input-wrapper {
flex: 1;
height: 100%;
margin-left: 2rpx;
&.full-width {
margin-left: 0;
}
.input-content {
flex: 1;
}
.search-icon {
font-size: 30rpx;
color: #919399;
margin-left: 10rpx;
margin-right: 14rpx;
flex-shrink: 0;
}
.search-input {
flex: 1;
font-size: 24rpx;
color: #484b59;
height: 100%;
}
.clear-icon {
font-size: 30rpx;
color: #c6c7cc;
margin-left: 10rpx;
flex-shrink: 0;
}
}
}
</style>
...@@ -278,6 +278,11 @@ ...@@ -278,6 +278,11 @@
"style": { "style": {
"navigationBarTitleText": "滞留预警" "navigationBarTitleText": "滞留预警"
} }
}, {
"path": "pages/stockOut/stockOutReceiptUpload",
"style": {
"navigationBarTitleText": "快递回单上传"
}
}], }],
"globalStyle": { "globalStyle": {
"navigationBarTextStyle": "black", "navigationBarTextStyle": "black",
......
...@@ -214,7 +214,9 @@ ...@@ -214,7 +214,9 @@
}, },
gridClick(item, index) { gridClick(item, index) {
if (item.name == '快递回单上传') { if (item.name == '快递回单上传') {
this.scanChange(); uni.navigateTo({
url: '/pages/stockOut/stockOutReceiptUpload'
});
} else if (item.name == '打印标签') { } else if (item.name == '打印标签') {
uni.navigateTo({ uni.navigateTo({
url: '/pages/tag/printNew' url: '/pages/tag/printNew'
......
<template>
<view class="page-box">
<!-- 时间筛选 -->
<DateRangePicker :startTime="start_time" :endTime="end_time" @change="handleDateRangeChange" />
<view class="search-all-box">
<SearchBoxWithPicker :showPicker="false" :showScan="true" placeholder="请输入出库单号、订单号、型号、箱号进行查询" :focus="is_focus" :value="searchParams.stock_out_search_key" :showClear="input_flag" @input="handleInput(1, $event)" @scan="handleScan" @clear="clearInput" />
</view>
<view class="tips row bothSide verCenter">
<view class="text">以下数据为<text class="blue">销售出库</text>类型的<text class="blue">待出库、已出库</text>出库单</view>
<view class="summary"><text class="blue">{{ total }}</text>条数据</view>
</view>
<!-- 列表区 -->
<ScrollList
class="list-scroll"
:list="list"
:skeleton="skeleton"
:refreshing="refreshing"
:loadingMore="loadingMore"
:loadBottom="loadBottom"
:hasMoreData="hasMoreData"
:page="searchParams.page"
@refresh="onRefresh"
@loadmore="loadMore"
>
<view class="sc-card-list" v-if="list.length > 0">
<view class="sc-card row" v-for="(item, index) in list" :key="index">
<view class="sc-card-badge" :class="item.stock_out_status == 1 ? 'pending' : 'shipped'">{{ item.stock_out_status_cn }}</view>
<view class="sc-card-item row">
<text class="label">出库单号:</text>
<text class="blue">{{ item.stock_out_sn }}</text>
</view>
<view class="sc-card-item row">
<text class="label">订单号:</text>
<text class="blue">{{ item.order_sn }}</text>
</view>
<view class="sc-card-item row">
<text class="label">出库类型:</text>
<text class="text">{{ item.stock_out_type_cn }}</text>
</view>
<view class="sc-card-item row full">
<text class="label">业务/商务:</text>
<text class="text" v-if="item.bs_name && item.sale_name">{{ item.bs_name }}/{{ item.sale_name }}</text>
</view>
<view class="sc-card-item row">
<text class="label">型号数:</text>
<text class="text">{{ item.goods_name_num }}</text>
</view>
<view class="sc-card-item row full">
<text class="label">客户:</text>
<text class="text">{{ item.customer_name }}</text>
</view>
<view class="sc-card-item row full">
<text class="label">出库时间:</text>
<text class="text">{{ item.stock_out_time_cn }} {{ item.create_name }}</text>
</view>
<view class="sc-card-item row full">
<text class="label">出库备注:</text>
<text class="desc">{{ item.upstream_remark }}</text>
</view>
<view class="sc-card-item row full">
<text class="label">回单图片:</text>
<view class="pick_img_list row">
<template v-if="item.sign_file">
<view class="img_list" v-for="(v, i) in item.sign_file.split(',')" :key="i">
<image :src="v" mode="aspectFill" @click="previewChange(item.sign_file.split(','), i)"></image>
<view class="delete-btn" @click="deleteImage(item.stock_out_id, i)">
<text class="iconfont icon-shanchu"></text>
</view>
</view>
</template>
<view class="default row rowCenter verCenter" @click="chooseImage(item.stock_out_id)">
<text class="iconfont icon-xingzhuangjiehe"></text>
</view>
</view>
</view>
</view>
</view>
</ScrollList>
</view>
</template>
<script>
import { API } from '@/util/api.js';
import { debounce } from '@/util/util.js';
import DateRangePicker from '@/components/DateRangePicker.vue';
import SearchBoxWithPicker from '@/components/SearchBoxWithPicker.vue';
import ScrollList from '@/components/ScrollList.vue';
export default {
components: {
DateRangePicker,
SearchBoxWithPicker,
ScrollList
},
data() {
return {
noexebshowFalg: true, //控制是否会触发生命周期
input_flag: false,
is_focus: true, //获取焦点动态化
list: [],
total: 0,
stock_out_item_sum: 0, //出库单型号数量
start_time: '', //开始时间
end_time: '', //结束时间
searchParams: {
page: 1,
limit: 10,
stock_out_type: 1, //销售出库
stock_out_status: '1,2', //1-待出库 2-已出库
create_time: '', //创建时间
stock_out_search_key: ''
},
hasMoreData: true, //是否还有更多数据
skeleton: true, //骨架屏显示状态
refreshing: false, //下拉刷新状态
loadingMore: false, //加载更多状态
loadBottom: false, //数据到底标识
stock_out_id: '', //出库单id
sign_file: ''
};
},
onShow() {
if (this.noexebshowFalg) {
this.resetChange();
this.getData();
}
},
methods: {
/**
* 下拉刷新
*/
onRefresh() {
this.refreshing = true;
this.list = [];
this.searchParams.page = 1;
this.hasMoreData = true;
this.loadBottom = false;
this.loadingMore = false;
this.skeleton = false;
this.getData();
},
/**
* 处理日期范围变化
* @param {Object} dateInfo 日期信息对象
*/
handleDateRangeChange(dateInfo) {
this.start_time = dateInfo.startTime;
this.end_time = dateInfo.endTime;
this.searchParams.create_time = dateInfo.dateRange;
this.resetChange();
this.getData();
},
/**
* 清除搜索输入内容
*/
clearInput() {
this.searchParams.stock_out_search_key = '';
this.clearInputAndFocus();
this.resetChange();
this.getData();
},
/**
* 滚动到底部加载更多
*/
loadMore() {
this.loadingMore = true;
this.searchParams.page++;
this.getData();
},
/**
* @param {Object} type
* @param {String} value
*/
handleInput: debounce(function (type, value) {
this.searchParams.stock_out_search_key = value;
this.input_flag = !!value;
this.resetChange();
this.getData();
}, 500),
/**
* 扫码回调
*/
handleScan(value) {
this.searchParams.stock_out_search_key = value;
this.input_flag = !!value;
this.resetChange();
this.getData();
},
/**
* 重置
*/
resetChange() {
this.list = [];
this.searchParams.page = 1;
this.hasMoreData = true;
this.loadBottom = false;
this.loadingMore = false;
this.skeleton = true;
},
/**
* 再次获取焦点
*/
clearInputAndFocus() {
this.input_flag = false; //关闭叉叉
this.is_focus = false;
setTimeout(() => {
this.is_focus = true;
}, 200);
},
/**
* 预览图片
* @param {Object} img
* @param {Object} index
*/
previewChange(arr, index) {
this.noexebshowFalg = false;
uni.previewImage({
current: index,
urls: arr
});
},
/**
* 获取数据
*/
getData() {
var currentPage = this.searchParams.page;
this.request(API.stockOutList, 'POST', this.searchParams, false).then(res => {
// 关闭骨架屏、下拉刷新和加载更多
this.skeleton = false;
this.refreshing = false;
this.loadingMore = false;
if (res.code === 0) {
var totalCount = res.data.total || 0;
var pageMax = Math.ceil(totalCount / this.searchParams.limit);
// 只有第一页才更新total
if (currentPage === 1) {
this.stock_out_item_sum = res.data.stock_out_item_sum || 0;
this.total = totalCount;
}
var newData = res.data.list || [];
// 无数据情况
if (pageMax <= 0) {
this.list = [];
this.loadBottom = false;
this.hasMoreData = false;
} else {
// 判断是否到底
if (currentPage >= pageMax) {
this.hasMoreData = false;
this.loadBottom = true;
}
// 第一页直接替换,非第一页追加
this.list = currentPage === 1 ? newData : [...this.list, ...newData];
}
} else {
uni.showToast({
title: res.msg,
icon: 'none'
});
}
});
},
/**
* 选择图片
*/
chooseImage(stock_out_id) {
this.noexebshowFalg = false;
uni.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: chooseImageRes => {
console.log('选择图片成功:', chooseImageRes);
// 显示loading
uni.showLoading({
title: '上传中...'
});
// 获取选择的图片路径数组
const imagePaths = chooseImageRes.tempFilePaths;
// 遍历图片路径数组,对每张图片进行压缩
imagePaths.forEach(imagePath => {
// 使用compressImage 压缩图片
uni.compressImage({
src: imagePath,
quality: 60, //压缩质量,范围0~100,数值越小,质量越低,压缩率越高
success: compressedRes => {
console.log('压缩图片成功:', compressedRes);
// 获取压缩后的图片路径
const compressedImagePath = compressedRes.tempFilePath;
// 在这里处理压缩后的图片,上传到服务器
uni.uploadFile({
url: API.upload + '?sys_type=4',
filePath: compressedImagePath,
name: 'file',
timeout: 10000,
header: {
'Content-Type': 'multipart/form-data'
},
success: uploadFileRes => {
console.log('服务器上传图片成功:', uploadFileRes);
uni.hideLoading();
let data = JSON.parse(uploadFileRes.data);
if (data.code === 0) {
this.stock_out_id = stock_out_id;
this.sign_file = data.data.oss_image_url;
this.uploadExpressPic();
} else {
uni.showToast({
title: data.msg,
icon: 'none'
});
}
},
fail: error => {
uni.showToast({
title: '上传图片失败',
icon: 'none'
});
uni.hideLoading();
}
});
},
fail: err => {
console.log('压缩图片失败:', err);
}
});
});
}
});
},
/**
* 删除回单图片
*/
deleteImage(stock_out_id, index) {
// 获取当前出库单
var targetItem = this.list.find(item => item.stock_out_id === stock_out_id);
if (targetItem && targetItem.sign_file) {
// 将图片字符串分割成数组
var imageArray = targetItem.sign_file.split(',');
// 删除指定索引的图片
imageArray.splice(index, 1);
// 重新拼接剩余图片
var remainingImages = imageArray.join(',');
// 调用接口更新
this.request(API.uploadExpressPic, 'POST', { stock_out_id: stock_out_id, sign_file: remainingImages }, true).then(res => {
if (res.code === 0) {
uni.showToast({
title: '删除成功',
icon: 'success'
});
// 更新本地数据
targetItem.sign_file = remainingImages;
this.$forceUpdate();
} else {
uni.showToast({
title: res.msg,
icon: 'none'
});
}
});
}
},
/**
* 快递回单上传
*/
uploadExpressPic() {
// 获取当前出库单已有的回单图片
var targetItem = this.list.find(item => item.stock_out_id === this.stock_out_id);
var allSignFiles = '';
// 拼接之前的图片和新上传的图片
if (targetItem && targetItem.sign_file) {
allSignFiles = targetItem.sign_file + ',' + this.sign_file;
} else {
allSignFiles = this.sign_file;
}
this.request(API.uploadExpressPic, 'POST', { stock_out_id: this.stock_out_id, sign_file: allSignFiles }, true).then(res => {
if (res.code === 0) {
uni.showToast({
title: '上传成功',
icon: 'success'
});
setTimeout(() => {
// 更新回单图片
if (targetItem) {
targetItem.sign_file = allSignFiles;
}
this.$forceUpdate();
}, 2000);
} else {
uni.showToast({
title: res.msg,
icon: 'none'
});
}
});
}
}
};
</script>
<style scoped lang="scss">
@import '@/assets/css/stockOut/stockOutReceiptUpload.scss';
</style>
\ No newline at end of file
...@@ -7,13 +7,15 @@ var ENV_CONFIG = { ...@@ -7,13 +7,15 @@ var ENV_CONFIG = {
API_BASE: 'https://api.ichunt.com', API_BASE: 'https://api.ichunt.com',
API_BASE_OSS: 'https://image.ichunt.net', API_BASE_OSS: 'https://image.ichunt.net',
API_BASE_OSS_HK: 'http://hk.image.semour.com', API_BASE_OSS_HK: 'http://hk.image.semour.com',
API_BASE_WMS: 'https://wms.ichunt.net' API_BASE_WMS: 'https://wms.ichunt.net',
API_BASE_SCWMS: 'http://scwms.ichunt.net'
}, },
development: { development: {
API_BASE: 'http://api.liexin.com', API_BASE: 'http://api.liexin.com',
API_BASE_OSS: 'http://image.liexindev.net', API_BASE_OSS: 'http://image.liexindev.net',
API_BASE_OSS_HK: 'http://image.liexindev.net', API_BASE_OSS_HK: 'http://image.liexindev.net',
API_BASE_WMS: 'http://wms.liexindev.net' API_BASE_WMS: 'http://wms.liexindev.net',
API_BASE_SCWMS: 'http://adminwms.liexindev.net'
} }
}; };
...@@ -23,6 +25,7 @@ var API_BASE = currentEnv.API_BASE; ...@@ -23,6 +25,7 @@ var API_BASE = currentEnv.API_BASE;
var API_BASE_OSS = currentEnv.API_BASE_OSS; var API_BASE_OSS = currentEnv.API_BASE_OSS;
var API_BASE_OSS_HK = currentEnv.API_BASE_OSS_HK; var API_BASE_OSS_HK = currentEnv.API_BASE_OSS_HK;
var API_BASE_WMS = currentEnv.API_BASE_WMS; var API_BASE_WMS = currentEnv.API_BASE_WMS;
var API_BASE_SCWMS = currentEnv.API_BASE_SCWMS;
// 环境日志输出 // 环境日志输出
var envText = ENV === 'production' ? '🔴 正式环境' : '🟢 测试环境'; var envText = ENV === 'production' ? '🔴 正式环境' : '🟢 测试环境';
...@@ -425,7 +428,15 @@ var API = { ...@@ -425,7 +428,15 @@ var API = {
/** /**
* 滞留数据详情 * 滞留数据详情
*/ */
getRetentionList: API_BASE + '/supplywechatwms/getRetentionList' getRetentionList: API_BASE + '/supplywechatwms/getRetentionList',
/**
* 销售出库单列表(快递回单上传)
*/
stockOutList: API_BASE_SCWMS + '/api/stockOut/stockOutList',
/**
* 快递回单上传
*/
uploadExpressPic: API_BASE_SCWMS + '/api/stockOut/uploadExpressPic'
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment