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

2421 lines
66 KiB
Vue
Raw 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 === 'photo'" class="form-content">
<view class="info-item info-item-row">
<warehouse-selector :initialStorage="selectedStorage" :initialWarehouse="selectedWarehouse"
@label-click="navigateBack" @storage-selected="handleStorageSelected" ref="warehouseSelector"
style="flex: 0.4"></warehouse-selector>
<view class="half-item" style="flex: 0.6">
<text class="label">印刷时间</text>
<view class="input-field time-input-view" @tap="showPrintTimeKeyboard">
<text>{{ bookInfo.printTime || '11111' }}</text>
</view>
<button class="upload-btn" @click="chooseImage" type="default" size="mini">
识图上传
</button>
</view>
</view>
<view class="info-item">
<view class="half-item">
<text class="label">书名</text>
<input type="text" v-model="bookInfo.bookName" class="input-field" placeholder="请输入书名"
:disabled="hasNormalImages" />
<button class="upload-btn" @click="getBookName" type="default" size="mini"
:disabled="hasNormalImages" :class="{'scan-btn-disabled': hasNormalImages}">
书名查询
</button>
</view>
</view>
<view class="info-item">
<view class="half-item">
<text class="label">作者</text>
<input type="text" v-model="bookInfo.author" class="input-field" placeholder="请输入作者" />
<button class="dropdown-btn"
@click.stop="authorDropdownVisible = !authorDropdownVisible">▼</button>
<view v-if="authorDropdownVisible" class="dropdown-list">
<view v-for="(item, idx) in authorOptions" :key="idx">
<view class="dropdown-item" @click="selectAuthor(item)">{{ item }}</view>
<view v-if="idx < authorOptions.length - 1" class="dropdown-divider"></view>
</view>
</view>
</view>
</view>
<view class="info-item" style="position:relative;">
<text class="label">出版社</text>
<input type="text" v-model="bookInfo.publisher" class="input-field" placeholder="请输入出版社" />
<button class="dropdown-btn"
@click.stop="publisherDropdownVisible = !publisherDropdownVisible">▼</button>
<view v-if="publisherDropdownVisible" class="dropdown-list" style="top:70rpx;left:0;">
<view v-for="(item, idx) in publisherOptions" :key="idx">
<view class="dropdown-item" @click="selectPublisher(item)">{{ item }}</view>
<view v-if="idx < publisherOptions.length - 1" class="dropdown-divider"></view>
</view>
</view>
</view>
<view class="info-item category-container">
<view class="half-item">
<text class="label">图书分类</text>
<picker mode="multiSelector" :range="categoryColumns" range-key="name"
@columnchange="onCategoryColumnChange" @change="onCategoryChange" :value="categoryIndexes">
<view class="picker-single">
{{ categoryPathText || '请选择分类' }}
</view>
</picker>
</view>
</view>
<view class="info-item info-item-row">
<view class="half-item format-item" style="position:relative;">
<text class="label">开本</text>
<input type="text" v-model="bookInfo.format" class="input-field" placeholder="请输入开本" />
<button class="dropdown-btn"
@click.stop="formatDropdownVisible = !formatDropdownVisible">▼</button>
<view v-if="formatDropdownVisible" class="dropdown-list"
style="top:70rpx;left:0;max-height:300rpx;">
<view v-for="(item, idx) in formatOptions" :key="idx">
<view class="dropdown-item" @click="selectFormat(item)">{{ item }}</view>
<view v-if="idx < formatOptions.length - 1" class="dropdown-divider"></view>
</view>
</view>
</view>
<view class="half-item isbn-item">
<text class="label">书号</text>
<input type="text" v-model="bookInfo.unifyIsbn" class="input-field" placeholder="请输入统一书号" />
</view>
</view>
<view class="info-item info-item-row">
<view class="half-item format-item">
<text class="label">定价</text>
<input type="digit" v-model="bookInfo.price" class="input-field" placeholder="请输入定价" />
</view>
<view class="half-item isbn-item">
<text class="label">字数</text>
<input type="number" v-model="bookInfo.wordage" class="input-field" placeholder="请输入字数" />
</view>
</view>
<view class="info-item">
<view class="half-item">
<text class="label">ISBN</text>
<input type="text" v-model="bookInfo.isbn" class="input-field" placeholder="请输入ISBN"
:disabled="hasNormalImages" />
</view>
</view>
<book-condition-select ref="conditionSelect" @change="onConditionChange"></book-condition-select>
<price-stock-control :price.sync="value4" :stock.sync="value3" @priceChange="onPriceChange"
@stockChange="onStockChange" />
<camera-upload v-model="fileList1" :maxCount="9" :isbn="bookInfo.isbn" :bookName="bookInfo.bookName"
@input="handleFileChange" @camera-status-change="handleCameraStatusChange"
@upload-status-change="handleUploadStatusChange"></camera-upload>
<on-sale-products :initialOnSaleProducts="onSaleProducts"
:initialDisplayOnSaleProducts="displayOnSaleProducts" :initialCompareType="compareType"
:isbn="bookInfo.isbn" :bookName="bookInfo.bookName" :showCompareButton="false"
:showCopyrightButton="true" :publisher="bookInfo.publisher" :author="bookInfo.author"
@compare-type-change="handleCompareTypeChange" :showFilterButton="false"
@copyright-compare="handleCopyrightCompare" @filters-applied="handleFiltersApplied"
@filters-reset="handleFiltersReset" @products-updated="handleProductsUpdated"
ref="onSaleProductsComponent" />
<view class="view-container" style="margin-top: 40rpx;">
<view class="view-item" @click="getBookRecords" style="display: flex; align-items: center;">
<view class="blue-block"></view>
<text class="general-label" style="background: none; padding: 0;">上书记录</text>
</view>
</view>
<view class="form-item fixed-bottom" v-show="showSubmitButton">
<button type="primary" @click="submitForm" class="submit-btn"
:disabled="isSubmitting || isUploading">{{ isSubmitting ? '正在提交...' : (isUploading ? '图片上传中...' : '提交') }}</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>
<!-- 添加bcode-camera组件 -->
<bcode-camera v-if="showBcodeCamera" tipsText="请将书籍对准取景框" @onConfirm="handleBcodeCameraResult"
@onCancel="handleBcodeCameraCancel" @onUpload="handleBcodeCameraResult" :color="'rgba(0, 122, 255, 0.8)'"
:showScanEffect="true" :scanMode="true" :customStyle="{
scanBox: {
borderColor: '#007AFF',
backgroundColor: 'rgba(0,0,0,0.1)'
}
}" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 9999;">
<view class="scan-container">
<view class="grid-background"></view>
<view class="scan-line"></view>
</view>
</bcode-camera>
</view>
</template>
<script>
import {
mapState
} from 'vuex'
// Vuex 模块拆分后使用命名空间访问
import CryptoJS from 'crypto-js';
import BookConditionSelect from '@/components/BookConditionSelect.vue';
import PriceStockControl from '@/components/PriceStockControl.vue';
import BookProductList from '@/components/BookProductList.vue';
import * as selectBookImage from '@/service/selectBookImage.js';
import WarehouseSelector from '@/components/WarehouserSelector.vue';
import CameraUpload from '@/components/CameraUpload.vue';
import * as bookRecords from '@/service/bookRecords.js';
import {
getAuthorAndPublisher
} from '@/service/getAuthorAndPublisher.js';
import {
checkMemberBooksCount
} from '@/components/MemberBookCheck.js';
// 导入bcode-camera组件
import bcodeCamera from '@/uni_modules/bcode-camera/components/bcode-camera/bcode-camera.vue';
export default {
name: 'PhotoUploadForm',
components: {
'book-condition-select': BookConditionSelect,
'price-stock-control': PriceStockControl,
'on-sale-products': BookProductList,
"warehouse-selector": WarehouseSelector,
"camera-upload": CameraUpload,
"bcode-camera": bcodeCamera, // 注册bcode-camera组件
},
props: {
selectedWarehouse: {
type: Object,
default: null
}
},
computed: {
...mapState('price', ['priceMode', 'priceType', 'averageRange', 'freight', 'minValue']),
...mapState('warehouse', ['selectedPosition']),
hasNormalImages() {
return this.fileList1.some(file => !file.name || !file.name.startsWith('识图-'));
}
},
created() {
this.$selectBookImage = selectBookImage;
},
data() {
return {
currentTab: 'photo',
imageUrl: '',
isLoading: false,
errorMsg: '',
selectedStorage: '',
warehouse: '',
shelf: '',
location: '',
shelves: [],
locations: [],
LocalWarehouse: this.selectedWarehouse,
selectedSheId: null,
selectedFreId: null,
bookInfo: {
bookName: '',
author: '',
publisher: '',
printTime: '',
format: '',
unifyIsbn: '',
price: '',
wordage: '',
isbn: ''
},
value4: 1.00,
value3: 1,
fileList1: [],
uploadedImages: [],
showSubmitButton: true,
isSubmitting: false,
isUploading: false,
authorDropdownVisible: false,
publisherDropdownVisible: false,
formatDropdownVisible: false,
authorOptions: [],
publisherOptions: [],
formatOptions: ['16开', '32开', '大32开', '小32开', '64开', '8开', '24开', '48开', '其他'],
compareType: 'isbn',
onSaleProducts: [],
displayOnSaleProducts: [],
soldProducts: [],
lowestBookPrice: 0,
lowestTotalPrice: 0,
filteredOnSaleProducts: [],
filteredSoldProducts: [],
isFiltered: false,
publisherAuthorMap: new Map(),
authorPublisherMap: new Map(),
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,
categoryList: [],
categoryOptions2: [],
categoryOptions3: [],
categoryLevel1: null,
categoryLevel2: null,
categoryLevel3: null,
selectedCategoryId: '',
categoryIndexes: [],
maxCategoryLevel: 6,
categoryPathText: '',
categoryColumns: [],
categoryLevels: [],
printTimePopupVisible: false,
printTimeTab: 'input',
printTimeYear: '',
printTimeMonth: '',
printTimeActiveInput: 'year',
decades: [
{ label: '50年代', value: '195' },
{ label: '60年代', value: '196' },
{ label: '70年代', value: '197' },
{ label: '80年代', value: '198' },
{ label: '90年代', value: '199' },
{ label: '00年代', value: '200' },
{ label: '10年代', value: '201' },
{ label: '20年代', value: '202' },
],
showBcodeCamera: false, // 添加控制bcode-camera显示的状态
};
},
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('Photo组件resetData方法开始执行');
try {
const currentWarehouse = this.warehouse;
const currentShelf = this.shelf;
const currentLocation = this.location;
const currentSelectedStorage = this.selectedStorage;
this.bookInfo = {
bookName: '',
author: '',
publisher: '',
printTime: '',
format: '',
unifyIsbn: '',
price: '',
wordage: '',
isbn: ''
};
this.value4 = 1.00;
this.value3 = 1;
this.fileList1 = [];
this.uploadedImages = [];
this.hasShownUploadMessage = false;
this.isUploading = 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();
}
this.categoryIndexes = [];
this.categoryPathText = '';
this.selectedCategoryId = '';
this.categoryLevels = [];
this.initCategoryPicker();
console.log('Photo组件resetData方法执行完成');
} catch (error) {
console.error('重置数据时发生错误:', error);
return Promise.reject(error);
}
},
async fetchCategoryData() {
try {
const cookies = uni.getStorageSync('cookies');
if (!cookies) {
console.error('获取分类失败: 未找到cookies');
return;
}
const res = await uni.request({
url: 'https://api.buzhiyushu.cn/api/kongfz/getCategory',
method: 'GET',
data: {
token: cookies
},
header: {
'Content-Type': 'application/json'
}
});
const responseData = Array.isArray(res) ? res[1].data : res.data;
if (responseData && responseData.successResponse) {
this.categoryList = responseData.successResponse;
this.initCategoryPicker();
}
} catch (error) {
console.error('获取分类数据异常:', error);
}
},
handleCameraStatusChange(isCameraOpen) {
this.showSubmitButton = !isCameraOpen;
},
async handleCompareTypeChange(payload) {
this.compareType = payload.type;
if (payload.type === 'isbn') {
this.bookInfo.isbn = payload.value;
} else {
this.bookInfo.bookName = payload.value;
}
const keyword = payload.type === 'isbn' ? this.bookInfo.isbn : this.bookInfo.bookName;
await this.fetchOnSaleProducts(keyword);
},
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;
if (this.fileList1.length > 0 && (!this.hasShownUploadMessage)) {
uni.showToast({
title: '已上传图片,书名不可修改',
icon: 'none',
duration: 2000
});
this.hasShownUploadMessage = true;
} else if (this.fileList1.length === 0) {
this.hasShownUploadMessage = false;
}
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.bookInfo.bookName) {
uni.showToast({
title: '请输入书名',
icon: 'none',
duration: 2500
});
this.isSubmitting = false;
return;
}
if (!warehouse && !shelf && !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.bookInfo.isbn || '',
userId: userId,
name: this.bookInfo.bookName,
recommendation: '',
conditionCode: selectedCondition.name,
price: this.value4 * 100,
inventory: this.value3 || 1,
files: this.fileList1,
marketTags: this.marketTags,
sellCount: sellCount,
buyCount: buyCount,
author: this.bookInfo.author,
fixPrice: this.bookInfo.price ? this.bookInfo.price * 100 : 0,
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: this.selectedCategoryId || ''
};
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.bookInfo = {
bookName: '',
author: '',
publisher: '',
printTime: '',
format: '',
unifyIsbn: '',
price: '',
wordage: '',
isbn: ''
};
this.value4 = 1.00;
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: this.bookInfo.publisher,
publishTime: this.bookInfo.printTime,
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.bookInfo.bookName;
let isbn = this.bookInfo.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;
},
selectAuthor(item) {
this.bookInfo.author = item;
this.authorDropdownVisible = false;
},
selectPublisher(item) {
this.bookInfo.publisher = item;
this.publisherDropdownVisible = false;
},
selectFormat(item) {
this.bookInfo.format = item;
this.formatDropdownVisible = false;
},
},
async getBookName() {
// 检查用户是否可以上传书籍
const canUpload = await checkMemberBooksCount();
if (!canUpload) {
// 如果不能上传,则直接返回,不继续执行
return;
}
// 如果有普通上传的图片,则不允许查询
if (this.hasNormalImages) {
uni.showToast({
title: '已上传图片,不可修改书名',
icon: 'none',
duration: 2000
});
return;
}
try {
// 检查是否有书名
if (!this.bookInfo.bookName) {
uni.showToast({
title: '请输入书名',
icon: 'none',
duration: 2500
});
return;
}
// 检查用户是否可以上传书籍
const canUpload = await checkMemberBooksCount();
if (!canUpload) {
// 如果不能上传,则直接返回,不继续执行
return;
}
// 显示加载提示
uni.showLoading({
title: '查询中...',
mask: true
});
// 获取书籍基本信息
const res = await uni.request({
url: 'https://api.buzhiyushu.cn/zhishu/baseInfo/getBookByName',
method: 'POST',
header: {
'Content-Type': 'application/json'
},
data: {
bookName: this.bookInfo.bookName
}
});
// 处理响应数据
const responseData = Array.isArray(res) ? res[1] : res;
if (responseData.statusCode === 200 && responseData.data && responseData.data.data) {
const resultData = responseData.data.data;
console.log("获取到的书籍信息:", resultData);
// 更新表单数据,保留已有数据
if (resultData) {
this.bookInfo = {
...this.bookInfo,
author: resultData.author || this.bookInfo.author || '',
publisher: resultData.publisher || this.bookInfo.publisher || '',
format: resultData.format || '32',
printTime: resultData.printTime || this.bookInfo.printTime || '',
unifyIsbn: resultData.isbn || this.bookInfo.unifyIsbn || '',
price: resultData.price ? String(resultData.price).replace('元', '') : this.bookInfo.price || '',
wordage: resultData.wordage || this.bookInfo.wordage || ''
};
}
// 处理ISBN
if (!this.bookInfo.isbn) {
try {
const isbnResponse = await uni.request({
url: 'https://api.buzhiyushu.cn/zhishu/statistic/isbn',
method: 'GET'
});
if (Array.isArray(isbnResponse)) {
this.bookInfo.isbn = isbnResponse[1].data;
} else {
this.bookInfo.isbn = isbnResponse.data;
}
console.log("生成的ISBN:", this.bookInfo.isbn);
} catch (error) {
console.error('获取ISBN失败使用备用方案:', error);
this.bookInfo.isbn = this.generateRandomIsbn();
}
}
// 获取作者和出版社信息
await this.updateAuthorAndPublisher();
// 获取在售商品信息
await this.fetchOnSaleProducts(this.bookInfo.bookName);
uni.showToast({
title: '查询成功',
icon: 'success',
duration: 1500
});
} else {
// 如果没有查到数据也获取ISBN和在售商品信息
if (!this.bookInfo.isbn) {
this.bookInfo.isbn = this.generateRandomIsbn();
}
await this.fetchOnSaleProducts(this.bookInfo.bookName);
uni.showToast({
title: '未找到完整信息,已获取部分数据',
icon: 'none',
duration: 2000
});
}
} catch (error) {
console.error('查询失败:', error);
// 即使请求失败,也尝试获取在售商品信息
try {
if (!this.bookInfo.isbn) {
this.bookInfo.isbn = this.generateRandomIsbn();
}
await this.fetchOnSaleProducts(this.bookInfo.bookName);
} catch (innerError) {
console.error('获取在售商品信息失败:', innerError);
}
uni.showToast({
title: '查询失败,已获取部分数据',
icon: 'none',
duration: 2000
});
} finally {
uni.hideLoading();
}
},
async chooseImage() {
console.log('=== chooseImage 方法开始执行 ===');
// 检查用户是否可以上传书籍
console.log('调用 checkMemberBooksCount...');
const canUpload = await checkMemberBooksCount();
console.log('checkMemberBooksCount 返回值:', canUpload);
if (!canUpload) {
// 如果不能上传,则直接返回,不继续执行
console.log("不能上传,直接返回");
return;
}
const warehouse = this.warehouse;
const shelf = this.shelf;
const location = this.location;
// 验证仓库/货架/货位 - 确保三个值都必须存在
if (!warehouse || !shelf || !location) {
uni.showToast({
title: '请完整选择仓库、货架和货位',
icon: 'none',
duration: 2500
});
return;
}
// 保存当前的货区和品相数据
const currentStorage = this.selectedStorage;
const currentWarehouse = this.warehouse;
const currentShelf = this.shelf;
const currentLocation = this.location;
const currentSelectedSheId = this.selectedSheId;
const currentSelectedFreId = this.selectedFreId;
// 保存当前的品相选择
let currentCondition = null;
if (this.$refs.conditionSelect) {
currentCondition = this.$refs.conditionSelect.getSelectedCondition();
}
// 清空表单数据
this.bookInfo = {
bookName: '',
author: '',
publisher: '',
format: '',
printTime: '',
isbn: '',
price: '',
wordage: '',
unifyIsbn: ''
};
// 清空图片列表和已上传图片
this.fileList1 = [];
this.uploadedImages = [];
this.hasShownUploadMessage = false;
// 重置在售商品列表
this.onSaleProducts = [];
this.displayOnSaleProducts = [];
// 重置下拉选项
this.authorOptions = [];
this.publisherOptions = [];
this.authorDropdownVisible = false;
this.publisherDropdownVisible = false;
this.formatDropdownVisible = false;
// 重置分类选择
this.categoryIndexes = [];
this.categoryPathText = '';
this.selectedCategoryId = '';
this.categoryLevels = [];
this.initCategoryPicker(); // 重新初始化选择器
// 恢复货区数据
this.selectedStorage = currentStorage;
this.warehouse = currentWarehouse;
this.shelf = currentShelf;
this.location = currentLocation;
this.selectedSheId = currentSelectedSheId;
this.selectedFreId = currentSelectedFreId;
// 恢复品相选择
if (this.$refs.conditionSelect && currentCondition) {
this.$refs.conditionSelect.setSelection(currentCondition.name);
}
// 显示bcode-camera组件
console.log('=== 设置 showBcodeCamera = true ===');
this.showBcodeCamera = true;
// 隐藏提交按钮
this.showSubmitButton = false;
},
showPrintTimeKeyboard() {
this.printTimePopupVisible = true;
},
closePrintTimePopup() {
this.printTimePopupVisible = false;
},
selectDecade(decade) {
this.printTimeYear = decade;
},
inputPrintTimeDigit(digit) {
if (this.printTimeActiveInput === 'year') {
if (this.printTimeYear.length < 4) {
this.printTimeYear += digit;
}
} else if (this.printTimeActiveInput === 'month') {
if (this.printTimeMonth.length < 2) {
this.printTimeMonth += digit;
}
}
},
deletePrintTimeDigit() {
if (this.printTimeActiveInput === 'year') {
this.printTimeYear = this.printTimeYear.slice(0, -1);
} else if (this.printTimeActiveInput === 'month') {
this.printTimeMonth = this.printTimeMonth.slice(0, -1);
}
},
confirmPrintTime() {
if (this.printTimeYear && this.printTimeMonth) {
this.bookInfo.printTime = `${this.printTimeYear}${this.printTimeMonth}`;
this.closePrintTimePopup();
} else {
uni.showToast({
title: '请输入完整的出版时间',
icon: 'none',
duration: 2500
});
}
},
handleUploadStatusChange(isUploading) {
console.log('文件上传状态变化:', isUploading ? '上传中' : '未上传');
this.isUploading = isUploading;
},
handleCopyrightCompare(data) {
console.log('版权比价:', data);
},
initCategoryPicker() {
this.categoryColumns = [];
this.categoryLevels = [];
this.categoryIndexes = [];
const level1Categories = (this.categoryList || []).filter(item => item.level === 1);
if (level1Categories.length === 0) {
this.categoryColumns = Array(this.maxCategoryLevel).fill([{
name: '暂无数据',
id: ''
}]);
this.categoryIndexes = Array(this.maxCategoryLevel).fill(0);
this.categoryPathText = '';
this.selectedCategoryId = '';
return;
}
this.categoryColumns[0] = level1Categories;
this.categoryIndexes[0] = 0;
let currentParent = level1Categories[0];
let currentLevel = 1;
this.categoryLevels[0] = currentParent;
while (currentLevel < this.maxCategoryLevel) {
const children = currentParent.children || [];
if (children.length === 0) {
break;
}
this.categoryColumns[currentLevel] = children;
this.categoryIndexes[currentLevel] = 0;
this.categoryLevels[currentLevel] = children[0];
currentParent = children[0];
currentLevel++;
}
while (this.categoryColumns.length < this.maxCategoryLevel) {
this.categoryColumns.push([{
name: '暂无数据',
id: ''
}]);
this.categoryIndexes.push(0);
this.categoryLevels.push({
name: '暂无数据',
id: ''
});
}
this.updateCategoryPathText();
this.updateSelectedCategoryId();
},
onCategoryColumnChange(e) {
const {
column,
value
} = e.detail;
this.categoryIndexes[column] = value;
this.categoryLevels[column] = this.categoryColumns[column][value];
if (column < this.maxCategoryLevel - 1) {
this.updateSubsequentColumns(column + 1);
}
this.updateCategoryPathText();
this.updateSelectedCategoryId();
},
updateSubsequentColumns(startColumn) {
const parentCategory = this.categoryLevels[startColumn - 1];
if (!parentCategory || !parentCategory.children || parentCategory.children.length === 0) {
for (let i = startColumn; i < this.maxCategoryLevel; i++) {
this.categoryColumns[i] = [{
name: '暂无数据',
id: ''
}];
this.categoryIndexes[i] = 0;
this.categoryLevels[i] = {
name: '暂无数据',
id: ''
};
}
return;
}
this.categoryColumns[startColumn] = parentCategory.children;
this.categoryIndexes[startColumn] = 0;
this.categoryLevels[startColumn] = parentCategory.children[0];
if (startColumn < this.maxCategoryLevel - 1) {
this.updateSubsequentColumns(startColumn + 1);
}
},
onCategoryChange(e) {
const values = e.detail.value;
this.categoryIndexes = [...values];
for (let i = 0; i < values.length; i++) {
if (this.categoryColumns[i] && this.categoryColumns[i][values[i]]) {
this.categoryLevels[i] = this.categoryColumns[i][values[i]];
}
}
this.updateCategoryPathText();
this.updateSelectedCategoryId();
},
updateCategoryPathText() {
const validLevels = this.categoryLevels.filter(level => level && level.name && level.name !== '暂无数据');
this.categoryPathText = validLevels.map(level => level.name).join(' / ');
},
updateSelectedCategoryId() {
const validLevels = this.categoryLevels.filter(level => level && level.id && level.id !== '');
if (validLevels.length === 0) {
this.selectedCategoryId = '';
return;
}
this.selectedCategoryId = validLevels[validLevels.length - 1].id;
},
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 [];
}
},
// 处理bcode-camera组件拍照结果的方法
async handleBcodeCameraResult(data) {
console.log('handleBcodeCameraResult被调用data:', data);
// 获取拍照结果
const tempFilePath = data.url;
// 如果没有拍照结果,按取消处理
if (!tempFilePath) {
this.handleBcodeCameraCancel();
return;
}
try {
// 保存当前的货区和品相数据
const currentStorage = this.selectedStorage;
const currentWarehouse = this.warehouse;
const currentShelf = this.shelf;
const currentLocation = this.location;
const currentSelectedSheId = this.selectedSheId;
const currentSelectedFreId = this.selectedFreId;
// 保存当前的品相选择
let currentCondition = null;
if (this.$refs.conditionSelect) {
currentCondition = this.$refs.conditionSelect.getSelectedCondition();
console.log('保存当前品相:', currentCondition);
}
// 显示加载中
uni.showLoading({
title: '识别中...',
mask: true
});
// OCR识别重试逻辑
const MAX_RETRIES = 3;
const RETRY_DELAY = 7000;
let retryCount = 0;
const performOCR = async () => {
try {
const ocrResult = await new Promise((resolve, reject) => {
uni.uploadFile({
url: 'https://book.xcx.ocr.buzhiyushu.cn/ocr',
filePath: tempFilePath,
name: 'file',
success: (res) => {
console.log("OCR响应:", res);
if (res.statusCode === 200) {
resolve(res);
} else {
reject(new Error('OCR服务器响应错误'));
}
},
fail: (err) => reject(new Error('OCR请求失败'))
});
});
const ocrData = JSON.parse(ocrResult.data);
if (!ocrData || !ocrData.texts) {
throw new Error('OCR识别结果无效');
}
return ocrData;
} catch (error) {
if (retryCount < MAX_RETRIES) {
retryCount++;
console.log(`OCR识别失败${retryCount}次重试,等待${RETRY_DELAY/1000}秒...`);
await new Promise(resolve => setTimeout(resolve, RETRY_DELAY));
return await performOCR();
}
throw error;
}
};
// 开始OCR识别
const ocrData = await performOCR();
console.log("OCR结果:", ocrData);
// 隐藏加载中
uni.hideLoading();
// 处理OCR结果
if (ocrData.texts) {
// 保存当前的bookInfo只更新识别到的字段
const currentBookInfo = {
...this.bookInfo
};
// 处理开本数据,如果不在预设列表中,则设置为默认值"32"
let formatValue = ocrData.texts.开本 || currentBookInfo.format || '32';
if (formatValue && !this.formatOptions.includes(formatValue)) {
formatValue = "32";
}
// 更新识别到的字段,保留未识别到的原有值
this.bookInfo = {
bookName: ocrData.texts.书名 || currentBookInfo.bookName || '',
author: ocrData.texts.作者 || currentBookInfo.author || '',
publisher: ocrData.texts.出版社 || currentBookInfo.publisher || '',
unifyIsbn: ocrData.texts.书号 || ocrData.texts.ISBN || currentBookInfo.unifyIsbn || '',
printTime: ocrData.texts.出版时间 || currentBookInfo.printTime || '',
price: ocrData.texts.定价 ? ocrData.texts.定价.replace('元', '') : currentBookInfo.price || '',
format: formatValue,
wordage: currentBookInfo.wordage || '',
};
console.log("更新后的bookInfo:", this.bookInfo);
// 检查isbn
const isbn = this.bookInfo.isbn;
if (!isbn || !/^\d{13}$/.test(isbn)) {
try {
const isbnRes = await new Promise((resolve, reject) => {
uni.request({
url: 'https://api.buzhiyushu.cn/zhishu/statistic/isbn',
method: 'GET',
success: (res) => {
resolve(res);
},
fail: (err) => {
reject(err);
}
});
});
this.bookInfo.isbn = isbnRes.data;
} catch (error) {
console.error('获取随机ISBN失败:', error);
}
}
// 将拍摄的照片添加到fileList1中
const newFile = {
url: tempFilePath,
status: "local",
message: "本地识图照片",
name: `识图-${Date.now()}.jpg`,
hidden: true,
num: "999",
isOCR: true
};
// 移除之前的识图上传图片(如果存在)
this.fileList1 = this.fileList1.filter(file => !file.name || !file.name.startsWith('识图-'));
// 添加新的识图上传图片
this.fileList1.push(newFile);
console.log('识图图片已添加到fileList1:', this.fileList1);
// 显示识别成功提示
uni.showToast({
title: '识别成功',
icon: 'success',
duration: 1500
});
// 隐藏相机组件
this.showBcodeCamera = false;
// 恢复显示提交按钮
this.showSubmitButton = true;
this.$emit('camera-status-change', false);
// 获取在售商品信息
if (this.bookInfo.bookName) {
await this.fetchOnSaleProducts(this.bookInfo.bookName);
}
// 使用 setTimeout 确保在 DOM 更新后恢复数据
setTimeout(() => {
// 恢复货区数据
this.selectedStorage = currentStorage;
this.warehouse = currentWarehouse;
this.shelf = currentShelf;
this.location = currentLocation;
this.selectedSheId = currentSelectedSheId;
this.selectedFreId = currentSelectedFreId;
// 通过 emit 事件更新 WarehouseSelector 组件
if (this.$refs.warehouseSelector) {
this.$refs.warehouseSelector.$emit('storage-selected', {
storage: currentStorage,
warehouse: currentWarehouse,
shelf: currentShelf,
location: currentLocation,
shelfId: currentSelectedSheId,
locationId: currentSelectedFreId
});
}
// 恢复品相选择
if (this.$refs.conditionSelect && currentCondition) {
this.$refs.conditionSelect.setSelection(currentCondition.name);
}
console.log('已恢复货区数据:', this.selectedStorage, this.warehouse, this.shelf, this.location);
// 强制更新整个表单
this.$forceUpdate();
}, 300);
}
} catch (error) {
console.error('OCR识别失败:', error);
uni.hideLoading();
uni.showToast({
title: '识别失败,请重试',
icon: 'none',
duration: 2500
});
// 隐藏相机组件
this.showBcodeCamera = false;
// 恢复显示提交按钮
this.showSubmitButton = true;
this.$emit('camera-status-change', false);
}
},
// 取消bcode-camera
handleBcodeCameraCancel() {
// 保存当前的货区和品相数据
const currentStorage = this.selectedStorage;
const currentWarehouse = this.warehouse;
const currentShelf = this.shelf;
const currentLocation = this.location;
const currentSelectedSheId = this.selectedSheId;
const currentSelectedFreId = this.selectedFreId;
// 保存当前的品相选择
let currentCondition = null;
if (this.$refs.conditionSelect) {
currentCondition = this.$refs.conditionSelect.getSelectedCondition();
console.log('取消时保存当前品相:', currentCondition);
}
// 隐藏相机组件
this.showBcodeCamera = false;
// 恢复显示提交按钮
this.showSubmitButton = true;
this.$emit('camera-status-change', false);
// 使用 setTimeout 确保在 DOM 更新后恢复数据
setTimeout(() => {
// 恢复货区数据
this.selectedStorage = currentStorage;
this.warehouse = currentWarehouse;
this.shelf = currentShelf;
this.location = currentLocation;
this.selectedSheId = currentSelectedSheId;
this.selectedFreId = currentSelectedFreId;
// 通过 emit 事件更新 WarehouseSelector 组件
if (this.$refs.warehouseSelector) {
this.$refs.warehouseSelector.$emit('storage-selected', {
storage: currentStorage,
warehouse: currentWarehouse,
shelf: currentShelf,
location: currentLocation,
shelfId: currentSelectedSheId,
locationId: currentSelectedFreId
});
}
// 恢复品相选择
if (this.$refs.conditionSelect && currentCondition) {
this.$refs.conditionSelect.setSelection(currentCondition.name);
}
console.log('取消时已恢复货区数据:', this.selectedStorage, this.warehouse, this.shelf, this.location);
// 强制更新整个表单
this.$forceUpdate();
}, 300);
},
async updateAuthorAndPublisher() {
try {
const cookies = uni.getStorageSync('cookies');
if (!cookies || !this.bookInfo.bookName) {
return;
}
const result = await getAuthorAndPublisher(this.bookInfo.bookName, cookies);
this.authorOptions = result.authors || [];
this.publisherOptions = result.publishers || [];
// 如果OCR识别的作者在列表中保持选中
if (this.bookInfo.author && result.authors && result.authors.includes(this.bookInfo.author)) {
this.bookInfo.author = this.bookInfo.author;
}
} catch (error) {
console.error('获取作者和出版社信息失败:', error);
}
},
// 生成随机ISBN的备用方法
generateRandomIsbn() {
// 生成符合ISBN-13格式的随机号码
// 978是图书的EAN前缀
let isbn = "978";
// 添加9位随机数字
for (let i = 0; i < 9; i++) {
isbn += Math.floor(Math.random() * 10).toString();
}
// 计算校验位
let sum = 0;
for (let i = 0; i < 12; i++) {
sum += parseInt(isbn[i]) * (i % 2 === 0 ? 1 : 3);
}
const checkDigit = (10 - (sum % 10)) % 10;
// 添加校验位
isbn += checkDigit;
return isbn;
},
// 从API获取ISBN
async generateIsbn() {
try {
const response = await uni.request({
url: 'https://api.buzhiyushu.cn/zhishu/statistic/isbn',
method: 'GET'
});
return response.data;
} catch (error) {
console.error('获取随机ISBN失败:', error);
throw error;
}
},
// 重置表单数据(保留货区和品相)
resetFormData() {
// 保存当前的货区和品相数据
const currentStorage = this.selectedStorage;
const currentWarehouse = this.warehouse;
const currentShelf = this.shelf;
const currentLocation = this.location;
const currentSelectedSheId = this.selectedSheId;
const currentSelectedFreId = this.selectedFreId;
// 清空表单数据
this.bookInfo = {
bookName: '',
author: '',
publisher: '',
format: '',
printTime: '',
isbn: '',
price: '',
wordage: ''
};
this.imageUrl = '';
this.uploadedImages = [];
this.fileList1 = [];
this.value3 = 1;
this.errorMsg = '';
this.onSaleProducts = [];
this.displayOnSaleProducts = [];
// 恢复货区数据
this.selectedStorage = currentStorage;
this.warehouse = currentWarehouse;
this.shelf = currentShelf;
this.location = currentLocation;
this.selectedSheId = currentSelectedSheId;
this.selectedFreId = currentSelectedFreId;
if (this.$refs.onSaleProductsComponent) {
this.$refs.onSaleProductsComponent.setCompareType('isbn');
}
},
};
</script>
<style scoped>
.form-container {
padding-left: 10rpx;
background-color: #fff;
}
.info-item {
display: flex;
padding: 20rpx 0;
border-bottom: 1px solid #eee;
}
.info-item-row {
display: flex;
gap: 20rpx;
}
.half-item {
flex: 1;
display: flex;
align-items: center;
position: relative;
}
.format-item {
flex: 1;
}
.isbn-item {
flex: 1;
}
.label {
padding: 0rpx 15rpx;
text-align: center;
height: 60rpx;
line-height: 60rpx;
color: #000;
font-size: 28rpx;
background-color: #ccc;
border-radius: 8rpx;
margin-right: 20rpx;
flex-shrink: 0;
}
.input-field {
flex: 1;
height: 60rpx;
line-height: 60rpx;
font-size: 28rpx;
padding: 0 20rpx;
background-color: #f5f5f5;
border-radius: 8rpx;
}
.time-input-view {
cursor: pointer;
}
.upload-btn {
margin-left: 20rpx;
padding: 0 20rpx;
height: 60rpx;
line-height: 60rpx;
font-size: 24rpx;
background-color: #007AFF;
color: white;
border: none;
border-radius: 8rpx;
}
.scan-btn-disabled {
pointer-events: none;
background-color: #cccccc !important;
color: #999 !important;
}
.dropdown-btn {
position: absolute;
right: 20rpx;
padding: 0 10rpx;
height: 60rpx;
line-height: 60rpx;
background-color: #f5f5f5;
border: none;
border-radius: 8rpx;
font-size: 20rpx;
}
.dropdown-list {
position: absolute;
top: 70rpx;
left: 0;
right: 0;
max-height: 300rpx;
background-color: #fff;
border: 1px solid #eee;
border-radius: 8rpx;
overflow-y: auto;
z-index: 100;
}
.dropdown-item {
padding: 20rpx;
font-size: 28rpx;
color: #333;
}
.dropdown-item:active {
background-color: #f5f5f5;
}
.dropdown-divider {
height: 1px;
background-color: #eee;
}
.category-container {
flex-direction: column;
}
.picker-single {
flex: 1;
height: 60rpx;
line-height: 60rpx;
padding: 0 20rpx;
background-color: #f5f5f5;
border-radius: 8rpx;
font-size: 28rpx;
color: #333;
display: flex;
align-items: center;
}
.blue-block {
width: 8rpx;
height: 32rpx;
background-color: #007AFF;
margin-right: 16rpx;
border-radius: 4rpx;
flex-shrink: 0;
align-self: center;
}
.general-label {
font-size: 28rpx;
color: #333;
font-weight: bold;
line-height: 32rpx;
display: flex;
align-items: center;
}
.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;
}
.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;
}
.print-time-popup {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.print-time-container {
width: 600rpx;
background-color: #fff;
border-radius: 16rpx;
overflow: hidden;
}
.print-time-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1px solid #eee;
}
.print-time-header text:first-child {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.close-btn {
font-size: 48rpx;
color: #999;
}
.print-time-tabs {
display: flex;
border-bottom: 1px solid #eee;
}
.tab-item {
flex: 1;
text-align: center;
padding: 20rpx 0;
font-size: 28rpx;
color: #666;
position: relative;
}
.tab-item.active {
color: #007AFF;
}
.tab-line {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 4rpx;
background-color: #007AFF;
}
.print-time-content {
padding: 40rpx;
}
.year-selection {
padding: 40rpx;
}
.year-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20rpx;
}
.decade-item {
padding: 20rpx;
text-align: center;
background-color: #f5f5f5;
border-radius: 8rpx;
font-size: 28rpx;
color: #333;
}
.decade-item:active {
background-color: #e6e6e6;
}
.time-input-fields {
display: flex;
gap: 20rpx;
}
.input-group {
flex: 1;
}
.time-input {
width: 100%;
height: 80rpx;
line-height: 80rpx;
padding: 0 20rpx;
background-color: #f5f5f5;
border-radius: 8rpx;
font-size: 32rpx;
text-align: center;
border: none;
}
.numeric-keyboard {
background-color: #f5f5f5;
padding: 20rpx;
}
.keyboard-row {
display: flex;
gap: 20rpx;
margin-bottom: 20rpx;
}
.key-item {
flex: 1;
height: 100rpx;
line-height: 100rpx;
text-align: center;
background-color: #fff;
border-radius: 8rpx;
font-size: 36rpx;
color: #333;
font-weight: bold;
}
.key-item:active {
background-color: #e6e6e6;
}
.zero-key {
flex: 2;
}
.keyboard-btn {
background-color: #007AFF;
color: white;
}
.delete-key {
background-color: #ff4d4f;
color: white;
}
</style>