daShangDao_miniProgram/components/TitleUploadForm.vue
2026-06-15 16:37:57 +08:00

1319 lines
34 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="form-container">
<view v-if="currentTab === 'title'" class="form-content">
<view class="view-container">
<warehouse-selector :initialStorage="selectedStorage" :initialWarehouse="selectedWarehouse"
@label-click="navigateBack" @storage-selected="handleStorageSelected"
ref="warehouseSelector"></warehouse-selector>
<view class="view-item view-item-7" @click.stop="handleSearchBoxClick" style="position:relative;">
<view class="label">书名</view>
<input class="scan-input" v-model="formData2.bookName" placeholder="请输入书名" @click.stop />
<view class="scan-btn" @click.stop="getBookName">
<text>查询</text>
</view>
</view>
</view>
<view class="view-container">
<view class="view-item view-item-7">
<view class="label">isbn</view>
<view class="input-group">
<input class="scan-input" v-model="displayIsbn" placeholder="请输入isbn"
:disabled="isUnrecognized" />
<view class="unrecognized-checkbox">
<checkbox :checked="isUnrecognized" @click="toggleUnrecognized"
style="transform:scale(0.7);" />
<text class="checkbox-label">不识别</text>
</view>
</view>
</view>
</view>
<book-condition-select ref="conditionSelect" @change="onConditionChange"></book-condition-select>
<view class="view-container" v-if="searchResults.length > 0">
<view class="view-item">
<view class="label">更多</view>
<view class="input-group">
<picker @change="onBookResultChange" :value="selectedBookIndex" :range="bookResultOptions"
range-key="text">
<view class="picker-content">
{{ selectedBookItem ? selectedBookItem.text : '请选择搜索结果' }}
<text class="arrow"></text>
</view>
</picker>
</view>
</view>
</view>
<price-stock-control :price.sync="value4" :stock.sync="value3" @priceChange="onPriceChange"
@stockChange="onStockChange" />
<camera-upload v-model="fileList1" :maxCount="9" :isbn="formData2.isbn" :bookName="formData2.bookName"
@input="handleFileChange"></camera-upload>
<view class="view-container">
<view class="view-item">
<view class="label">市场竞争</view>
</view>
<view class="tag-input-group">
<text v-for="(item, index) in marketTags" :key="index" class="market-tag">
[{{ item.label }}{{ item.value }}]
</text>
</view>
</view>
<on-sale-products :initialOnSaleProducts="onSaleProducts"
:initialDisplayOnSaleProducts="displayOnSaleProducts" :initialCompareType="compareType"
:isbn="formData2.isbn" :bookName="formData2.bookName" @compare-type-change="handleCompareTypeChange"
@filters-applied="handleFiltersApplied" @filters-reset="handleFiltersReset"
@products-updated="handleProductsUpdated" :showCompareButton="false" ref="onSaleProductsComponent" />
<view class="form-item fixed-bottom" v-show="showSubmitButton">
<button type="primary" @click="submitForm" class="submit-btn"
:disabled="isSubmitting">{{ isSubmitting ? '正在提交...' : '提交' }}</button>
<u-popup class="form-popup" :show="popupDialog.show" mode="center">
<view class="popupContentBox">{{ popupDialog.title }}</view>
<view class="popupContentBox">{{ popupDialog.content }}</view>
<view class="c_box_">
<image :src="popupDialog.imgSrc" mode="aspectFill" class="popup-image"></image>
</view>
<view class="select-container">
<view class="custom-select" @click="popupDialog.showPicker = true">
<text>{{ popupDialog.selectedSeries || '请选择' }}</text>
</view>
</view>
<u-picker :show="popupDialog.showPicker" :columns="[popupDialog.seriesOptions]"
@confirm="onSeriesConfirm" @cancel="popupDialog.showPicker = false"></u-picker>
<view class="button-group">
<view class="btn cancel-btn" @click="onPopupCancel">
<text>{{ popupDialog.cancelText }}</text>
</view>
<view class="btn confirm-btn" @click="onPopupConfirm">
<text>{{ popupDialog.confirmText }}</text>
</view>
</view>
</u-popup>
</view>
</view>
</view>
</template>
<script>
import {
mapState
} from 'vuex'
// Vuex 模块拆分后使用命名空间访问
import CryptoJS from 'crypto-js';
import CameraUpload from '@/components/CameraUpload.vue';
import PriceStockControl from '@/components/PriceStockControl.vue';
import BookConditionSelect from '@/components/BookConditionSelect.vue';
import WarehouseSelector from '@/components/WarehouserSelector.vue';
import * as selectBookImage from '@/service/selectBookImage.js';
import BookProductList from '@/components/BookProductList.vue';
import * as bookRecords from '@/service/bookRecords.js';
import {
uploadFile
} from '@/utils/upload.js';
import {
checkMemberBooksCount
} from '@/components/MemberBookCheck.js';
export default {
name: 'TitleUploadForm',
props: {
selectedWarehouse: {
type: Object,
default: null
}
},
computed: {
...mapState('price', ['priceMode', 'priceType', 'averageRange', 'freight', 'minValue']),
...mapState('warehouse', ['selectedPosition']),
displayIsbn: {
get() {
return this.isUnrecognized ? '' : this.formData2.isbn;
},
set(value) {
if (!this.isUnrecognized) {
this.formData2.isbn = value;
}
}
}
},
components: {
'price-stock-control': PriceStockControl,
'camera-upload': CameraUpload,
'book-condition-select': BookConditionSelect,
'on-sale-products': BookProductList,
'warehouse-selector': WarehouseSelector,
},
created() {
this.$selectBookImage = selectBookImage;
},
data() {
return {
currentTab: 'title',
lowestBookPrice: 0,
lowestTotalPrice: 0,
isSubmitting: false,
showSubmitButton: true,
value4: 1.00,
value3: 1,
fileList1: [],
uploadedImages: [],
selectedStorage: '',
warehouse: '',
shelf: '',
location: '',
searchResults: [],
selectedBookIndex: 0,
selectedBookItem: null,
bookResultOptions: [],
selectedConditionName: '',
fixPrice: 1,
compareType: 'isbn',
onSaleProducts: [],
displayOnSaleProducts: [],
soldProducts: [],
publisherOptions: [],
formattedData: [],
authorOptions: [],
filteredOnSaleProducts: [],
filteredSoldProducts: [],
isFiltered: false,
publisherAuthorMap: new Map(),
authorPublisherMap: new Map(),
selectedStorage: '',
shelves: [],
locations: [],
LocalWarehouse: this.selectedWarehouse,
selectedSheId: null,
selectedFreId: null,
formData2: {
isbn: '',
sku: '',
title: '',
art_no: '',
more: '',
bookName: '',
},
columns: [
[],
[],
[]
],
warehouseShelvesData: {},
shelfLocationsData: {},
marketTags: [{
label: '在售:',
value: 0
},
{
label: '旧:',
value: 0
},
{
label: '新:',
value: 0
},
{
label: '已售:',
value: 0
}
],
popupDialog: {
show: false,
title: '',
content: '',
confirmText: '',
cancelText: '',
imgSrc: '',
count: 0,
subFormData: null,
showPicker: false,
selectedSeries: '',
seriesOptions: ['B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N']
},
hasShownUploadMessage: false,
isUnrecognized: false,
};
},
watch: {
selectedWarehouse: {
handler(newVal) {
if (newVal) {
this.columns[0] = [newVal.name];
this.fetchShelves(newVal.id).then(shelves => {
if (shelves.length > 0) {
this.columns[1] = shelves.map(item => item.code);
this.fetchLocations(shelves[0].id).then(locations => {
this.columns[2] = locations.map(item => item.code);
});
} else {
this.columns[1] = [];
this.columns[2] = [];
}
});
this.selectedStorage = '';
this.warehouse = '';
this.shelf = '';
this.location = '';
}
},
immediate: true
},
displayOnSaleProducts: {
handler(newProducts) {
if (newProducts && newProducts.length > 0) {
this.lowestBookPrice = Math.min(...newProducts.map(p => parseFloat(p.bookPrice) || 0));
this.lowestTotalPrice = Math.min(...newProducts.map(p => parseFloat(p.totalPrice) || 0));
this.calculateReferencePrice();
}
},
immediate: true
},
priceMode: {
handler() {
this.calculateReferencePrice();
}
},
priceType: {
handler() {
this.calculateReferencePrice();
}
},
averageRange: {
handler() {
this.calculateReferencePrice();
}
},
freight: {
handler() {
this.calculateReferencePrice();
}
},
minValue: {
handler() {
this.calculateReferencePrice();
}
},
selectedPosition: {
handler() {
this.calculateReferencePrice();
}
}
},
methods: {
loadStorageSelection() {
try {
if (!this.selectedWarehouse || !this.selectedWarehouse.id) {
return;
}
const storageKey = `selectedStorageData_${this.selectedWarehouse.id}`;
const storageData = uni.getStorageSync(storageKey);
if (storageData) {
this.selectedStorage = storageData.selectedStorage || '';
this.warehouse = storageData.warehouse || '';
this.shelf = storageData.shelf || '';
this.location = storageData.location || '';
this.selectedSheId = storageData.selectedSheId || null;
this.selectedFreId = storageData.selectedFreId || null;
this.$nextTick(() => {
if (this.$refs.warehouseSelector) {
const formattedData = {
storage: storageData.selectedStorage,
warehouse: storageData.warehouse,
shelf: storageData.shelf,
location: storageData.location,
shelfId: storageData.selectedSheId,
locationId: storageData.selectedFreId
};
this.$refs.warehouseSelector.updateSelectedStorage(formattedData);
}
});
}
} catch (error) {
console.error('加载货区选择状态失败:', error);
}
},
async resetData() {
console.log('Title组件resetData方法开始执行');
try {
const currentWarehouse = this.warehouse;
const currentShelf = this.shelf;
const currentLocation = this.location;
const currentSelectedStorage = this.selectedStorage;
this.formData2 = {
isbn: '',
sku: '',
title: '',
art_no: '',
more: '',
bookName: '',
};
this.value4 = 1.00;
this.value3 = 1;
this.fileList1 = [];
this.uploadedImages = [];
this.hasShownUploadMessage = false;
this.marketTags = [{
label: '在售:',
value: 0
},
{
label: '旧:',
value: 0
},
{
label: '新:',
value: 0
},
{
label: '已售:',
value: 0
}
];
this.warehouse = currentWarehouse;
this.shelf = currentShelf;
this.location = currentLocation;
this.selectedStorage = currentSelectedStorage;
if (this.$refs.onSaleProductsComponent) {
this.$refs.onSaleProductsComponent.updateProducts([]);
}
if (this.$refs.conditionSelect) {
this.$refs.conditionSelect.resetSelection();
}
if (this.$refs.priceStockControl) {
this.$refs.priceStockControl.reset();
}
console.log('Title组件resetData方法执行完成');
} catch (error) {
console.error('重置数据时发生错误:', error);
return Promise.reject(error);
}
},
handleStorageSelected(data) {
this.selectedStorage = data.storage;
this.warehouse = data.warehouse;
this.shelf = data.shelf;
this.location = data.location;
this.selectedSheId = data.shelfId;
this.selectedFreId = data.locationId;
uni.setStorageSync('warehouseId', this.selectedWarehouse.id);
uni.setStorageSync('shelfId', data.shelfId);
uni.setStorageSync('locationId', data.locationId);
},
handleFiltersApplied(filteredProducts) {
this.filteredOnSaleProducts = filteredProducts;
this.isFiltered = true;
},
handleFiltersReset() {
this.isFiltered = false;
},
handleProductsUpdated(products) {
this.displayOnSaleProducts = products;
this.calculateReferencePrice();
},
async fetchOnSaleProducts(keyword) {
try {
const conditionValue = uni.getStorageSync("conditionValue");
const sortType = 7;
let cookies = uni.getStorageSync('UserInfoCookies');
if (!cookies) {
cookies = uni.getStorageSync('cookies');
}
if (!cookies) {
uni.showToast({
title: '请先在设置页面登录孔网账号',
icon: 'none',
duration: 2500
});
return;
}
const mockData = await this.$selectBookImage.fetchOnSaleProducts(keyword, sortType, conditionValue,
cookies);
const blockedShopsStr = uni.getStorageSync('blockedShops') || '';
const blockedShops = blockedShopsStr.split(';').filter(shop => shop.trim() !== '');
const filteredData = mockData.filter(product => {
return !blockedShops.some(shop => product.shopName && product.shopName.includes(shop
.trim()));
});
this.onSaleProducts = [...filteredData];
if (this.$refs.onSaleProductsComponent) {
this.$refs.onSaleProductsComponent.updateProducts(this.onSaleProducts);
}
this.calculateReferencePrice();
} catch (error) {
console.error('获取在售商品信息失败:', error);
}
},
onConditionChange(index, conditionName) {
this.selectedConditionName = conditionName;
},
handleFileChange(newFileList) {
this.fileList1 = newFileList;
this.isUploading = newFileList.some(file => file.status === 'uploading');
},
async getBookRecords() {
try {
const phoneNumber = uni.getStorageSync('phoneNumber');
if (!phoneNumber) {
uni.showToast({
title: '请先登录',
icon: 'none',
duration: 2500
});
return;
}
uni.showLoading({
title: '加载中...'
});
try {
const records = await bookRecords.fetchBookRecords(phoneNumber);
if (!records || records.length === 0) {
uni.showToast({
title: '暂无上书记录',
icon: 'none',
duration: 2500
});
return;
}
uni.navigateTo({
url: '/pkgUser/book-records',
success: (res) => {
res.eventChannel.emit('bookRecordsData', {
records: records
});
}
});
} finally {
uni.hideLoading();
}
} catch (error) {
console.error('获取上书记录失败:', error);
}
},
onSeriesConfirm(e) {
this.popupDialog.selectedSeries = e.value[0];
this.popupDialog.showPicker = false;
},
async submitForm() {
const lastSubmitTime = uni.getStorageSync('lastSubmitTime');
const currentTime = Date.now();
if (lastSubmitTime) {
const timeDiff = currentTime - lastSubmitTime;
const twoHours = 2 * 60 * 60 * 1000;
if (timeDiff > twoHours) {
uni.showToast({
title: '登录已过期,请重新登录',
icon: 'none',
duration: 2000
});
setTimeout(() => {
uni.navigateTo({
url: '/pages/login/index'
});
}, 2000);
return;
}
}
uni.setStorageSync('lastSubmitTime', currentTime);
const canUpload = await checkMemberBooksCount();
if (!canUpload) {
return;
}
if (this.isSubmitting) {
return;
}
this.isSubmitting = true;
const warehouse = this.warehouse;
const shelf = this.shelf;
const location = this.location;
const userId = uni.getStorageSync("userId");
if (!this.formData2.bookName) {
uni.showToast({
title: '请输入书名',
icon: 'none',
duration: 2500
});
this.isSubmitting = false;
return;
}
if (!warehouse) {
uni.showToast({
title: '请选择仓库/货架/货位',
icon: 'none',
duration: 2500
});
this.isSubmitting = false;
return;
}
if (!shelf) {
uni.showToast({
title: '请选择仓库/货架/货位',
icon: 'none',
duration: 2500
});
this.isSubmitting = false;
return;
}
if (!location) {
uni.showToast({
title: '请选择仓库/货架/货位',
icon: 'none',
duration: 2500
});
this.isSubmitting = false;
return;
}
const selectedCondition = this.$refs.conditionSelect.getSelectedCondition();
if (!selectedCondition) {
uni.showToast({
title: '请选择品相',
icon: 'none',
duration: 2500
});
this.isSubmitting = false;
return;
}
if (this.fileList1.length > 0) {
if (this.fileList1.length > 0) {
const temporaryImages = [];
this.fileList1.forEach((file, index) => {
if (file.url && (file.url.startsWith('file://') ||
file.url.startsWith('blob:') ||
file.url.startsWith('wxfile://') ||
file.url.indexOf('tmp') !== -1)) {
temporaryImages.push(index + 1);
}
});
if (temporaryImages.length > 0) {
uni.showToast({
title: `${temporaryImages.join('、')}张图片上传失败,请重新拍照,若仍然失败请联系管理员!`,
icon: 'none',
duration: 4000
});
this.isSubmitting = false;
return;
}
}
try {
uni.showLoading({
title: '正在上传图片...'
});
this.isUploading = true;
for (let i = 0; i < this.fileList1.length; i++) {
const file = this.fileList1[i];
if (file.status === "ready") {
this.fileList1.splice(i, 1, {
...file,
status: "uploading",
message: "上传中"
});
try {
const result = await this.uploadFilePromise(file.url, i);
this.fileList1.splice(i, 1, {
...file,
status: "success",
message: "",
url: result,
num: (i + 1).toString()
});
} catch (error) {
console.error('图片上传失败:', error);
this.fileList1.splice(i, 1, {
...file,
status: "error",
message: "上传失败",
errorMessage: `${i + 1}张图片上传失败`
});
uni.showModal({
title: '图片上传失败',
content: `${i + 1}张图片上传失败,请检查网络连接后重新上传`,
showCancel: false,
confirmText: '我知道了'
});
this.isSubmitting = false;
this.isUploading = false;
uni.hideLoading();
return;
}
}
}
this.isUploading = false;
uni.hideLoading();
} catch (error) {
console.error('图片上传过程出错:', error);
uni.hideLoading();
uni.showToast({
title: '图片上传失败',
icon: 'none',
duration: 2500
});
this.isSubmitting = false;
this.isUploading = false;
return;
}
}
const invalidImages = [];
this.fileList1.forEach((img, index) => {
if (
img.url &&
(
img.url.startsWith('file://') ||
img.url.startsWith('blob:') ||
img.url.startsWith('wxfile://') ||
img.url.indexOf('tmp') !== -1
)
) {
invalidImages.push({
...img,
index
});
}
});
if (invalidImages.length > 0) {
console.error('发现临时路径图片:', invalidImages);
const problemImageNumbers = invalidImages
.map(img => img.index + 1)
.join('、');
const errorMessage = `${problemImageNumbers}张图片上传异常,请重新上传这些图片`
uni.showModal({
title: '图片上传异常',
content: errorMessage,
showCancel: false,
confirmText: '我知道了',
success: () => {
this.highlightProblemImages(invalidImages);
}
});
this.isSubmitting = false;
return;
}
const sellCountTag = this.marketTags.find(tag => tag.label === '在售:');
const buyCountTag = this.marketTags.find(tag => tag.label === '已售:');
const sellCount = sellCountTag ? sellCountTag.value : 0;
const buyCount = buyCountTag ? buyCountTag.value : 0;
const formData = {
barcode: this.formData2.isbn,
userId: userId,
name: this.formData2.bookName,
recommendation: '',
conditionCode: selectedCondition.name,
price: this.value4 * 100,
inventory: this.value3 || 1,
files: this.fileList1,
marketTags: this.marketTags,
sellCount: sellCount,
buyCount: buyCount,
author: '',
fixPrice: this.fixPrice * 100,
selectedStorage: this.selectedStorage,
depotName: this.warehouse,
shelvesName: this.shelf,
freightName: this.location,
phoneNumber: uni.getStorageSync('phoneNumber'),
passWord: uni.getStorageSync('password'),
tenantId: uni.getStorageSync('tenantId'),
userName: uni.getStorageSync('userName'),
categoryId: ''
};
uni.request({
url: 'https://api.buzhiyushu.cn/zhishu/shopGoods/repeatBook',
method: 'POST',
data: formData,
header: {
'Content-Type': 'application/json'
},
success: (res) => {
if (res.data.data && res.data.data.count != 0) {
const bookName = res.data.data && res.data.data.name ? res.data.data.name
.trim() :
'';
const md5Hash = CryptoJS.MD5(bookName).toString();
const firstLetter = bookName ? md5Hash.charAt(0).toUpperCase() : '';
const imagePath = res.data.data && res.data.data.image ? res.data.data.image :
'';
const fullImageUrl =
`https://img.buzhiyushu.cn/zhishu1/${firstLetter}/${imagePath}`;
const count = res.data.data && res.data.data.count ? res.data.data.count : 0;
const allLetters = ['B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N'
];
const startIndex = count > 0 ? count - 1 : 0;
if (startIndex >= 0 && startIndex < allLetters.length) {
this.popupDialog.seriesOptions = allLetters.slice(startIndex);
this.popupDialog.selectedSeries = this.popupDialog.seriesOptions[0];
}
this.popupDialog.title = '提示'
this.popupDialog.content = '请仔细核对此书是否为套装书,一号多书等情况?请选择(否:增加库存 是:新增书籍)'
this.popupDialog.confirmText = '是'
this.popupDialog.cancelText = '否'
this.popupDialog.imgSrc = fullImageUrl
this.popupDialog.show = true
this.popupDialog.count = count || 0
this.popupDialog.subFormData = formData
} else {
this.submitToServer(formData);
}
},
fail: (err) => {
console.error('检查重复书籍失败:', err);
uni.showToast({
title: '网络错误,请稍后重试',
icon: 'none',
duration: 2500
});
this.isSubmitting = false;
}
});
},
onPopupConfirm() {
this.popupDialog.subFormData.series = this.popupDialog.selectedSeries;
this.submitToServer(this.popupDialog.subFormData);
this.popupDialog.show = false
},
onPopupCancel() {
this.submitToServer(this.popupDialog.subFormData);
this.popupDialog.show = false
},
submitToServer(formData) {
uni.request({
url: 'https://api.buzhiyushu.cn/zhishu/shopGoods/submit',
method: 'POST',
data: formData,
header: {
'Content-Type': 'application/json'
},
complete: () => {
this.isSubmitting = false;
},
success: (res) => {
const responseData = res.data.data;
const idsToPass = {
depotId: responseData.depotId,
freightId: responseData.freightId,
goodsId: responseData.goodsId,
shelvesId: responseData.shelvesId,
userId: responseData.userId,
artNo: responseData.artNo,
};
this.syncBookToCenter(formData);
const newFormData = {
...formData,
...idsToPass
};
uni.request({
url: 'https://newadmin.buzhiyushu.cn/zhishu/shopGoods/submit',
method: 'POST',
data: newFormData,
header: {
'Content-Type': 'application/json'
},
success: (newAdminRes) => {
console.log('newadmin API请求成功:', newAdminRes);
},
fail: (newAdminErr) => {
console.error('newadmin API请求失败:', newAdminErr);
}
});
this.formData2 = {
bookName: '',
recommendation: '',
};
this.value4 = this.value4;
this.value3 = 1;
this.fileList1 = [];
this.uploadedImages = [];
uni.showToast({
title: '提交成功',
icon: 'success',
duration: 2000
});
},
fail: (err) => {
console.error('请求失败:', err);
uni.showToast({
title: '网络错误,请稍后重试',
icon: 'none',
duration: 2500
});
}
});
},
syncBookToCenter(formData) {
const centerUrl = 'https://api.buzhiyushu.cn/zhishu/baseInfo/getXcxData';
const centerData = {
barcode: formData.barcode,
name: formData.name,
price: formData.price,
author: formData.author,
publisher: '',
publishTime: '',
sellCount: formData.sellCount,
buyCount: formData.buyCount,
files: formData.files || [],
kfzBookPic: ''
};
setTimeout(() => {
uni.request({
url: centerUrl,
method: 'POST',
data: centerData,
header: {
'Content-Type': 'application/json'
},
success: (res) => {
console.log('选品中心同步成功:', res);
},
fail: (err) => {
console.error('选品中心同步失败:', err);
}
});
}, 300);
},
uploadFilePromise(url, index) {
return new Promise((resolve, reject) => {
const bookName = this.formData2.bookName;
let isbn = this.formData2.isbn;
if (!isbn || isbn.trim() === '') {
isbn = '';
for (let i = 0; i < 13; i++) {
isbn += Math.floor(Math.random() * 10);
}
}
const warehouseId = uni.getStorageSync('warehouseId');
const shelfId = uni.getStorageSync('shelfId');
const locationId = uni.getStorageSync('locationId');
const num = (index + 1).toString();
uni.uploadFile({
url: "https://xcx.uploadfile.yushutx.com/uploadImages",
filePath: url,
name: "file",
success: (res) => {
console.log('图片上传成功:', res);
const data = JSON.parse(res.data);
const urlData = JSON.parse(data.data);
const imageUrl = urlData.url || url;
this.uploadedImages.push({
url: imageUrl,
bookName: bookName,
isbn: isbn,
num: num,
warehouseId: warehouseId,
shelfId: shelfId,
locationId: locationId,
originalUrl: url
});
resolve(imageUrl);
},
fail: (err) => {
console.error('图片上传失败:', err);
reject(err);
}
});
});
},
highlightProblemImages(invalidImages) {
invalidImages.forEach(invalidImg => {
const index = this.fileList1.findIndex(file => file.url === invalidImg.originalUrl);
if (index !== -1) {
this.$set(this.fileList1[index], 'status', 'error');
this.$set(this.fileList1[index], 'errorMessage', '上传失败,请重新上传');
}
});
this.$forceUpdate();
},
calculateReferencePrice() {
if (!this.displayOnSaleProducts || this.displayOnSaleProducts.length === 0) {
this.value4 = 1.00;
return;
}
let products = [...this.displayOnSaleProducts];
let priceField = 'totalPrice';
products.sort((a, b) => parseFloat(a[priceField]) - parseFloat(b[priceField]));
const shippingFee = this.freight;
const minValue = this.minValue;
const priceMode = uni.getStorageSync("current1");
const selectedPositionIndex = uni.getStorageSync("selectedPositionIndex");
switch (priceMode) {
case 0:
const positionIndex = this.selectedPosition || selectedPositionIndex || 0;
const validIndex = Math.min(positionIndex, products.length - 1);
const selectedTotal = parseFloat(products[validIndex].totalPrice);
this.lowestTotalPrice = parseFloat(products[0].totalPrice);
const lowestPrice = selectedTotal - shippingFee - 0.01;
if (lowestPrice <= minValue) {
this.value4 = minValue;
} else {
this.value4 = parseFloat(lowestPrice.toFixed(2));
}
break;
case 1:
let count = Math.min(this.averageRange, products.length);
let sum = 0;
for (let i = 0; i < count; i++) {
sum += parseFloat(products[i][priceField]);
}
const averagePrice = (sum / count) - shippingFee - 0.01;
if (averagePrice <= minValue) {
this.value4 = minValue;
} else {
this.value4 = parseFloat(averagePrice.toFixed(2));
}
break;
case 2:
this.value4 = parseFloat(products[0].totalPrice);
break;
}
},
navigateBack() {
uni.removeStorageSync('lastSelectedStorage');
uni.removeStorageSync('selectedWarehouse');
uni.removeStorageSync('lastSelectedShelf');
uni.removeStorageSync('lastSelectedLocation');
this.selectedStorage = '';
this.warehouse = '';
this.shelf = '';
this.location = '';
uni.navigateTo({
url: '/pages/warehouse/warehouse-select'
});
},
onPriceChange(value) {
this.value4 = value;
},
onStockChange(value) {
this.value3 = value;
},
async handleCompareTypeChange(payload) {
this.compareType = payload.type;
if (payload.type === 'isbn') {
this.formData2.isbn = payload.value;
} else {
this.formData2.bookName = payload.value;
}
const keyword = payload.type === 'isbn' ? this.formData2.isbn : this.formData2.bookName;
await this.fetchOnSaleProducts(keyword);
},
async getBookName() {
try {
if (!this.formData2.bookName) {
uni.showToast({
title: '请先输入书名',
icon: 'none',
duration: 2500
});
return;
}
uni.showLoading({
title: '查询中...'
});
const keyword = this.formData2.bookName;
await this.fetchOnSaleProducts(keyword);
uni.hideLoading();
} catch (error) {
console.error('获取书名信息失败:', error);
uni.hideLoading();
}
},
handleSearchBoxClick() {
console.log('搜索框被点击');
},
onBookResultChange(e) {
this.selectedBookIndex = e.detail.value;
this.selectedBookItem = this.bookResultOptions[this.selectedBookIndex];
if (this.selectedBookItem) {
this.formData2.isbn = this.selectedBookItem.isbn;
this.formData2.bookName = this.selectedBookItem.bookName;
}
},
toggleUnrecognized() {
this.isUnrecognized = !this.isUnrecognized;
if (this.isUnrecognized) {
this.formData2.isbn = '';
}
},
async fetchShelves(depotId) {
try {
const response = await uni.request({
url: 'https://api.buzhiyushu.cn/shelves/shelves/sheNamelist',
data: {
depotId
}
});
const [err, res] = Array.isArray(response) ? response : [null, response];
if (!res?.data?.rows) {
console.error('获取货架数据失败,返回空数据');
return [];
}
return res.data.rows;
} catch (error) {
console.error('获取货架失败:', error);
return [];
}
},
async fetchLocations(sheId) {
if (!sheId) {
console.error('获取货位列表失败未提供货架ID');
return [];
}
try {
const response = await uni.request({
url: 'https://api.buzhiyushu.cn/freight/freight/freNamelist',
data: {
sheId
}
});
const [err, res] = Array.isArray(response) ? response : [null, response];
if (!res?.data?.rows) {
console.error('获取货位数据失败,返回空数据');
return [];
}
return res.data.rows;
} catch (error) {
console.error('获取货位失败:', error);
return [];
}
},
}
};
</script>
<style scoped>
.form-container {
padding-left: 10rpx;
background-color: #fff;
}
.view-container {
display: flex;
background-color: #fff;
margin-bottom: 20rpx;
overflow: hidden;
border-bottom: 1px solid #ccc;
}
.view-item {
flex: 1;
display: flex;
padding: 4rpx 0;
text-align: center;
color: #666;
position: relative;
}
.view-item-7 {
flex: 7 !important;
}
.view-item>.label {
display: inline;
padding: 13rpx;
text-align: center;
height: 40rpx;
line-height: 40rpx;
color: #000;
font-size: 28rpx;
background-color: #ccc;
border-top-left-radius: 10rpx;
border-bottom-left-radius: 10rpx;
}
.view-item>.input-group {
padding: 10rpx;
text-align: center;
width: 100%;
height: 40rpx;
line-height: 40rpx;
}
.scan-input {
flex: 1;
height: 60rpx;
font-size: 23rpx;
}
.scan-btn {
background: #007AFF;
padding: 8rpx 20rpx;
border-radius: 20rpx;
color: white;
font-size: 24rpx;
margin-left: 10rpx;
}
.unrecognized-checkbox {
display: flex;
align-items: center;
margin-left: 20rpx;
}
.checkbox-label {
font-size: 24rpx;
color: #666;
margin-left: 10rpx;
}
.picker-content {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20rpx;
background-color: #f5f5f5;
border-radius: 8rpx;
height: 60rpx;
}
.arrow {
font-size: 20rpx;
color: #999;
}
.tag-input-group {
display: flex;
flex-wrap: inherit;
gap: 20rpx;
margin-top: 15rpx;
}
.market-tag {
color: #999;
font-size: 29rpx;
margin-right: 12rpx;
font-weight: normal;
background: none;
border: none;
border-radius: 0;
padding: 0;
}
.fixed-bottom {
position: fixed;
bottom: 0;
left: 0;
right: 0;
width: 100%;
padding: 20rpx;
background: #fff;
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.1);
z-index: 999;
box-sizing: border-box;
}
.submit-btn {
width: 100%;
height: 80rpx;
line-height: 80rpx;
text-align: center;
background-color: #007AFF;
color: #fff;
border-radius: 8rpx;
font-size: 32rpx;
}
.submit-btn:disabled {
background-color: #ccc;
opacity: 0.8;
}
.popupContentBox {
width: 600rpx;
padding: 50rpx;
}
.c_box_ {
width: 400rpx;
margin: 50rpx auto;
}
.popup-image {
width: 300rpx;
height: 300rpx;
margin: 20rpx auto;
display: block;
}
.select-container {
margin: 20rpx 0;
text-align: center;
}
.custom-select {
padding: 10rpx 20rpx;
background-color: #f5f5f5;
border-radius: 4rpx;
text-align: center;
cursor: pointer;
}
.custom-select text {
font-size: 28rpx;
color: #333;
}
.button-group {
display: flex;
align-items: center;
gap: 20rpx;
margin: 10rpx 0;
}
.btn {
flex: 1;
height: 80rpx;
border-radius: 8rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
}
.cancel-btn {
background-color: #f0f0f0;
color: #666;
}
.confirm-btn {
background-color: #007AFF;
color: white;
}
.btn:active {
opacity: 0.8;
}
</style>