daShangDao_miniProgram/pkgUpload/isbn-upload/index.vue
2026-06-15 16:37:57 +08:00

3412 lines
94 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="page-container" @click="closeDropdown">
<!-- 顶部Tab切换 -->
<view class="upload-tab-header">
<view
class="upload-tab-item"
:class="{ 'active': true }"
@click="stayOnIsbn">
<text>ISBN上传</text>
</view>
<view
class="upload-tab-item"
@click="switchToPhoto">
<text>无ISBN上传</text>
</view>
</view>
<view v-if="currentTab === 'isbn'" class="form-container">
<view class="view-container">
<warehouse-selector v-if="selectedWarehouse" :initialStorage="selectedStorage" :initialWarehouse="selectedWarehouse"
@label-click="navigateBack" @storage-selected="handleStorageSelected" ref="warehouseSelector"
style="flex: 0.47"></warehouse-selector>
<view class="view-item">
<!-- ISBN标签 -->
<view class="label">ISBN</view>
<view class="input-group">
<!-- 输入容器(弹性容器) -->
<view class="input-container">
<!-- 输入框 -->
<input class="scan-input" v-model="scanResult" placeholder="请点击扫码"
:disabled="fileList1.length > 0" />
<!-- 扫码按钮 -->
<view class="scan-btn" :class="{ 'scan-btn-disabled': isScanning || fileList1.length > 0 }"
@click="startScanning"
:style="(isScanning || fileList1.length > 0) ? 'opacity: 0.5;' : ''">
<text>{{ isScanning ? '扫描中...' : '扫码' }}</text>
</view>
<!-- 搜索按钮 -->
<view class="scan-btn" @click="searchByIsbn"
:class="{ 'scan-btn-disabled': fileList1.length > 0 }"
:style="fileList1.length > 0 ? 'opacity: 0.5;' : ''">
<text>搜索</text>
</view>
</view>
</view>
</view>
</view>
<!-- 扫码 -->
<view class="view-container">
<view class="view-item">
<view class="label">书名</view><input class="input" v-model="formData.bookName" placeholder="请输入书名"
:disabled="fileList1.length > 0" />
</view>
</view>
<!-- 图书分类多级联动 -->
<!-- <view class="view-container category-container">
<view class="view-item">
<view class="label">图书分类</view>
<picker mode="multiSelector" :range="categoryColumns" range-key="name"
@columnchange="onCategoryColumnChange" @change="onCategoryChange" :value="categoryIndexes">
<view class="picker-single">
{{ categoryPathText || '请选择分类' }}
</view>
</picker>
</view>
</view> -->
<!-- 使用封装后的品相选择组件不需要传入v-model -->
<book-condition-select ref="conditionSelect" @change="onConditionChange"></book-condition-select>
<!-- 使用封装后的价格库存控制组件 -->
<price-stock-control :price.sync="value4" :stock.sync="value3" @priceChange="onPriceChange"
@stockChange="onStockChange" ref="priceStockControl" />
<!-- </view> -->
<camera-upload v-model="fileList1" :maxCount="9" :isbn="scanResult" :bookName="formData.bookName"
@input="handleFileChange" @camera-status-change="handleCameraStatusChange"
@upload-status-change="handleUploadStatusChange"></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="scanResult" :bookName="formData.bookName" @compare-type-change="handleCompareTypeChange"
@filters-applied="handleFiltersApplied" @filters-reset="handleFiltersReset"
@products-updated="handleProductsUpdated" ref="onSaleProductsComponent" />
<view class="view-container" style="margin-top: 40rpx; margin-bottom: 200rpx;">
<view class="view-item updateBook" @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 v-if="scanResult" class="result-container">
<!-- <text>扫码结果: {{ scanResult }}</text> -->
<view v-if="isSaving" class="loading">
<text>正在保存数据...</text>
</view>
<view v-if="saveSuccess" class="success-message">
<text>数据保存成功</text>
</view>
<view v-if="saveError" class="error-message">
<text>数据保存失败: {{ saveError }}</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>
</view>
</template>
<script>
import {
mapState
} from 'vuex'
// Vuex 模块拆分后使用命名空间访问
import CryptoJS from 'crypto-js';
import CameraUpload from '@/components/CameraUpload.vue';
import TabBar from '@/components/TabBar.vue';
// 导入bcode-camera组件
import bcodeCamera from '@/uni_modules/bcode-camera/components/bcode-camera/bcode-camera.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';
// 导入uni-app API
import {
uploadFile
} from '@/utils/upload.js';
// 导入会员书籍数量检查工具
import {
checkMemberBooksCount
} from '@/components/MemberBookCheck.js';
export default {
name: 'IsbnUpload',
// 添加页面配置
options: {
enablePullDownRefresh: true, // 启用下拉刷新
backgroundTextStyle: 'dark'
},
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
},
},
computed: {
...mapState('price', ['priceMode', 'priceType', 'averageRange', 'freight', 'minValue']),
...mapState('warehouse', ['selectedPosition'])
},
components: {
"tab-bar": TabBar,
'bcode-camera': bcodeCamera,
"price-stock-control": PriceStockControl,
"camera-upload": CameraUpload,
"book-condition-select": BookConditionSelect,
"on-sale-products": BookProductList,
"warehouse-selector": WarehouseSelector,
},
// 将selectBookImage挂载到组件实例上
created() {
this.$selectBookImage = selectBookImage;
},
data() {
return {
selectedWarehouse: null, // 添加 selectedWarehouse
lowestBookPrice: 0,
lowestTotalPrice: 0,
currentTab: 'isbn', // 默认显示ISBN上传
retype: false, // 重输选项的状态
scanResult: null,
showSubmitButton: true, // 控制提交按钮显示状态
isSaving: false,
saveSuccess: false,
saveError: null,
isScanning: false, // 扫码状态变量
isSubmitting: false, // 防止重复提交的状态变量
isUploading: false, // 新增:用于跟踪图片是否正在上传
show: false,
popupShow: false,
isbn: '',
value4: 1.00,
value3: 1,
fileList1: [],
fileList: [],
uploadedImages: [], // 存储上传成功的图片信息,用于提交表单时一并传递
selectedStorage: '',
warehouse: '',
shelf: '',
location: '',
bookPicPath: null, // 新增变量用于存储图片路径
searchResults: [], // 存储查询到的多条数据
showSearchDropdown: false, // 控制下拉框显示
fixPrice: 1,
cameraRatio: '1:1', // 默认相机比例为1:1
showCameraRatioPopup: false, // 控制相机比例选择弹窗显示
compareType: 'isbn', // 默认为ISBN比价
titleCompareResults: [], // 存储书名比价结果示
showCamera: false, // 控制bcode-camera组件的显示
searchBoxRef: null, // 用于存储搜索框的引用
onSaleProducts: [], // 存储所有在售商品信息用于筛选
displayOnSaleProducts: [], // 存储按总价排序后的前十条在售商品信息用于展示
soldProducts: [], // 存储已售商品信息
// 筛选相关变量
publisherOptions: [], // 出版社选项
formattedData: [],
selectedCondition: '',
selectedConditionName: '',
authorOptions: [], // 作者选项
press: '',
author: '', // 书籍作者
pubDateText: '', // 出版时间
filteredOnSaleProducts: [], // 筛选后的在售商品
filteredSoldProducts: [], // 筛选后的已售商品
isFiltered: false, // 是否已应用筛选
publisherAuthorMap: new Map(), // 出版社-作者关联映射
authorPublisherMap: new Map(), // 作者-出版社关联映射
title: 'uni-fab',
directionStr: '水平',
horizontal: 'right',
vertical: 'bottom',
direction: 'horizontal',
pattern: {
color: '#7A7E83',
backgroundColor: '#fff',
selectedColor: '#007AFF',
buttonColor: '#007AFF',
iconColor: '#fff'
},
is_color_type: false,
selectedStorage: '',
shelves: [], // 货架列表
locations: [], // 货位列表
LocalWarehouse: this.selectedWarehouse,
selectedSheId: null,
selectedFreId: null,
formData: {
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, // 添加标记,避免重复显示提示
categoryList: [], // 原始分类数据
categoryOptions2: [], // 二级分类(兼容旧代码)
categoryOptions3: [], // 三级分类(兼容旧代码)
categoryLevel1: null, // 选中的一级(兼容旧代码)
categoryLevel2: null, // 选中的二级(兼容旧代码)
categoryLevel3: null, // 选中的三级(兼容旧代码)
selectedCategoryId: '', // 选中的分类id最终叶子节点的id
categoryIndexes: [], // 用于存储分类选择的索引(可变长度数组)
maxCategoryLevel: 6, // 支持的最大分类级别数
categoryPathText: '', // 用于显示分类路径
categoryColumns: [], // 多级分类选择器的所有列数据
categoryLevels: [], // 存储每个级别选中的分类对象
kfzBookPic: '', // 存储孔夫子图书官图
};
},
watch: {
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();
}
}
},
async onLoad() {
console.log('=== onLoad 方法被调用 ===');
const phoneNumber = uni.getStorageSync('phoneNumber');
const warehouse = uni.getStorageSync("selectedWarehouse");
console.log('选择仓库11111:', warehouse);
// 先设置 selectedWarehouse触发 warehouse-selector 组件渲染
if (warehouse) {
this.selectedWarehouse = warehouse;
this.columns[0] = [warehouse.name]; // 假设仓库对象有name字段
}
// 使用 setTimeout 等待 warehouse-selector 组件渲染完成后再加载货区选择状态
setTimeout(() => {
this.loadStorageSelection();
}, 100);
await this.fetchCategoryData();
console.log("分类数据获取成功:", this.categoryList)
},
onShow() {
console.log('=== onShow 方法被调用 ===');
// 检查本地存储中是否有更新的仓库信息
const warehouse = uni.getStorageSync("selectedWarehouse");
console.log("warehouse", warehouse)
// 先设置 selectedWarehouse再加载货区选择状态
if (warehouse) {
console.log('从存储获取仓库信息:', warehouse);
// 设置仓库对象以便传递给组件
this.selectedWarehouse = warehouse;
}
// 使用 setTimeout 等待组件渲染后再加载货区选择状态
setTimeout(() => {
this.loadStorageSelection();
}, 100);
// 新增:每次页面显示都拉取分类
console.log('onShow: 开始调用fetchCategoryData');
this.fetchCategoryData().then(() => {
console.log('onShow: fetchCategoryData执行完成');
}).catch(error => {
console.error('onShow: fetchCategoryData执行失败:', error);
});
},
// 添加Vue的mounted生命周期钩子确保组件切换时能正确加载状态
mounted() {
// 不在这里调用 loadStorageSelection因为 v-if 导致组件渲染延迟
// 使用 setTimeout 等待组件渲染完成后再调用
setTimeout(() => {
this.loadStorageSelection();
}, 100);
},
// 添加onReady生命周期钩子uni-app中相当于mounted
onReady() {
// console.log('=== onReady 方法被调用 ===');
// 在uni-app中我们可以使用页面级别的点击事件
// 这里不需要添加全局事件监听器,我们将在模板中使用@click事件
// 手动触发分类数据获取
// console.log('onReady: 手动触发fetchCategoryData');
this.fetchCategoryData().then(() => {
// console.log('onReady: fetchCategoryData执行完成');
}).catch(error => {
console.error('onReady: fetchCategoryData执行失败:', error);
});
},
// 添加onUnload生命周期钩子uni-app中相当于beforeDestroy
onUnload() {
// 在uni-app中我们不需要手动移除事件监听器
},
onBackPress() {
if (this.$refs.fab.isShow) {
this.$refs.fab.close()
return true
}
return false
},
//下拉刷新
onPullDownRefresh() {
console.log('触发下拉刷新');
try {
this.resetPageData();
uni.showToast({
title: '刷新成功',
icon: 'success',
duration: 1500
});
} catch (error) {
console.error('刷新失败:', error);
uni.showToast({
title: '刷新失败',
icon: 'none',
duration: 1500
});
} finally {
// 停止下拉刷新动画
setTimeout(() => {
uni.stopPullDownRefresh();
}, 500);
}
},
methods: {
// 停留在ISBN上传页面
stayOnIsbn() {
// 已在当前页面,不做任何操作
},
// 切换到无ISBN上传页面
switchToPhoto() {
uni.redirectTo({
url: '/pkgUpload/photo-upload/index'
});
},
// 获取货架列表
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/shelves/shelves/freNamelist',
method: 'GET',
data: { sheId }
});
const [err, res] = Array.isArray(response) ? response : [null, response];
if (!res || !res.data || !res.data.rows) {
console.error('货位响应数据格式不正确');
return [];
}
return res.data.rows;
} catch (error) {
console.error('获取货位失败:', error);
return [];
}
},
// 从本地存储加载货区选择状态
loadStorageSelection() {
try {
// 只有在选择了仓库的情况下才加载货区状态
if (!this.selectedWarehouse || !this.selectedWarehouse.id) {
console.log('ISBN页面未选择仓库不加载货区状态');
return;
}
// 根据仓库ID加载对应的货区状态
const storageKey = `selectedStorageData_${this.selectedWarehouse.id}`;
const storageData = uni.getStorageSync(storageKey);
if (storageData) {
console.log(`ISBN页面加载仓库${this.selectedWarehouse.id}的货区选择状态:`, 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;
// 使用$nextTick确保组件已经渲染完成
this.$nextTick(() => {
// 如果有货区选择器组件的引用,也更新它的状态
if (this.$refs.warehouseSelector) {
// 转换数据格式以匹配updateSelectedStorage方法的期望格式
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);
console.log('已更新WarehouserSelector组件状态:', formattedData);
} else {
console.warn('WarehouserSelector组件引用不存在');
}
});
} else {
console.log(`ISBN页面仓库${this.selectedWarehouse.id}没有保存的货区状态`);
}
} catch (error) {
console.error('ISBN页面加载货区选择状态失败:', error);
}
},
// 添加重置数据的方法
resetPageData() {
console.log('子组件resetPageData被调用');
// 保存当前的货区选择
const currentWarehouse = this.warehouse;
const currentShelf = this.shelf;
const currentLocation = this.location;
const currentSelectedStorage = this.selectedStorage;
// 清空所有数据
this.scanResult = ''; // 清空ISBN
this.kfzBookPic = ''; // 清空孔夫子图书官图
this.formData = {
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([]);
this.$refs.onSaleProductsComponent.setCompareType('isbn');
}
// 重置品相选择
if (this.$refs.conditionSelect) {
// 尝试使用resetSelection方法
if (typeof this.$refs.conditionSelect.resetSelection === 'function') {
this.$refs.conditionSelect.resetSelection();
}
}
// 强制更新视图
this.$forceUpdate();
console.log('数据重置完成,当前状态:', {
scanResult: this.scanResult,
bookName: this.formData.bookName,
fileList1Length: this.fileList1.length
});
return Promise.resolve('重置完成');
},
// 获取图书分类数据
async fetchCategoryData() {
try {
// console.log('开始获取分类数据...');
// 获取cookies作为token
const cookies = uni.getStorageSync('cookies');
// console.log('获取到的cookies:', cookies);
if (!cookies) {
console.error('获取分类失败: 未找到cookies');
uni.showToast({
title: '请先登录孔网账号再进行操作',
icon: 'none',
duration: 3000
});
return;
}
// console.log('使用token获取分类数据...');
// uni.showLoading({
// title: '加载分类...'
// });
// 调用后端接口获取分类数据
// console.log('发起API请求到:', 'https://api.buzhiyushu.cn/api/kongfz/getCategory');
const res = await uni.request({
url: 'https://api.buzhiyushu.cn/api/kongfz/getCategory',
method: 'GET',
data: {
token: cookies
},
header: {
'Content-Type': 'application/json'
}
});
uni.hideLoading();
// console.log('分类数据API响应:', res);
// console.log('响应状态码:', res.statusCode);
// 处理返回的数据,兼容不同格式
const responseData = Array.isArray(res) ? res[1].data : res.data;
// console.log('处理后的responseData:', responseData);
if (responseData && responseData.successResponse) {
// 保存完整的分类数据
this.categoryList = responseData.successResponse;
// console.log('分类数据获取成功,开始初始化选择器');
this.initCategoryPicker();
// console.log('分类数据获取成功:', this.categoryList);
} else {
console.error('获取分类数据失败, 响应不符合预期:', responseData);
// console.log('responseData类型:', typeof responseData);
// console.log('responseData内容:', JSON.stringify(responseData));
uni.showToast({
title: '获取分类数据失败',
icon: 'none',
duration: 2000
});
}
} catch (error) {
uni.hideLoading();
// console.error('获取分类数据异常:', error);
console.error('错误详情:', error.message);
uni.showToast({
title: '获取分类数据失败',
icon: 'none',
duration: 2000
});
}
},
handleCameraStatusChange(isCameraOpen) {
// 当相机打开时隐藏提交按钮,关闭时显示
this.showSubmitButton = !isCameraOpen;
},
// 切换比价按钮
async handleCompareTypeChange(payload) {
// console.log("payload", payload)
this.compareType = payload.type
if (payload.type === 'isbn') {
this.scanResult = payload.value;
} else {
this.formData.bookName = payload.value;
}
// console.log(`比较类型已切换为: ${payload.type}`);
// console.log(`当前搜索值: ${payload.value}`);
const keyword = payload.type === 'isbn' ? this.scanResult : this.formData.bookName;
await this.fetchOnSaleProducts(keyword);
this.isLoading = false;
},
handleStorageSelected(data) {
// console.log('选择的货区数据:', 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;
// 将ID存储到本地
uni.setStorageSync('warehouseId', this.selectedWarehouse.id); // 仓库ID
uni.setStorageSync('shelfId', data.shelfId); // 货架ID
uni.setStorageSync('locationId', data.locationId); // 货位ID
},
// 处理筛选结果
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;
console.log("sortType", sortType)
// 获取最新的cookies
let cookies = uni.getStorageSync('UserInfoCookies');
// 如果cookies不存在尝试从cookies字段获取
if (!cookies) {
cookies = uni.getStorageSync('cookies');
console.log('从cookies字段获取:', cookies);
}
// 如果仍然没有,显示提示
if (!cookies) {
uni.showToast({
title: '请先在设置页面登录孔网账号',
icon: 'none',
duration: 2500
});
return;
}
// 调用封装在selectBookImage.js中的方法
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);
}
// console.log('获取在售商品信息成功(已过滤屏蔽店铺)');
// 计算参考价格
this.calculateReferencePrice();
} catch (error) {
console.error('获取在售商品信息失败:', error);
uni.showToast({
title: '获取在售商品信息失败',
icon: 'none',
duration: 2500
});
}
},
onConditionChange(index, conditionName) {
// console.log('品相已选择:', index);
// console.log('选中的品相名称:', conditionName);
// 保存选中的品相名称,用于表单提交
this.selectedConditionName = conditionName;
},
handleTabChange(tab) {
if (tab === this.currentTab) return;
if (tab === 'title') {
// 跳转到仅书名上传页面
uni.navigateTo({
url: '/pkgUpload/title-upload/index'
});
}
},
handleFileChange(newFileList) {
this.fileList1 = newFileList;
console.log("fileList1111111", this.fileList1)
// 当有图片上传时,添加提示
if (this.fileList1.length > 0 && (!this.hasShownUploadMessage)) {
uni.showToast({
title: '已上传图片ISBN和书名不可修改',
icon: 'none',
duration: 2000
});
this.hasShownUploadMessage = true;
} else if (this.fileList1.length === 0) {
this.hasShownUploadMessage = false;
}
// 检查是否有文件正在上传
this.isUploading = newFileList.some(file => file.status === 'uploading');
console.log('图片上传状态:', this.isUploading ? '上传中' : '未上传');
},
// 获取上书记录
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);
console.log("1111", records)
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);
uni.showToast({
title: error.message || '获取上书记录失败',
icon: 'none',
duration: 2500
});
}
},
cancel() {
this.show = false;
},
// 添加open和close方法
open() {
// 打开弹出层时的处理逻辑
console.log('弹出层打开');
this.popupShow = true;
},
close() {
// 关闭弹出层时的处理逻辑
this.popupShow = false;
console.log('弹出层关闭');
},
// 处理字母选择确认事件
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; // 2小时的毫秒数
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;
}
// 设置提交状态为true
this.isSubmitting = true;
const warehouse = this.warehouse
// console.log("warehouse", warehouse)
const shelf = this.shelf
// console.log("shelf", shelf)
const location = this.location
// console.log("location", location)
const userId = uni.getStorageSync("userId")
// 根据当前选项卡进行表单验证
if (this.currentTab === 'isbn') {
// ISBN上传模式验证
// 验证ISBN
if (!this.scanResult) {
uni.showToast({
title: '请扫码获取ISBN',
icon: 'none',
duration: 2500
});
this.isSubmitting = false; // 重置提交状态
return;
}
// 验证书名
if (!this.formData.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;
}
} else {
// 仅书名上传模式验证
// 验证书名
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.selectedCategoryId) {
// uni.showToast({
// title: '请选择图书分类',
// icon: 'none',
// duration: 2500
// });
// this.isSubmitting = false; // 重置提交状态
// return;
// }
// 上传所有待上传的图片
if (this.fileList1.length > 0) {
// 在提交表单前检查是否有临时路径的图片
if (this.fileList1.length > 0) {
// 检查是否有上传失败或者临时路径的图片
const temporaryImages = [];
console.log("当前图片数据fileList1", this.fileList1)
this.fileList1.forEach((file, index) => {
// 检查图片状态是否为error或者路径是临时路径
if (file.url && (file.url.startsWith('file://') ||
file.url.startsWith('blob:') ||
file.url.startsWith('wxfile://') ||
file.url.indexOf('tmp') !== -1)) {
temporaryImages.push(index + 1); // 索引从0开始所以+1表示第几张
}
});
if (temporaryImages.length > 0) {
uni.showToast({
title: `${temporaryImages.join('、')}张图片上传失败,请重新拍照,若仍然失败请联系管理员!`,
icon: 'none',
duration: 4000
});
this.isSubmitting = false; // 重置提交状态
return;
}
}
try {
// 显示上传中提示
uni.showLoading({
title: '正在上传图片...'
});
// 设置上传状态为true
this.isUploading = true;
// 上传所有图片
for (let i = 0; i < this.fileList1.length; i++) {
const file = this.fileList1[i];
// 只上传状态为ready的图片
if (file.status === "ready") {
// 更新状态为上传中
this.fileList1.splice(i, 1, {
...file,
status: "uploading",
message: "上传中"
});
try {
// 上传图片
const result = await this.uploadFilePromise(file.url, i);
console.log("图片上传result", result)
// 更新状态为上传成功
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;
}
}
// 最终验证确保uploadedImages中没有临时路径
// console.log("uploadedImages",this.uploadedImages)
// console.log("fileList1",this.fileList1)
// const invalidImages = this.uploadedImages.filter(img => {
// return img.url && (
// img.url.startsWith('file://') ||
// img.url.startsWith('blob:') ||
// img.url.startsWith('wxfile://') ||
// img.url.indexOf('tmp') !== -1
// );
// });
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;
}
// 从marketTags中提取sellCount和buyCount
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;
// 收集ISBN上传数据
const formData = {
barcode: this.scanResult, // 正确绑定扫码结果
userId: userId,
name: this.formData.bookName, // 书名
recommendation: this.formData.recommendation, // 推荐语
conditionCode: selectedCondition.name,
price: this.value4 * 100, // 商品售价
inventory: this.value3 || 1, // 库存
files: this.fileList1, // 只使用已成功上传的图片信息
marketTags: this.marketTags, // 市场标签
sellCount: sellCount, // 在售数量
buyCount: buyCount, // 已售数量
author: this.author, // 书籍作者
fixPrice: this.fixPrice * 100,
selectedStorage: this.selectedStorage, // 仓库ID
depotName: this.warehouse, // 仓库名称(需与后端字段名一致)
shelvesName: this.shelf, // 货架名称
freightName: this.location, // 自由区名称
phoneNumber: uni.getStorageSync('phoneNumber'), // 从本地存储获取用户
passWord: uni.getStorageSync('password'), // 从本地存储获取用户
tenantId: uni.getStorageSync('tenantId'), // 从本地存储获取租户ID
userName: uni.getStorageSync('userName'), // 从本地存储获取手机号
categoryId: this.selectedCategoryId || '' // 添加分类ID
};
// 根据当前选项卡打印对应数据
console.log('提交的表单数据:', formData);
// 先检查是否重复书籍
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() :
''; // 添加空值检查
// 1. MD5 32位加密小写
const md5Hash = CryptoJS.MD5(bookName).toString(); // 输出 32 位小写十六进制字符串
// 2. 获取首字母并大写
const firstLetter = bookName ? md5Hash.charAt(0).toUpperCase() : '';
console.log('原始书名:', bookName);
console.log('MD5加密后32位小写:', md5Hash);
console.log('加密后字符串的首字母大写:', firstLetter);
const imagePath = res.data.data && res.data.data.image ? res.data.data.image :
'';
console.log("图片", imagePath)
// 拼接图片地址
const fullImageUrl =
`https://img.buzhiyushu.cn/zhishu1/${firstLetter}/${imagePath}`;
console.log("fullImageUrl", fullImageUrl)
// 根据count值动态设置下拉框的起始字母
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'
];
// 如果count为1从B开始count为2从C开始以此类推
const startIndex = count > 0 ? count - 1 : 0;
if (startIndex >= 0 && startIndex < allLetters.length) {
// 从对应位置截取字母数组
this.popupDialog.seriesOptions = allLetters.slice(startIndex);
// 默认选中第一个字母即对应count的字母
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 // 添加默认值防止count为null
this.popupDialog.subFormData = formData
} else {
// 不是重复书籍,直接提交
this.submitToServer(formData);
}
},
fail: (err) => {
console.error('检查重复书籍失败:', err);
uni.showToast({
title: '网络错误,请稍后重试',
icon: 'none',
duration: 2500
});
this.isSubmitting = false; // 重置提交状态
}
});
},
onPopupConfirm() {
// 直接使用选择的字母作为series参数
this.popupDialog.subFormData.series = this.popupDialog.selectedSeries;
console.log("字母", this.popupDialog.subFormData.series)
// 继续提交流程
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',
// url: 'http://192.168.101.209:8080/zhishu/shopGoods/submit',
// url: 'http://192.168.101.127:8080/zhishu/shopGoods/submit',
method: 'POST',
data: formData,
header: {
'Content-Type': 'application/json'
},
complete: () => {
// 无论成功或失败,都重置提交状态
this.isSubmitting = false;
},
success: (res) => {
console.log('请求成功1111:', res);
// 获取返回的id
const goosId = res.data.msg;
// console.log('返回的ID:', returnedId);
// 将id保存到本地存储
// uni.setStorageSync('lastSubmittedId', returnedId);
// 保存最后选择的位置信息
uni.setStorageSync('lastSelectedStorage', this.selectedStorage);
uni.setStorageSync('lastSelectedWarehouse', this.warehouse);
uni.setStorageSync('lastSelectedShelf', this.shelf);
uni.setStorageSync('lastSelectedLocation', this.location);
// 从第一个API响应中提取ID
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);
// 创建包含ID的新formData
const newFormData = {
...formData,
...idsToPass
};
console.log("newFormData", newFormData)
// 调用newadmin API
uni.request({
url: 'https://newadmin.buzhiyushu.cn/zhishu/shopGoods/submit',
// url: 'http://localhost:8089/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);
}
});
// 清空表单数据,但保留品相选择
if (this.currentTab === 'isbn') {
this.formData = {
bookName: '',
recommendation: '',
};
this.scanResult = '';
this.kfzBookPic = ''; // 清空孔夫子图书官图
} else {
this.formData2 = {
isbn: '',
bookName: '',
recommendation: '',
};
}
// 保持价格、库存和品相为用户选择的值
this.value4 = this.value4; // 保持价格
this.value3 = 1; // 重置库存为1
// 清空照片数据
this.fileList1 = []; // 清空文件列表
this.uploadedImages = []; // 清空上传图片数组
// this.marketTags = []; // 清空市场标签
// 不重置品相选择保留conditions数组中的checked状态
// 显示提交成功提示
uni.showToast({
title: '提交成功',
icon: 'success',
duration: 2000
});
console.log('请求成功,表单已清空');
if (this.$refs.onSaleProductsComponent) {
this.$refs.onSaleProductsComponent.setCompareType('isbn');
}
// 如果当前是ISBN上传模式自动触发扫码功能
if (this.currentTab === 'isbn') {
// 延迟一小段时间后触发扫码,确保表单清空和提示显示完成
setTimeout(() => {
this.startScanning();
}, 800);
}
},
fail: (err) => {
console.error('请求失败:', err);
uni.showToast({
title: '网络错误,请稍后重试',
icon: 'none',
duration: 2500
});
}
});
},
// 新增:异步调用选品中心接口的方法
syncBookToCenter(formData) {
// 后台接口地址POST
const centerUrl = 'https://api.buzhiyushu.cn/zhishu/baseInfo/getXcxData';
// const centerUrl = 'http://localhost:8080/zhishu/baseInfo/getXcxData';
// 仅提取所需参数
const centerData = {
barcode: formData.barcode,
name: formData.name,
price: formData.price,
author: formData.author,
publisher: this.press,
publishTime: this.pubDateText,
sellCount: formData.sellCount,
buyCount: formData.buyCount,
files: formData.files || [],
kfzBookPic: this.kfzBookPic
};
console.log("选品中心参数", centerData)
// 异步执行(不影响主提交流程)
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); // 延迟300ms避免主请求未完全结束
},
// 图片上传到服务器
uploadFilePromise(url, index) {
return new Promise((resolve, reject) => {
// 获取当前选项卡下的书名和ISBN
const bookName = this.currentTab === 'isbn' ? this.formData.bookName : this.formData2.bookName;
let isbn = this.currentTab === 'isbn' ? this.scanResult : this.formData2.isbn;
// 检查 isbn 是否为空
if (!isbn || isbn.trim() === '') {
isbn = '';
for (let i = 0; i < 13; i++) {
isbn += Math.floor(Math.random() * 10);
}
}
// 获取存储的仓库相关ID
const warehouseId = uni.getStorageSync('warehouseId');
const shelfId = uni.getStorageSync('shelfId');
const locationId = uni.getStorageSync('locationId');
// 图片编号从1开始
const num = (index + 1).toString();
uni.uploadFile({
// url: "https://api.buzhiyushu.cn/zhishu/shopGoods/uploadImages",
url: "https://xcx.uploadfile.yushutx.com/uploadImages",
filePath: url,
name: "file",
success: (res) => {
console.log('图片上传成功:', res);
// 解析返回结果
const data = JSON.parse(res.data);
console.log("data", data)
const urlData = JSON.parse(data.data);
const imageUrl = urlData.url || url;
console.log("url", imageUrl)
// 将上传成功的图片信息存储到数组中
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);
}
});
});
},
valChange(e) {
console.log('当前值为: ' + e.value)
},
valChange1(e) {
console.log('当前值为: ' + e.value)
},
radioClick(index) {
this.conditions = this.conditions.map((item, i) => ({
...item,
checked: i === index,
}));
},
// 高亮显示有问题的图片
highlightProblemImages(invalidImages) {
// 根据invalidImages中的originalUrl找到fileList1中对应的图片并标记
invalidImages.forEach(invalidImg => {
const index = this.fileList1.findIndex(file => file.url === invalidImg.originalUrl);
if (index !== -1) {
// 标记为错误状态UI可以根据这个状态显示红色边框或错误图标
this.$set(this.fileList1[index], 'status', 'error');
this.$set(this.fileList1[index], 'errorMessage', '上传失败,请重新上传');
}
});
// 强制更新视图
this.$forceUpdate();
// 可选:滚动到第一个有问题的图片位置
this.$nextTick(() => {
const firstErrorIndex = this.fileList1.findIndex(file => file.status === 'error');
if (firstErrorIndex !== -1) {
// 这里可以添加滚动到错误图片的逻辑
console.log(`请检查第${firstErrorIndex + 1}张图片`);
}
});
},
// 数据填充方法
async populateForm(data) {
console.log("data2", data)
this.formData.bookName = data.bookName;
this.fixPrice = data.fixPrice;
this.formData.recommendation = "权威认证 立即购买";
this.value = data.price;
this.value1 = data.stock;
this.formData.isbn = data.isbn;
// 解析响应数据中的在售和已售数量
const sellCount = data.sellCount;
const buyCount = data.buyCount;
// const buyCount = parseInt(data.buyCount.replace('人买过', ''), 10);
// 只有当没有选中任何品相时才使用API返回的品相
// const hasSelectedCondition = this.conditions.some(item => item.checked);
// if (!hasSelectedCondition) {
// this.conditions = this.conditions.map(condition => ({
// ...condition,
// checked: condition.name === data.condition
// }));
// }
if (data.condition) {
// 使用组件方法设置品相
this.$refs.conditionSelect.setSelection(data.condition);
}
// 更新 marketTags 数组
this.marketTags = this.marketTags.map(item => {
if (item.label === '在售:') {
return {
...item,
value: sellCount
};
} else if (item.label === '已售:') {
return {
...item,
value: buyCount
};
}
return item;
});
// 获取图片路径
if (data.bookPic) {
const fileName = data.bookPic.split('.')[0];
const suffix = data.bookPic.split('.')[1];
// this.getBookPicPath(fileName, suffix);
}
},
// 切换比价类型
switchCompareType(type) {
this.compareType = type;
if (type === 'title') {
if (!this.formData.bookName) {
console.log("比价书名", this.formData.bookName)
uni.showToast({
title: '请先输入书名',
icon: 'none',
duration: 2500
});
return;
}
this.fetchOnSaleProducts(this.formData.bookName, 'title');
} else if (type === 'isbn') {
if (!this.scanResult) {
console.log("比价isbn", this.scanResult)
uni.showToast({
title: '请先扫码获取ISBN',
icon: 'none',
duration: 2500
});
return;
}
console.log("比价isbn", this.scanResult)
this.fetchOnSaleProducts(this.scanResult);
}
},
// 计算参考价格
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]));
// 从Vuex store获取运费和最低值
const shippingFee = this.freight;
const minValue = this.minValue;
console.log("priceMode111", this.priceMode)
const priceMode = uni.getStorageSync("current1")
console.log("priceMode", priceMode)
const selectedPositionIndex = uni.getStorageSync("selectedPositionIndex")
console.log("selectedPositionIndex", selectedPositionIndex)
switch (priceMode) {
case 0: // 最低价
// 获取选择的位置索引从store中获取
const positionIndex = this.selectedPosition || selectedPositionIndex || 0;
console.log("索引", positionIndex)
// 确保索引在有效范围内
const validIndex = Math.min(positionIndex, products.length - 1);
console.log("索引1", positionIndex)
console.log('使用第' + (validIndex + 1) + '条数据的价格');
// 获取选中位置的总价
const selectedTotal = parseFloat(products[validIndex].totalPrice);
this.lowestTotalPrice = parseFloat(products[0].totalPrice);
// 计算新价格:选中位置的总价 - 运费 - 最低值
const lowestPrice = selectedTotal - shippingFee - 0.01;
// 如果总价减去运费后的价格小于0则使用最低值设置的值
if (lowestPrice <= minValue) {
this.value4 = minValue;
} else {
this.value4 = parseFloat(lowestPrice.toFixed(2));
}
break;
case 1: // 均价
// 获取最低的N个价格并计算平均值
let count = Math.min(this.averageRange, products.length);
console.log("count", count)
let sum = 0;
for (let i = 0; i < count; i++) {
sum += parseFloat(products[i][priceField]);
console.log("sum+", sum)
}
// 计算平均总价后减去运费
const averagePrice = (sum / count) - shippingFee - 0.01;
console.log("averagePrice", averagePrice)
// 如果计算结果小于等于0则使用最低值
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'
});
},
// 关闭下拉框方法
closeDropdown() {
// 在uni-app中我们可以直接设置状态来关闭下拉框
if (this.showSearchDropdown) {
this.showSearchDropdown = false;
}
if (this.popupShow) {
this.popupShow = false;
}
},
// 处理价格变化事件
onPriceChange(value) {
this.value4 = value;
},
// 处理库存变化事件
onStockChange(value) {
this.value3 = value;
},
// 扫码成功回调
async startScanning() {
// 检查用户是否可以上传书籍
const canUpload = await checkMemberBooksCount();
if (!canUpload) {
// 如果不能上传,则直接返回,不继续执行
return;
}
// 如果已经上传了图片,则不允许扫描
if (this.fileList1.length > 0) {
uni.showToast({
title: '已上传图片不可修改ISBN',
icon: 'none',
duration: 2000
});
return;
}
// 如果当前正在扫码中,则不执行任何操作
if (this.isScanning) {
return;
}
const warehouse = this.warehouse
console.log("warehouse", warehouse)
const shelf = this.shelf
console.log("shelf", shelf)
const location = this.location
console.log("location", location)
// 验证仓库/货架/货位 - 确保三个值都必须存在
if (!warehouse || !shelf || !location) {
uni.showToast({
title: '请完整选择仓库、货架和货位',
icon: 'none',
duration: 2500 // 延长到2.5秒
});
return;
}
// 设置扫码状态为true按钮变为灰色
this.isScanning = true;
this.selectedStorage = `${warehouse} / ${shelf} / ${location}`;
console.log("selectedStorage", this.selectedStorage)
uni.scanCode({
onlyFromCamera: true,
scanType: ['barcode'],
success: (res) => {
console.log("res111", res)
// 扫码完成,恢复按钮状态
this.isScanning = false;
if (this.$refs.onSaleProductsComponent) {
this.$refs.onSaleProductsComponent.setCompareType('isbn');
}
if (res.result.length != 13) {
console.error('扫码失败:');
uni.showToast({
title: '扫码失败,请重试',
icon: 'none',
duration: 2500
})
} else {
this.scanResult = res.result;
this.fetchBookInfo(res.result); // 调用获取书籍信息
}
},
fail: (err) => {
// 扫码失败,恢复按钮状态
this.isScanning = false;
// 清空表单内容
this.scanResult = '';
this.formData.bookName = '';
this.fileList1 = [];
// 清空市场标签数据
this.marketTags = [{
label: '在售:',
value: 0
},
{
label: '旧:',
value: 0
},
{
label: '新:',
value: 0
},
{
label: '已售:',
value: 0
}
];
// 清空在售商品列表
if (this.$refs.onSaleProductsComponent) {
this.$refs.onSaleProductsComponent.updateProducts([]);
}
// 重置在售商品数据
this.onSaleProducts = [];
this.displayOnSaleProducts = [];
console.error('扫码失败:', err.errMsg);
uni.showToast({
title: '扫码失败,请重试',
icon: 'none',
duration: 2500
});
}
});
},
// 根据输入的ISBN搜索书籍信息
async searchByIsbn() {
// 检查用户是否可以上传书籍
const canUpload = await checkMemberBooksCount();
if (!canUpload) {
// 如果不能上传,则直接返回,不继续执行
return;
}
// 如果已经上传了图片,则不允许搜索
if (this.fileList1.length > 0) {
uni.showToast({
title: '已上传图片不可修改ISBN',
icon: 'none',
duration: 2000
});
return;
}
// 验证ISBN是否输入
if (!this.scanResult) {
uni.showToast({
title: '请输入ISBN',
icon: 'none',
duration: 2500
});
return;
}
// 验证ISBN格式
if (this.scanResult.length != 13) {
uni.showToast({
title: 'ISBN格式不正确应为13位数字',
icon: 'none',
duration: 2500
});
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;
}
this.selectedStorage = `${warehouse} / ${shelf} / ${location}`;
// 调用获取书籍信息的方法
this.fetchBookInfo(this.scanResult);
},
//新增获取书籍信息方法
async fetchBookInfo(isbn) {
console.log("扫描到ISBN:", isbn)
// 获取当前用户cookie
const cookie = uni.getStorageSync('UserInfoCookies');
console.log("cookie1111", cookie)
const newCookie = `PHPSESSID=${cookie}`;
console.log("newCookie", newCookie)
// 确保扫码状态为false以防万一
this.isScanning = false;
try {
// 调用孔夫子网站API获取图书信息
const res = await uni.request({
url: 'https://search.kongfz.com/pc-gw/search-web/client/pc/product/keyword/list',
// url: 'https://search.kongfz.com/pc-gw/search-web/client/pc/bookLib/keyword/list',
method: 'GET',
data: {
dataType: 0,
keyword: isbn,
page: 1,
userArea: '13003000000'
},
header: {
'Cookie': newCookie,
},
});
//调用接口获取已售商品
const soldOutRes = await uni.request({
url: 'https://api.buzhiyushu.cn/xcx/getOnSaleGoods',
method: 'GET',
data: {
dataType: 1, // 1 = 已售
keyword: isbn, // ISBN 或关键字
cookie: cookie, // 你的 Cookie
},
header: {
'Content-Type': 'application/json'
}
});
// 调用孔网图书条目接口获取官图(失败不影响主流程)
let bookPicRes = null;
try {
bookPicRes = await uni.request({
url: 'https://search.kongfz.com/pc-gw/search-web/client/pc/bookLib/keyword/list',
method: 'GET',
data: {
keyword: isbn,
},
header: {
'Cookie': newCookie,
'Content-Type': 'application/json'
},
});
} catch (bookPicError) {
console.warn('获取孔网图书官图失败,不影响主流程:', bookPicError);
bookPicRes = null;
}
uni.hideLoading();
console.log("在售响应:", res);
const responseData = Array.isArray(res) ? res[1].data : res.data;
console.log("已售响应", soldOutRes);
if (bookPicRes) {
console.log("图书条目响应:", bookPicRes);
}
const responseData1 = Array.isArray(res) ? soldOutRes[1].data.data.data : soldOutRes.data.data
.data;
// 安全地获取图书官图,如果失败则为空字符串
this.kfzBookPic = '';
if (bookPicRes && Array.isArray(bookPicRes) && bookPicRes[1]?.data?.data?.itemResponse?.list?.[0]
?.imgUrlEntity?.bigImgUrl) {
this.kfzBookPic = bookPicRes[1].data.data.itemResponse.list[0].imgUrlEntity.bigImgUrl;
}
console.log("图书条目图片:", this.kfzBookPic || '未获取到');
if (responseData.errType === "102" || responseData1.errType === "102") {
uni.showToast({
title: '请登录或切换孔网账号后再进行扫码上书',
icon: 'none',
duration: 2500
});
return;
}
// 处理product接口的响应数据结构
if (res[1].data.data.itemResponse.total != 0 && responseData && responseData.status === 1 &&
responseData.data) {
const buyCount = res[1].data.data.itemResponse.total;
const author = res[1].data.data.itemResponse.list[0].author;
const press = res[1].data.data.itemResponse.list[0].press;
const pubDateText = res[1].data.data.itemResponse.list[0].pubDateText
// 保存作者信息到组件数据中
this.author = author || '';
this.press = press || '';
this.pubDateText = pubDateText || '';
let bookData = null;
let productList = [];
// 检查不同的数据结构
if (responseData.data.itemResponse && responseData.data.itemResponse.list) {
// bookLib接口结构
productList = responseData.data.itemResponse.list;
} else if (responseData.data.productList) {
// product接口结构
productList = responseData.data.productList;
} else if (Array.isArray(responseData.data)) {
// 直接是数组
productList = responseData.data;
}
console.log("在售", responseData.data.itemResponse.pager.total)
if (productList && productList.length > 0) {
bookData = productList[0];
// 构造所需的书籍数据,兼容不同字段名
const data = {
bookName: bookData.bookName || bookData.title || bookData.name || '',
fixPrice: bookData.newBookMinPrice || bookData.price || bookData.minPrice || 1.00,
sellCount: responseData.data.itemResponse.pager.total,
buyCount: responseData1.data.itemResponse.pager.total,
condition: '', // 孔夫子API没有提供品相信息
};
// 更新到表单
this.bookInfo = data;
this.populateForm(data);
// 获取在售商品信息
this.fetchOnSaleProducts(isbn);
return;
}
}
// 如果没有查询到数据
// this.fetchOnSaleProducts(isbn);
this.isScanning = false;
// 清空表单内容
this.scanResult = '';
this.formData.bookName = '';
this.fileList1 = [];
// 清空市场标签数据
this.marketTags = [{
label: '在售:',
value: 0
},
{
label: '旧:',
value: 0
},
{
label: '新:',
value: 0
},
{
label: '已售:',
value: 0
}
];
// 清空在售商品列表
if (this.$refs.onSaleProductsComponent) {
this.$refs.onSaleProductsComponent.updateProducts([]);
}
// 重置在售商品数据
this.onSaleProducts = [];
this.displayOnSaleProducts = [];
uni.showToast({
title: '暂无当前书籍信息,请使用(无ISBN-上传)上传该书籍',
icon: 'none',
duration: 2500
});
} catch (error) {
uni.hideLoading();
console.error('请求异常:', error);
uni.showToast({
title: '网络请求失败',
icon: 'none',
duration: 2500
});
}
},
// 页面显示时触发
onShow() {
// 检查本地存储中是否有更新的仓库信息
const warehouse = uni.getStorageSync("selectedWarehouse");
if (warehouse) {
// 只更新仓库列表,不自动选择
this.selectedWarehouse = warehouse;
this.columns[0] = [warehouse.name]; // 更新仓库列
// 不再自动设置selectedStorage和warehouse
// 不再自动设置shelf和location
// 加载货架数据,但不自动选择
this.fetchShelves(warehouse.id).then(shelves => {
if (shelves.length > 0) {
this.columns[1] = shelves.map(item => item.code);
// 加载货位数据,但不自动选择
const firstSheId = shelves[0].id;
this.fetchLocations(firstSheId).then(locations => {
this.columns[2] = locations.map(item => item.code);
// 不再自动设置location
});
}
});
}
// 每次页面显示都拉取分类数据
console.log('onShow: 开始调用fetchCategoryData');
this.fetchCategoryData().then(() => {
console.log('onShow: fetchCategoryData执行完成');
}).catch(error => {
console.error('onShow: fetchCategoryData执行失败:', error);
});
},
close() {
// 在这里编写关闭弹窗时要执行的逻辑
this.show = false;
console.log('弹窗已关闭');
},
open() {
// 在这里编写打开弹窗时要执行的逻辑
this.show = true;
console.log('弹窗已打开');
},
// 公开的重置数据方法,供父组件调用
async resetData() {
console.log('ISBN组件resetData方法开始执行');
try {
// 保存当前的货区选择
const currentWarehouse = this.warehouse;
const currentShelf = this.shelf;
const currentLocation = this.location;
const currentSelectedStorage = this.selectedStorage;
// 清空所有数据
this.scanResult = ''; // 清空ISBN
this.kfzBookPic = ''; // 清空孔夫子图书官图
console.log('已清空scanResult:', this.scanResult);
// 重置表单数据
this.formData = {
isbn: '',
sku: '',
title: '',
art_no: '',
more: '',
bookName: '',
recommendation: ''
};
console.log('已重置formData:', this.formData);
// 重置价格和库存
this.value4 = 1.00;
this.value3 = 1;
console.log('已重置价格和库存:', {
price: this.value4,
stock: this.value3
});
// 清空文件列表和上传图片
this.fileList1 = [];
this.uploadedImages = [];
this.hasShownUploadMessage = false;
this.isUploading = false; // 重置上传状态
console.log('已清空图片相关数据');
// 重置市场标签
this.marketTags = [{
label: '在售:',
value: 0
},
{
label: '旧:',
value: 0
},
{
label: '新:',
value: 0
},
{
label: '已售:',
value: 0
}
];
console.log('已重置市场标签');
// 恢复货区选择
this.warehouse = currentWarehouse;
this.shelf = currentShelf;
this.location = currentLocation;
this.selectedStorage = currentSelectedStorage;
console.log('已恢复货区选择:', {
warehouse: this.warehouse,
shelf: this.shelf,
location: this.location
});
// 重置在售商品列表
if (this.$refs.onSaleProductsComponent) {
this.$refs.onSaleProductsComponent.updateProducts([]);
this.$refs.onSaleProductsComponent.setCompareType('isbn');
console.log('已重置在售商品列表');
}
// 重置品相选择
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('ISBN组件resetData方法执行完成');
} catch (error) {
console.error('重置数据时发生错误:', error);
return Promise.reject(error);
}
},
// 分类联动逻辑
onCategoryLevel1Change(e) {
const idx = e.detail.value;
this.categoryLevel1 = this.categoryList[idx];
this.categoryOptions2 = this.categoryLevel1.children || [];
this.categoryLevel2 = null;
this.categoryOptions3 = [];
this.categoryLevel3 = null;
this.selectedCategoryId = '';
},
onCategoryLevel2Change(e) {
const idx = e.detail.value;
this.categoryLevel2 = this.categoryOptions2[idx];
this.categoryOptions3 = this.categoryLevel2.children || [];
this.categoryLevel3 = null;
this.selectedCategoryId = '';
},
onCategoryLevel3Change(e) {
const idx = e.detail.value;
this.categoryLevel3 = this.categoryOptions3[idx];
this.selectedCategoryId = this.categoryLevel3.id;
},
// 分类数据初始化
initCategoryPicker() {
// console.log('initCategoryPicker开始执行');
// console.log('原始categoryList:', this.categoryList);
// 初始化分类选择器数据
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 = '';
console.log('没有分类数据,使用默认空分类');
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();
// 设置选中的分类ID叶子节点的ID
this.updateSelectedCategoryId();
// console.log('初始化后的分类数据:', {
// categoryColumns: this.categoryColumns,
// categoryIndexes: this.categoryIndexes,
// categoryLevels: this.categoryLevels,
// categoryPathText: this.categoryPathText,
// selectedCategoryId: this.selectedCategoryId
// });
// console.log('initCategoryPicker执行完成');
},
// 处理多列选择器的列变化
onCategoryColumnChange(e) {
// 获取当前变化的列和选中的值
const {
column,
value
} = e.detail;
// console.log(`列变化: 第${column}列, 值=${value}`);
// 更新对应列的索引
this.categoryIndexes[column] = value;
// 更新选中的分类对象
this.categoryLevels[column] = this.categoryColumns[column][value];
// 如果不是最后一列,需要级联更新后续列
if (column < this.maxCategoryLevel - 1) {
// 从当前列的下一列开始,重置所有后续列
this.updateSubsequentColumns(column + 1);
}
// 更新分类路径和选中ID
this.updateCategoryPathText();
this.updateSelectedCategoryId();
console.log('列变化后的分类数据:', {
categoryColumns: this.categoryColumns,
categoryIndexes: this.categoryIndexes,
categoryLevels: this.categoryLevels
});
},
// 更新后续列的数据
updateSubsequentColumns(startColumn) {
// 获取前一列选中的分类对象
const parentCategory = this.categoryLevels[startColumn - 1];
// 如果父分类不存在或没有子分类,则清空后续所有列
if (!parentCategory || !parentCategory.children || parentCategory.children.length === 0) {
// 从startColumn开始设置所有后续列为空数据
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;
console.log('分类选择确认:', values);
// 更新所有列的索引
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]];
}
}
// 更新分类路径和选中ID
this.updateCategoryPathText();
this.updateSelectedCategoryId();
console.log('已选择分类路径:', this.categoryPathText);
console.log('已选择分类ID:', this.selectedCategoryId);
},
// 更新分类路径文本
updateCategoryPathText() {
// 过滤出有效的分类名称(排除"暂无数据"
const validLevels = this.categoryLevels.filter(level => level && level.name && level.name !== '暂无数据');
// 用斜杠连接所有级别的名称
this.categoryPathText = validLevels.map(level => level.name).join(' / ');
// console.log('更新分类路径文本:', this.categoryPathText);
},
// 更新选中的分类ID最终叶子节点的ID
updateSelectedCategoryId() {
// 获取有效的分类级别(排除"暂无数据"
const validLevels = this.categoryLevels.filter(level => level && level.id && level.id !== '');
// 如果没有有效级别,则返回空字符串
if (validLevels.length === 0) {
this.selectedCategoryId = '';
return;
}
// 选择最后一个有效级别的ID作为选中的分类ID
this.selectedCategoryId = validLevels[validLevels.length - 1].id;
// console.log('更新选中的分类ID:', this.selectedCategoryId);
},
// 处理上传状态变化
handleUploadStatusChange(isUploading) {
console.log('文件上传状态变化:', isUploading ? '上传中' : '未上传');
this.isUploading = isUploading;
},
}
};
</script>
<style scoped>
/* 顶部Tab切换样式 */
.upload-tab-header {
display: flex;
background-color: #ffffff;
border-bottom: 1rpx solid #e5e5e5;
margin: -20rpx -20rpx 20rpx -20rpx;
padding: 0 20rpx;
}
.upload-tab-item {
flex: 1;
padding: 24rpx 0;
text-align: center;
position: relative;
}
.upload-tab-item text {
font-size: 28rpx;
color: #999999;
}
.upload-tab-item.active text {
color: #007AFF;
font-weight: 500;
}
.upload-tab-item.active::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60rpx;
height: 4rpx;
background-color: #007AFF;
border-radius: 2rpx;
}
.page-container {
padding: 20rpx;
padding-bottom: 120rpx;
/* 为固定定位的按钮留出空间 */
background-color: #f8f8f8;
min-height: 100vh;
/* 确保容器至少占满整个视口高度 */
box-sizing: border-box;
/* 确保padding不会增加总宽度 */
}
/* .fixed-bottom { */
/* 关键定位属性 */
/* position: fixed; */
/* 改为 fixed 定位 */
/* bottom: 0; */
/* left: 0; */
/* 横向铺满屏幕 */
/* right: 0; */
/* 尺寸与间距 */
/* width: calc(100% -20rpx); */
/* 移除 calc 计算 */
/* padding: 20rpx; */
/* 内边距替代左右边距 */
/* 视觉样式 */
/* background: #fff; */
/* 避免透明遮挡内容 */
/* box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.1); */
/* 顶部投影增强层次 */
/* z-index: 9; */
/* width: calc(100% - 40rpx);
position: fixed;
bottom: 0;
z-index: 99999; */
/* } */
.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;
/* 确保padding不会增加总宽度 */
}
/* 提交按钮样式 */
.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;
}
/* 搜索结果下拉框样式 */
.search-results {
position: absolute;
width: 100%;
max-height: 300rpx;
background-color: #fff;
border: 1px solid #ebedf0;
border-radius: 8rpx;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
z-index: 999;
overflow-y: auto;
margin-top: 2rpx;
transition: all 0.3s ease;
}
.result-item {
padding: 20rpx;
border-bottom: 1px solid #f0f0f0;
}
.result-item:last-child {
border-bottom: none;
}
.result-item:active {
background-color: #f5f5f5;
}
.tab-bar {
display: flex;
background-color: #fff;
margin-bottom: 30rpx;
overflow: hidden;
}
.tab-item {
flex: 1;
padding: 10rpx 0;
text-align: center;
font-size: 29rpx;
color: #666;
position: relative;
}
.tab-item.active {
color: #03A9F4;
background-color: rgba(0, 122, 255, 0.1);
}
.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;
/* font-size: 20rpx; */
color: #666;
position: relative;
/* border-bottom: 1px solid #ccc; */
}
.view-item-3 {
flex: 3 !important;
}
.view-item-4 {
flex: 4 !important;
}
.view-item-6 {
flex: 6 !important;
}
.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>.select {
padding: 10rpx;
text-align: center;
width: 100%;
height: 40rpx;
font-size: 18rpx;
line-height: 40rpx;
}
.view-item>.input {
padding: 10rpx 20rpx;
text-align: center;
width: 100%;
height: 40rpx;
line-height: 40rpx;
text-align: left;
font-size: 30rpx;
/* font-weight: 510; */
}
.view-item>.input-group {
padding: 10rpx;
text-align: center;
width: 100%;
height: 40rpx;
line-height: 40rpx;
}
.view-item>.input-group>.input-container {
display: flex;
width: 100%;
height: 40rpx;
line-height: 40rpx;
}
.select-container {
position: relative;
margin: 20rpx 0;
width: 100%;
}
.custom-select {
padding: 10rpx 20rpx;
background-color: #f5f5f5;
border-radius: 4rpx;
text-align: center;
cursor: pointer;
}
.custom-select text {
font-size: 28rpx;
color: #333;
}
.view-item>.input-group>.input-container>.btn {
background: #007AFF;
padding: 8rpx 20rpx;
border-radius: 6rpx;
color: white;
font-size: 24rpx;
}
.updateBook {
padding: 0rpx 10rpx;
}
.input-group1 {
display: flex;
align-items: center;
padding: 15rpx 20rpx;
background: #fff;
border-radius: 8rpx;
border: 0rpx solid #ddd;
width: 30%;
}
.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-container {
flex: 1;
display: flex;
align-items: center;
position: relative;
}
.scan-input {
flex: 1;
height: 60rpx;
font-size: 23rpx;
/* padding-right: 10rpx; */
/* 给右侧按钮留出空间 */
}
.scan-input-cangku {
font-size: 28rpx;
width: 100%;
}
.action-area {
position: absolute;
right: 0;
display: flex;
align-items: center;
gap: 20rpx;
}
.scan-btn {
background: #007AFF;
padding: 8rpx 20rpx;
border-radius: 20rpx;
color: white;
font-size: 24rpx;
margin-left: 10rpx;
}
.divider {
width: 1rpx;
height: 30rpx;
background: #ddd;
}
.retype-checkbox {
display: flex;
align-items: center;
font-size: 24rpx;
color: #666;
}
.tag-input-group {
display: flex;
flex-wrap: inherit;
gap: 20rpx;
margin-top: 15rpx;
}
.button-group {
display: flex;
align-items: center;
gap: 20rpx;
margin: 10rpx 0;
}
::v-deep .u-button--mini.data-v-2bf0e569 {
height: 60rpx;
width: 160rpx;
font-size: 24rpx;
}
::v-deep .u-button {
border-bottom-left-radius: 30rpx;
border-bottom-right-radius: 30rpx;
border-top-left-radius: 30rpx;
border-top-right-radius: 30rpx;
}
::v-deep .u-button--mini.data-v-2bf0e569 {
height: 60rpx;
width: 60rpx;
font-size: 24rpx;
}
::v-deep .u-safe-bottom {
height: 500px;
width: 500px;
}
.nav-left,
.nav-right {
width: 50rpx;
}
.back-icon,
.more-icon {
font-size: 40rpx;
}
::v-deep .u-button--square.data-v-2bf0e569 {
border-bottom-left-radius: 30rpx;
border-bottom-right-radius: 30rpx;
border-top-left-radius: 30rpx;
border-top-right-radius: 30rpx;
}
::v-deep .u-button.data-v-2bf0e569 {
width: 50%;
}
.select-container {
margin: 20rpx 0;
text-align: center;
}
.series-select {
width: 200rpx;
height: 60rpx;
line-height: 60rpx;
padding: 0 20rpx;
border: 1px solid #DDDDDD;
border-radius: 8rpx;
background-color: #FFFFFF;
font-size: 28rpx;
}
.general-label {
font-size: 32rpx;
color: #333;
margin-bottom: 1rpx;
}
.popup-image {
width: 200rpx;
height: 200rpx;
margin: 20rpx auto;
display: block;
}
.form-popup ::v-deep .u-popup__content {
width: 50rpx !important;
/* 正方形宽度 */
height: 50rpx !important;
/* 高度等于宽度 */
border-radius: 16rpx !important;
/* 圆角 */
overflow: hidden;
/* 隐藏溢出内容 */
display: flex !important;
flex-direction: column !important;
align-items: center !important;
padding: 30rpx !important;
}
/* 标题样式 */
.popup-title {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 30rpx;
}
/* 图片容器(正方形) */
.image-wrapper {
width: 400rpx;
height: 400rpx;
/* 等于宽度 */
border-radius: 8rpx;
overflow: hidden;
margin-bottom: 40rpx;
}
/* 图片填充容器 */
.popup-image {
width: 100%;
height: 100%;
}
/* 按钮容器 */
.button-group {
width: 100%;
display: flex;
justify-content: space-between;
gap: 20rpx;
}
/* 按钮基础样式 */
.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;
}
::v-deep .u-mode-center-box {
background-color: transparent !important;
}
.popupContentBox {
width: 600rpx;
padding: 50rpx;
}
.q_box_ {
width: 400rpx;
margin: 50rpx auto;
}
.popup-image.data-v-57280228 {
width: 300rpx;
height: 300rpx;
margin: 20rpx auto;
display: block;
}
::v-deep .data-v-57280228 .u-safe-bottom {
height: 0rpx;
width: 500rpx;
}
/* ::v-deep .u-toolbar__wrapper__cancel.data-v-55c89db1 {
color: #909193;
font-size: 45rpx;
padding: 0 15rpx;
}
::v-deep .u-toolbar__wrapper__confirm.data-v-55c89db1 {
color: #3c9cff;
font-size: 45rpx;
padding: 0 15rpx;
} */
::v-deep .u-picker__view__column__item.data-v-f45a262e {
font-size: 30rpx;
}
::v-deep .u-upload__deletable.data-v-69e2a36e {
position: absolute;
top: 0;
right: 0;
background-color: #9a7777;
height: 30rpx;
width: 30rpx;
display: flex;
flex-direction: row;
border-bottom-left-radius: 0rpx;
align-items: center;
justify-content: center;
z-index: 3;
}
::v-deep .u-icon__icon {
font-size: 40rpx !important;
line-height: 40rpx !important;
font-weight: 700 !important;
/* top: px; */
color: #020000 !important;
}
::v-deep .u-tag--large.data-v-3732d7af {
height: 50rpx;
line-height: 32rpx;
weight: 30rpx;
padding: 0 15rpx;
}
/* 改变对号的位置 */
::v-deep .u-upload__success__icon.data-v-69e2a36e {
display: none;
}
/* 背景色 */
::v-deep .u-upload__success.data-v-69e2a36e {
display: none;
}
::v-deep .u-upload__deletable.data-v-69e2a36e {
position: absolute;
top: 0;
right: 0;
background-color: #9E9E9E;
height: 40rpx;
width: 40rpx;
display: flex;
flex-direction: row;
border-bottom-left-radius: 1rpx;
align-items: center;
justify-content: center;
z-index: 3;
}
.market-tag {
color: #999;
font-size: 29rpx;
margin-right: 12rpx;
font-weight: normal;
background: none;
border: none;
border-radius: 0;
padding: 0;
}
.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;
}
::v-deep .view-item>.input.data-v-215497dc {
color: #666;
}
::v-deep .view-item>.select.data-v-5450f0a9 {
font-size: 16rpx;
}
/* 添加禁用状态的样式 */
.scan-input:disabled,
.input:disabled {
background-color: #f5f5f5;
color: #999;
}
.scan-btn-disabled {
pointer-events: none;
background-color: #cccccc !important;
color: #999 !important;
}
/* 分类选择器样式 */
.category-input {
flex: 1;
height: 60rpx;
font-size: 28rpx;
padding: 0 20rpx;
background-color: #f5f5f5;
border-radius: 8rpx 0 0 8rpx;
}
/* 禁止分类输入框编辑 */
.category-input:disabled {
background-color: #f5f5f5;
color: #333;
}
/* 分类选择器样式 */
.picker {
padding: 10rpx 20rpx;
background-color: #f5f5f5;
border-radius: 8rpx;
font-size: 28rpx;
color: #333;
min-height: 60rpx;
display: flex;
align-items: center;
margin-bottom: 10rpx;
}
.picker:empty::before {
content: '请选择分类';
color: #999;
}
/* 分类选择器样式 */
.picker-single {
padding: 8rpx 40rpx 8rpx 15rpx;
/* 左侧减少内边距,右侧增加内边距给箭头留空间 */
background-color: #f5f5f5;
border-radius: 8rpx;
font-size: 28rpx;
color: #333;
min-height: 50rpx;
/* 减小最小高度 */
display: flex;
align-items: center;
position: relative;
box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.05);
margin: 0;
/* 移除外边距 */
line-height: 1.2;
/* 设置合理的行高 */
width: 100%;
/* 设置宽度占满容器 */
box-sizing: border-box;
/* 确保内边距计算在宽度内 */
text-align: left;
/* 文字左对齐 */
white-space: nowrap;
/* 防止文字换行 */
overflow: hidden;
/* 超出部分隐藏 */
text-overflow: ellipsis;
/* 文字溢出显示省略号 */
margin-bottom: 10rpx;
}
.picker-single:after {
content: '';
position: absolute;
right: 15rpx;
/* 减少右侧距离 */
top: 50%;
transform: translateY(-50%);
width: 0;
height: 0;
border-left: 8rpx solid transparent;
border-right: 8rpx solid transparent;
border-top: 10rpx solid #007AFF;
}
.picker-single:active {
background-color: #e6e6e6;
}
.category-container {
display: flex;
flex-direction: column;
align-items: flex-start;
margin-bottom: 10rpx;
/* 减少底部间距 */
}
.view-item {
width: 100%;
/* 确保宽度占满容器 */
}
::v-deep .data-v-55c89db1 .u-toolbar__wrapper__confirm.data-v-55c89db1 {
color: #3c9cff;
font-size: 45rpx;
padding: 0 15rpx;
}
::v-deep .data-v-55c89db1 .u-toolbar__wrapper__cancel.data-v-55c89db1 {
color: #909193;
font-size: 45rpx;
padding: 0 15rpx;
}
::v-deep .u-toolbar.data-v-55c89db1 {
height: 50rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
</style>