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

2571 lines
65 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

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

<template>
<view class="page-container" @click="closeDropdown">
<view v-if="currentTab === 'title'" class="form-container">
<!-- 仓库、货架、货位三级联动选择 -->
<view class="view-container">
<warehouse-selector :initialStorage="selectedStorage" :initialWarehouse="selectedWarehouse"
@label-click="navigateBack" @storage-selected="handleStorageSelected"
ref="warehouseSelector"></warehouse-selector>
<view class="view-item view-item-7" @click.stop="handleSearchBoxClick" style="position:relative;">
<!-- <view class="view-item">
<!-- 书名标签 -->
<view class="label">书名</view>
<!-- 输入框 -->
<input class="scan-input" v-model="formData2.bookName" placeholder="请输入书名" @click.stop />
<view class="scan-btn" @click.stop="getBookName">
<text>查询</text>
</view>
<!-- </view> -->
</view>
</view>
<view class="view-container">
<view class="view-item view-item-7">
<view class="label">isbn</view>
<view class="input-group">
<input class="scan-input" v-model="displayIsbn" placeholder="请输入isbn"
:disabled="isUnrecognized" />
<view class="unrecognized-checkbox">
<checkbox :checked="isUnrecognized" @click="toggleUnrecognized"
style="transform:scale(0.7);" />
<text class="checkbox-label">不识别</text>
</view>
</view>
</view>
</view>
<!-- 新增下拉选择框 -->
<!-- <view v-if="showSearchDropdown" class="search-results" @click.stop="handleDropdownClick">
<view class="result-item" v-for="(item, index) in searchResults" :key="index"
@click.stop="selectBook(item)">
{{ item.bookName }} (ISBN: {{ item.isbn }})
</view>
</view> -->
<!-- 使用封装后的品相选择组件不需要传入v-model -->
<book-condition-select ref="conditionSelect" @change="onConditionChange"></book-condition-select>
<!-- 更多搜索结果下拉框 -->
<view class="view-container" v-if="searchResults.length > 0">
<view class="view-item">
<view class="label">更多</view>
<view class="input-group">
<picker @change="onBookResultChange" :value="selectedBookIndex" :range="bookResultOptions"
range-key="text">
<view class="picker-content">
{{ selectedBookItem ? selectedBookItem.text : '请选择搜索结果' }}
<text class="arrow"></text>
</view>
</picker>
</view>
</view>
</view>
<price-stock-control :price.sync="value4" :stock.sync="value3" @priceChange="onPriceChange"
@stockChange="onStockChange" />
<camera-upload v-model="fileList1" :maxCount="9" :isbn="formData2.isbn" :bookName="formData2.bookName"
@input="handleFileChange"></camera-upload>
<!-- <view>
<uni-fab :pattern="pattern" :content="content" :horizontal="horizontal" :vertical="vertical"
:direction="direction" @trigger="trigger"></uni-fab>
</view> -->
<!-- <view v-if="bookPicPath" class="update">
<image :src="bookPicPath" mode="aspectFit"></image>
</view> -->
<view class="view-container">
<view class="view-item">
<!-- 市场竞争标签 -->
<view class="label">市场竞争</view>
</view>
<!-- 输入框 -->
<view class="tag-input-group">
<text v-for="(item, index) in marketTags" :key="index" class="market-tag">
[{{ item.label }}{{ item.value }}]
</text>
</view>
</view>
<on-sale-products :initialOnSaleProducts="onSaleProducts"
:initialDisplayOnSaleProducts="displayOnSaleProducts" :initialCompareType="compareType"
:isbn="formData2.isbn" :bookName="formData2.bookName" @compare-type-change="handleCompareTypeChange"
@filters-applied="handleFiltersApplied" @filters-reset="handleFiltersReset"
@products-updated="handleProductsUpdated" :showCompareButton="false" ref="onSaleProductsComponent" />
<!-- <view class="input-group" @click="getBookRecords">
<view class="general-label">上书记录</view>
</view> -->
<view class="form-item fixed-bottom" v-show="showSubmitButton">
<button type="primary" @click="submitForm" class="submit-btn"
:disabled="isSubmitting">{{ isSubmitting ? '正在提交...' : '提交' }}</button>
<u-popup class="form-popup" :show="popupDialog.show" mode="center">
<!-- 标题 -->
<view class="popupContentBox">{{ popupDialog.title }}</view>
<view class="popupContentBox">{{ popupDialog.content }}</view>
<!-- 图片容器保持正方形 -->
<view class="c_box_">
<image :src="popupDialog.imgSrc" mode="aspectFill" class="popup-image"></image>
</view>
<!-- 字母选择下拉框 -->
<view class="select-container">
<view class="custom-select" @click="popupDialog.showPicker = true">
<text>{{ popupDialog.selectedSeries || '请选择' }}</text>
</view>
</view>
<u-picker :show="popupDialog.showPicker" :columns="[popupDialog.seriesOptions]"
@confirm="onSeriesConfirm" @cancel="popupDialog.showPicker = false"></u-picker>
<!-- 按钮容器 -->
<view class="button-group">
<view class="btn cancel-btn" @click="onPopupCancel">
<text>{{ popupDialog.cancelText }}</text>
</view>
<view class="btn confirm-btn" @click="onPopupConfirm">
<text>{{ popupDialog.confirmText }}</text>
</view>
</view>
</u-popup>
</view>
</view>
</view>
</template>
<script>
import {
mapState
} from 'vuex'
// Vuex 模块拆分后使用命名空间访问
import CryptoJS from 'crypto-js';
// 导入拍照上传组件
import CameraUpload from '@/components/CameraUpload.vue';
import 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 * as selectBookImage from '@/service/selectBookImage.js';
// 导入上书记录获取方法
import * as bookRecords from '@/service/bookRecords.js';
// 导入仓库组件
import WarehouseSelector from '@/components/WarehouserSelector.vue';
// 导入品相组件
import BookConditionSelect from '@/components/BookConditionSelect.vue';
// 导入在售商品组件
import BookProductList from '@/components/BookProductList.vue';
// import * as Cookies from '@/pages/common/components/getCookies.js'
// 导入uni-app API
import {
uploadFile
} from '@/utils/upload.js';
// // 导入uni-popup组件
// import uniPopup from '@dcloudio/uni-ui/lib/uni-popup/uni-popup.vue';
// import uniPopupDialog from '@dcloudio/uni-ui/lib/uni-popup-dialog/uni-popup-dialog.vue';
export default {
name: 'titleUpload',
props: {
selectedWarehouse: {
type: Object,
default: null
}
},
computed: {
...mapState('price', ['priceMode', 'priceType', 'averageRange', 'freight', 'minValue']),
...mapState('warehouse', ['selectedPosition']),
// 添加计算属性
displayIsbn: {
get() {
return this.isUnrecognized ? '' : this.formData2.isbn;
},
set(value) {
if (!this.isUnrecognized) {
this.formData2.isbn = value;
}
}
}
},
components: {
"tab-bar": TabBar,
'bcode-camera': bcodeCamera,
"price-stock-control": PriceStockControl,
"camera-upload": CameraUpload,
"warehouse-selector": WarehouseSelector,
"on-sale-products": BookProductList,
"book-condition-select": BookConditionSelect,
},
// 将selectBookImage挂载到组件实例上
created() {
this.$selectBookImage = selectBookImage;
},
data() {
return {
currentTab: 'title', // 默认为仅书名上传
lowestBookPrice: 0,
lowestTotalPrice: 0,
retype: false, // 重输选项的状态
scanResult: null,
isSaving: false,
saveSuccess: false,
saveError: null,
isScanning: false, // 扫码状态变量
isSubmitting: false, // 防止重复提交的状态变量
show: false,
popupShow: false,
isbn: '',
value4: 1.00,
value3: 1,
fileList1: [],
fileList: [],
uploadedImages: [], // 存储上传成功的图片信息,用于提交表单时一并传递
selectedStorage: '',
warehouse: '',
shelf: '',
location: '',
bookPicPath: null, // 新增变量用于存储图片路径
searchResults: [], // 存储查询到的多条数据
showSearchDropdown: false, // 控制下拉框显示
selectedBookIndex: 0, // 当前选中的书籍结果索引
selectedBookItem: null, // 当前选中的书籍结果对象
bookResultOptions: [], // 用于显示在picker中的书籍结果选项
selectedConditionName: '', // 选中的品相名称
fixPrice: 1,
cameraRatio: '1:1', // 默认相机比例为1:1
showCameraRatioPopup: false, // 控制相机比例选择弹窗显示
compareType: 'isbn', // 默认为ISBN比价
titleCompareResults: [], // 存储书名比价结果示
showCamera: false, // 控制bcode-camera组件的显示
searchBoxRef: null, // 用于存储搜索框的引用
onSaleProducts: [], // 存储所有在售商品信息用于筛选
displayOnSaleProducts: [], // 存储按总价排序后的前十条在售商品信息用于展示
soldProducts: [], // 存储已售商品信息
// 筛选相关变量
showSubmitButton: true, // 控制提交按钮显示状态
publisherOptions: [], // 出版社选项
formattedData: [],
authorOptions: [], // 作者选项
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: [], // 货位列表
LocalselectedWarehouse: this.selectedWarehouse,
selectedSheId: null,
selectedFreId: null,
formData2: {
isbn: '',
sku: '',
title: '',
art_no: '',
more: '',
bookName: '',
},
columns: [
[], // 仓库列表
[], // 货架列表
[] // 货位列表
],
// 存储不同仓库对应的货架数据
warehouseShelvesData: {},
// 存储不同货架对应的货位数据
shelfLocationsData: {},
conditions: [{
name: '六品',
checked: false
},
{
name: '七品',
checked: false
},
{
name: '八品',
checked: false
},
{
name: '八五品',
checked: false
},
{
name: '九品',
checked: false
},
{
name: '九五品',
checked: false
},
{
name: '全新',
checked: false
}
],
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']
},
isUnrecognized: false, // 新增变量用于控制不识别的checkbox
};
},
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();
}
},
// 添加监听isUnrecognized变化
isUnrecognized: {
handler(newVal) {
if (newVal) {
// 如果勾选了"不识别"则设置ISBN为固定的13个0
this.formData2.isbn = '0000000000000';
} else {
// 如果取消勾选则清空ISBN
this.formData2.isbn = '';
}
}
}
},
async onLoad() {
const phoneNumber = uni.getStorageSync('phoneNumber');
const warehouse = uni.getStorageSync("selectedWarehouse");
console.log('选择仓库11111:', warehouse);
// 不再自动设置仓库、货架和货位
// 用户需要手动选择完整的三级数据
// 初始化仓库列,但不自动选择
if (warehouse) {
// 只初始化仓库列但不设置selectedStorage
this.selectedWarehouse = warehouse;
this.columns[0] = [warehouse.name]; // 假设仓库对象有name字段
// 不再自动设置selectedStorage
// 不再自动加载和选择货架和货位
}
const cookiesResponse = await this.getCookies("18904056801", "Long6166@")
console.log(cookiesResponse.cookies.PHPSESSID)
uni.setStorageSync('cookies', cookiesResponse.cookies.PHPSESSID);
console.log('Cookies已保存到本地存储', cookiesResponse.cookies.PHPSESSID);
},
// 添加onReady生命周期钩子uni-app中相当于mounted
onReady() {
// 在uni-app中我们可以使用页面级别的点击事件
// 这里不需要添加全局事件监听器,我们将在模板中使用@click事件
},
// 添加onUnload生命周期钩子uni-app中相当于beforeDestroy
onUnload() {
// 在uni-app中我们不需要手动移除事件监听器
},
onBackPress() {
if (this.$refs.fab.isShow) {
this.$refs.fab.close()
return true
}
return false
},
methods: {
// 选择品相
onConditionChange(index, conditionName) {
console.log('品相已选择:', index);
console.log('选中的品相名称:', conditionName);
// 保存选中的品相名称,用于表单提交
this.selectedConditionName = conditionName;
},
// 处理价格变化事件
onPriceChange(value) {
this.value4 = value;
},
// 处理筛选结果
handleFiltersApplied(filteredProducts) {
this.filteredOnSaleProducts = filteredProducts;
this.isFiltered = true;
},
// 处理产品数据更新
handleProductsUpdated(products) {
this.displayOnSaleProducts = products;
// 如果需要,可以在这里更新最低价格并重新计算参考价格
this.calculateReferencePrice();
},
// 处理库存变化事件
onStockChange(value) {
this.value3 = value;
},
handleTabChange(tab) {
if (tab === this.currentTab) return;
if (tab === 'isbn') {
// 跳转到ISBN上传页面
uni.navigateTo({
url: '/pkgUpload/isbn-upload/index'
});
}
},
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;
},
handleFileChange(newFileList) {
this.fileList1 = newFileList;
},
// 获取上书记录
async getBookRecords() {
try {
// 从本地存储获取手机号
const phoneNumber = uni.getStorageSync('phoneNumber');
if (!phoneNumber) {
uni.showToast({
title: '请先登录',
icon: 'none'
});
return;
}
// 显示加载提示
uni.showLoading({
title: '加载中...'
});
// 调用获取上书记录的方法
const records = await bookRecords.fetchBookRecords(phoneNumber);
// 隐藏加载提示
uni.hideLoading();
if (records.length === 0) {
uni.showToast({
title: '暂无上书记录',
icon: 'none'
});
return;
}
// 跳转到上书记录页面并传递数据
uni.navigateTo({
url: '/pkgUser/book-records',
success: (res) => {
// 向打开的页面传递数据
res.eventChannel.emit('bookRecordsData', {
records: records
});
}
});
} catch (error) {
console.error('获取上书记录失败:', error);
uni.hideLoading();
uni.showToast({
title: '获取上书记录失败',
icon: 'none'
});
}
},
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() {
// 防止重复提交
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)
// 根据当前选项卡进行表单验证{
// 仅书名上传模式验证
// 验证书名
if (!this.formData2.bookName) {
uni.showToast({
title: '请输入书名',
icon: 'none'
});
this.isSubmitting = false; // 重置提交状态
return;
}
// 验证仓库/货架/货位
if (!warehouse) {
uni.showToast({
title: '请选择仓库/货架/货位',
icon: 'none'
});
this.isSubmitting = false; // 重置提交状态
return;
}
if (!shelf) {
uni.showToast({
title: '请选择仓库/货架/货位',
icon: 'none'
});
this.isSubmitting = false; // 重置提交状态
return;
}
if (!location) {
uni.showToast({
title: '请选择仓库/货架/货位',
icon: 'none'
});
this.isSubmitting = false; // 重置提交状态
return;
}
// 检查是否选择了品相
const selectedCondition = this.$refs.conditionSelect.getSelectedCondition();
if (!selectedCondition) {
uni.showToast({
title: '请选择品相',
icon: 'none'
});
this.isSubmitting = false; // 重置提交状态
return;
}
// 上传所有待上传的图片
if (this.fileList1.length > 0) {
try {
// 显示上传中提示
uni.showLoading({
title: '正在上传图片...'
});
// 上传所有图片
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);
// 更新状态为上传成功
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: "上传失败"
});
// 显示错误提示
uni.showToast({
title: '图片上传失败',
icon: 'none'
});
// 重置提交状态
this.isSubmitting = false;
uni.hideLoading();
return;
}
}
}
uni.hideLoading();
} catch (error) {
console.error('图片上传过程出错:', error);
uni.hideLoading();
uni.showToast({
title: '图片上传失败',
icon: 'none'
});
this.isSubmitting = false;
return;
}
}
// 收集仅书名上传数据
const formData = {
barcode: this.formData2.isbn, // 正确绑定扫码结果
name: this.formData2.bookName, // 书名
recommendation: this.formData2.recommendation, // 推荐语
conditionCode: selectedCondition.name, // 品相名称
price: this.value4 * 100, // 商品售价
inventory: this.value3 || 1, // 库存
files: this.uploadedImages.length > 0 ? this.uploadedImages : this.fileList1.map(file => ({
...file,
num: file.num || '1' // 确保每个文件都有num属性
})), // 优先使用uploadedImages中的图片信息
fixPrice: this.fixPrice * 100,
marketTags: this.marketTags, // 市场标签
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') // 从本地存储获取手机号
};
// 根据当前选项卡打印对应数据
// const formData = this.currentTab === 'isbn' ? isbnData : titleData;
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'
});
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',
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);
// 清空表单数据,但保留品相选择
if (this.currentTab === 'isbn') {
this.formData = {
bookName: '',
recommendation: '',
};
this.scanResult = '';
} else {
this.formData2 = {
isbn: '',
bookName: '',
recommendation: '',
};
}
// 保持价格、库存和品相为用户选择的值
this.value4 = this.value4; // 保持价格
this.value3 = this.value3; // 保持库存
// 清空照片数据
this.fileList1 = []; // 清空文件列表
this.uploadedImages = []; // 清空上传图片数组
this.marketTags = []; // 清空市场标签
// 不重置品相选择保留conditions数组中的checked状态
// 显示提交成功提示
uni.showToast({
title: '提交成功',
icon: 'success'
});
console.log('请求成功,表单已清空');
},
fail: (err) => {
console.error('请求失败:', err);
uni.showToast({
title: '网络错误,请稍后重试',
icon: 'none'
});
}
});
// uni.showToast({
// title: '数据已打印到控制台',
// icon: 'none'
// });
},
// 图片上传到服务器
uploadFilePromise(url, index) {
return new Promise((resolve, reject) => {
// 获取当前选项卡下的书名和ISBN
const bookName = this.currentTab === 'isbn' ? this.formData.bookName : this.formData2.bookName;
console.log("bookName", bookName)
let isbn = this.currentTab === 'isbn' ? this.scanResult : this.formData2.isbn;
console.log("isbn", isbn)
// 图片编号从1开始
const num = (index + 1).toString();
uni.uploadFile({
url: "https://api.buzhiyushu.cn/zhishu/shopGoods/uploadImages", // 后端接口地址
filePath: url,
name: "file",
formData: {
bookName: bookName,
isbn: isbn,
num: num
},
success: (res) => {
console.log('图片上传成功:', res);
// 解析返回结果
const data = JSON.parse(res.data);
const imageUrl = data.url || url;
// 将上传成功的图片信息存储到数组中
this.uploadedImages.push({
url: imageUrl,
bookName: bookName,
isbn: isbn,
num: num,
originalUrl: url
});
resolve(imageUrl); // 如果返回了URL则使用否则使用原URL
},
fail: (err) => {
console.error('图片上传失败:', err);
reject(err);
}
});
});
},
// 数据填充方法
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 = parseInt(data.sellCount.replace('条', ''), 10);
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
}));
}
// 更新 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);
}
},
populateForm2(bookData) {
console.log("选中的数据", bookData);
this.formData2.isbn = bookData.isbn;
this.formData2.bookName = bookData.bookName;
this.formData2.recommendation = "权威认证 立即购买"; // 推荐语可从接口获取或固定
this.value = bookData.fixPrice || 0; // 价格
this.value1 = bookData.stock || 1; // 库存
// 处理品相和市场标签
const sellCount = bookData.sellCount ? parseInt(bookData.sellCount.replace('条',
''), 10) : 0;
const buyCount = bookData.buyCount ? parseInt(bookData.buyCount.replace('人买过', ''),
10) : 0;
this.conditions = this.conditions.map(condition => ({
...condition,
checked: condition.name === bookData
.condition // 假设接口返回 condition 字段
}));
this.marketTags = this.marketTags.map(item => {
if (item.label === '在售:') return {
...item,
value: sellCount
};
if (item.label === '已售:') return {
...item,
value: buyCount
};
return item;
});
// 处理图片路径(假设 bookPic 是完整 URL 或需要拼接)
this.bookPicPath = bookData.bookPic ?
`https://your-image-domain/${bookData.bookPic}` : null;
},
selectBook(bookData) {
this.showSearchDropdown = false; // 隐藏下拉框
this.populateForm2(bookData); // 填充表单
// 获取在售和已售商品信息
// if (bookData.bookName) {
// this.fetchOnSaleProducts(bookData.bookName);
// }
},
// 切换比价类型
switchCompareType(type) {
this.compareType = type;
if (type === 'title') {
if (!this.formData.bookName) {
console.log("比价书名", this.formData.bookName)
uni.showToast({
title: '请先输入书名',
icon: 'none'
});
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'
});
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;
switch (this.priceMode) {
case 0: // 最低价
// 获取选择的位置索引从store中获取
const positionIndex = this.selectedPosition || 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]);
}
// 计算平均总价后减去运费
const averagePrice = (sum / count) - shippingFee - 0.01;
// 如果计算结果小于等于0则使用最低值
if (averagePrice <= minValue) {
this.value4 = minValue;
} else {
this.value4 = parseFloat(averagePrice.toFixed(2));
}
break;
case 2: // 最新已售价
// 使用最低总价
this.value4 = parseFloat(products[0].totalPrice);
break;
}
},
switchCompareType1(type) {
this.compareType = type;
if (type === 'title') {
if (!this.formData2.bookName) {
uni.showToast({
title: '请先输入书名',
icon: 'none'
});
return;
}
this.fetchOnSaleProducts(this.formData2.bookName, 'title');
} else if (type === 'isbn') {
if (!this.formData2.isbn) {
uni.showToast({
title: '请先扫码获取ISBN',
icon: 'none'
});
return;
}
this.fetchOnSaleProducts(this.formData2.isbn, 'isbn');
}
},
// 返回上一页并清除缓存
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;
}
},
// 处理书名输入框点击事件,阻止冒泡
handleSearchBoxClick(event) {
// 阻止事件冒泡,防止触发全局点击事件
event.stopPropagation();
},
// 处理下拉框点击事件,阻止冒泡
handleDropdownClick(event) {
// 阻止事件冒泡,防止触发全局点击事件
event.stopPropagation();
},
// 获取在售商品信息
async fetchOnSaleProducts(keyword) {
try {
console.log("keyword", keyword)
const conditionValue = uni.getStorageSync("conditionValue");
const sortType = 7;
console.log("sortType", sortType)
const cookies = uni.getStorageSync('cookies');
// 调用封装在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()));
});
console.log('(已过滤屏蔽店铺)', filteredData);
// 保存所有数据用于筛选
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'
});
}
},
//书名上传回调
async getBookName() {
if (!this.selectedStorage) {
uni.showToast({
title: '请选择仓库',
icon: 'none'
});
return;
}
const bookName = this.formData2.bookName;
if (!bookName) {
uni.showToast({
title: '请输入书名',
icon: 'none',
});
return;
}
try {
const res = await uni.request({
url: 'https://api.buzhiyushu.cn/zhishu/baseInfo/getBookByName',
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
data: {
bookName: bookName
},
});
const responseData = Array.isArray(res) ? res[1] : res;
const resultData = responseData.data.data;
// 处理不同数据情况
if (Array.isArray(resultData)) {
if (resultData.length === 0) {
this.showEmptyTips();
} else if (resultData.length === 1) {
this.populateForm2(resultData[0]);
} else {
this.searchResults = resultData;
}
} else if (typeof resultData === 'object') {
this.populateForm2(resultData);
} else {
this.showEmptyTips();
}
if (responseData.data.code === 200) {
// 处理搜索结果
this.searchResults = responseData.data.data;
// 格式化用于picker显示的选项
this.bookResultOptions = this.searchResults.map(item => ({
text: `${item.bookName || '未知书名'} (ISBN: ${item.isbn || '无'})`,
value: item.isbn || ''
}));
// 默认选中第一项
if (this.bookResultOptions.length > 0) {
this.selectedBookIndex = 0;
this.selectedBookItem = this.bookResultOptions[0];
this.selectBook(this.searchResults[0]);
}
this.showSearchDropdown = false;
} else {
uni.showToast({
title: `请求失败: ${res.statusCode}`,
icon: 'none'
});
}
// 在所有数据处理完成后只调用一次fetchOnSaleProducts
await this.fetchOnSaleProducts(bookName, 'title');
} catch (error) {
console.error('请求异常:', error);
uni.showToast({
title: '网络请求失败',
icon: 'none'
});
}
},
// 新增方法:显示空数据提示
showEmptyTips() {
uni.showToast({
title: '暂无相关书籍数据',
icon: 'none',
duration: 2000
});
this.clearForm();
},
// 新增方法:清空表单
clearForm() {
this.formData2 = {
isbn: '',
bookName: this.formData2.bookName, // 保留输入的书名
recommendation: ''
};
this.value = 0;
this.value1 = 1;
this.fileList1 = [];
this.marketTags = this.marketTags.map(item => ({
...item,
value: 0
}));
// 不重置品相选择,保留用户之前的选择
// this.conditions.forEach(item => item.checked = false);
this.bookPicPath = null;
},
// 获取货架列表
async fetchShelves(depotId) {
try {
const [err, response] = await uni.request({
url: 'https://api.buzhiyushu.cn/shelves/shelves/sheNamelist',
data: {
depotId
}
});
if (!response?.data?.rows) return [];
this.shelves = response.data.rows; // 保存货架列表
this.columns[1] = this.shelves.map(item => item.code);
return this.shelves;
} catch (error) {
console.error('获取货架失败:', error);
return [];
}
},
// 获取货位列表
async fetchLocations(sheId) {
if (!sheId) {
console.error('获取货位列表失败未提供货架ID');
return [];
}
try {
console.log('开始获取货位数据货架ID:', sheId);
const [err, response] = await uni.request({
url: 'https://api.buzhiyushu.cn/shelves/shelves/freNamelist',
method: 'GET',
data: {
sheId
}
});
if (err) {
console.error('获取货位请求错误:', err);
return [];
}
console.log('货位API响应:', response);
if (!response || !response.data || !response.data.rows) {
console.error('货位响应数据格式不正确');
return [];
}
const locations = response.data.rows;
console.log('解析后的货位数据:', locations);
// 保存货位数据
this.locations = locations;
// 更新货位列
this.columns[2] = locations.map(item => item.code || '未知货位');
console.log('更新后的货位列:', this.columns[2]);
return locations;
} catch (error) {
console.error('获取货位列表失败:', error);
return [];
}
},
// 处理picker列变化
changeHandler(e) {
// 防御性检查确保e和必要的属性存在
if (!e) {
console.warn('changeHandler: 事件对象为空');
return;
}
console.log('changeHandler 事件:', JSON.stringify(e));
// 获取列索引和选中的索引数组
const {
columnIndex,
index,
indexes = []
} = e;
console.log('列索引:', columnIndex, '选中索引:', index, 'indexes数组:',
indexes);
// 如果是选择了仓库第0列
if (columnIndex === 0) {
// 获取选中的仓库
const warehouseName = this.columns[0][index];
const warehouse = this.selectedWarehouse || {
id: null,
name: warehouseName
};
console.log('选中的仓库:', warehouseName, '仓库对象:', warehouse);
// 如果有仓库ID获取对应的货架
if (warehouse.id) {
console.log('开始获取货架数据仓库ID:', warehouse.id);
this.fetchShelves(warehouse.id).then(shelves => {
console.log('获取到货架数据:', shelves);
// 清空货位列
this.columns[2] = [];
// 更新UI
this.$nextTick(() => {
if (this.$refs.uPicker) {
this.$refs.uPicker
.setColumnValues(2, []);
}
});
});
}
}
// 如果是选择了货架第1列
if (columnIndex === 1) {
// 获取选中的货架索引
const shelfIndex = index;
console.log('选中的货架索引:', shelfIndex);
// 确保货架数据有效
if (Array.isArray(this.shelves) && this.shelves.length > 0 &&
shelfIndex >= 0 && shelfIndex < this
.shelves.length) {
const selectedShelf = this.shelves[shelfIndex];
console.log("选中的货架对象:", selectedShelf);
// 保存选中的货架ID
this.selectedSheId = selectedShelf.id;
// 如果货架有ID获取对应的货位
if (selectedShelf?.id) {
console.log('开始获取货位数据货架ID:', selectedShelf.id);
this.fetchLocations(selectedShelf.id).then(
locations => {
console.log('获取到货位数据:', locations);
// 确保locations是数组且有数据
if (Array.isArray(locations) && locations
.length > 0) {
// 更新货位列
this.columns[2] = locations.map(item =>
item.code || '未知货位');
console.log('更新后的货位列:', this.columns[
2]);
// 更新UI
this.$nextTick(() => {
if (this.$refs.uPicker) {
console.log(
'更新货位选择器UI');
this.$refs.uPicker
.setColumnValues(2,
this.columns[2]
);
}
});
} else {
console.warn('获取到的货位数据为空');
// 清空货位列
this.columns[2] = ['暂无货位'];
this.$nextTick(() => {
if (this.$refs.uPicker) {
this.$refs.uPicker
.setColumnValues(2,
this.columns[2]
);
}
});
}
}).catch(error => {
console.error('获取货位数据失败:', error);
// 显示错误提示
this.columns[2] = ['获取失败'];
this.$nextTick(() => {
if (this.$refs.uPicker) {
this.$refs.uPicker
.setColumnValues(2,
this.columns[2]);
}
});
});
} else {
console.warn('货架ID无效');
}
} else {
console.warn('无效的货架索引或数据未准备好', {
shelfIndex,
shelvesLength: this.shelves?.length
});
// 清空货位列
this.columns[2] = ['请先选择有效货架'];
this.$nextTick(() => {
if (this.$refs.uPicker) {
this.$refs.uPicker.setColumnValues(2, this.columns[2]);
}
});
}
}
},
// 确认选择
confirm(e) {
const {
value
} = e;
const [warehouse, shelf, location] = value;
// 只有当三个值都存在时才保存选中的值
if (warehouse && shelf && location) {
this.warehouse = warehouse;
this.shelf = shelf;
this.location = location;
// 更新显示文本
this.selectedStorage = `${warehouse} / ${shelf} / ${location}`;
} else {
// 如果不完整,提示用户
uni.showToast({
title: '请完整选择仓库、货架和货位',
icon: 'none'
});
}
this.show = false;
// 获取选中的完整对象(根据实际数据结构调整)
const selectedShelf = this.shelves.find(item => item.code ===
shelf);
const selectedLocation = this.locations.find(item => item.code ===
location);
// 保存选中ID等后续操作
this.selectedSheId = selectedShelf?.id;
this.selectedFreId = selectedLocation?.id;
console.log('已选择:', {
warehouse: this.warehouse,
shelf: this.shelf,
location: this.location,
selectedSheId: this.selectedSheId,
selectedFreId: this.selectedFreId
});
},
// 书籍搜索结果选择变更
async onBookResultChange(e) {
const index = e.detail.value;
this.selectedBookIndex = index;
this.selectedBookItem = this.bookResultOptions[index];
// 选择对应的书籍数据并填充表单
const selectedBook = this.searchResults[index];
this.selectBook(selectedBook);
// 根据选中的书籍更新在售商品列表
if (selectedBook.bookName) {
await this.fetchOnSaleProducts(selectedBook.bookName, 'title');
}
},
toggleUnrecognized() {
this.isUnrecognized = !this.isUnrecognized;
if (this.isUnrecognized) {
// 勾选"不识别"时内部设置ISBN为13个0但界面显示为空
this.formData2.isbn = '0000000000000';
// uni.request({
// url: 'https://api.buzhiyushu.cn/zhishu/statistic/isbn',
// method: 'GET',
// success: (res) => {
// console.log("res-isbn", res)
// this.formData2.isbn = res.data;
// },
// fail: (err) => {
// uni.showToast({
// title: '获取随机ISBN失败',
// icon: 'none'
// });
// }
// });
} else {
// 取消勾选时清空ISBN
this.formData2.isbn = '';
}
},
},
// 调用后端接口获取仓库列表
async fetchWarehouses(phoneNumber) {
try {
console.log('开始获取仓库列表,手机号:', phoneNumber);
const [err, response] = await uni.request({
url: 'https://api.buzhiyushu.cn/shelves/shelves/namelist',
method: 'GET',
data: {
phoneNumber: phoneNumber
}
});
if (err) {
console.error('请求发生错误:', err);
return [];
}
console.log('API响应完整数据:', response);
if (!response || !response.data) {
console.error('响应数据为空');
return [];
}
console.log('响应数据:', response.data);
if (!response.data.rows) {
console.error('rows数据为空');
return [];
}
const warehouses = response.data.rows || [];
console.log('解析后的仓库数据:', warehouses);
this.columns[0] = warehouses.map(item => item.code || '未命名仓库');
console.log('更新后的仓库列表:', this.columns[0]);
return warehouses;
} catch (error) {
console.error('获取仓库列表失败:', error);
return [];
}
},
// 根据仓库名称获取ID
getWarehouseId(warehouseName) {
const warehouses = Object.values(this.warehouseShelvesData).flat();
const warehouse = warehouses.find(w => w.code === warehouseName);
return warehouse ? warehouse.id : null;
},
// 根据货架名称获取ID
getShelfId(shelfName) {
const shelves = Object.values(this.warehouseShelvesData).flat();
const shelf = shelves.find(s => s.code === shelfName);
return shelf ? shelf.id : null;
},
// 页面显示时触发
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
});
}
});
}
},
close() {
// 在这里编写关闭弹窗时要执行的逻辑
this.show = false;
console.log('弹窗已关闭');
},
open() {
// 在这里编写打开弹窗时要执行的逻辑
this.show = true;
console.log('弹窗已打开');
},
trigger(e) {
console.log(e)
this.content[e.index].active = !e.item.active
uni.showModal({
title: '提示',
content: `${this.content[e.index].active ? '选中了' : '取消了'}${e.item.text}`,
success: function(res) {
if (res.confirm) {
console.log('用户点击确定')
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
},
fabClick() {
uni.showToast({
title: '点击了悬浮按钮',
icon: 'none'
})
},
switchBtn(hor, ver) {
if (hor === 0) {
this.direction = this.direction === 'horizontal' ? 'vertical' : 'horizontal'
this.directionStr = this.direction === 'horizontal' ? '垂直' : '水平'
} else {
this.horizontal = hor
this.vertical = ver
}
this.$forceUpdate()
},
switchColor() {
this.is_color_type = !this.is_color_type
if (this.is_color_type) {
this.pattern.iconColor = '#aaa'
this.pattern.buttonColor = '#fff'
} else {
this.pattern.iconColor = '#fff'
this.pattern.buttonColor = '#007AFF'
}
}
};
</script>
<style scoped>
.page-container {
padding: 20rpx;
padding-bottom: 120rpx;
/* 为固定定位的按钮留出空间 */
background-color: #f8f8f8;
min-height: 100vh;
/* 确保容器至少占满整个视口高度 */
box-sizing: border-box;
/* 确保padding不会增加总宽度 */
}
.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;
}
.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; */
}
/* 搜索结果下拉框样式 */
.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: 5rpx 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: 10rpx;
text-align: center;
height: 40rpx;
line-height: 40rpx;
color: #000;
font-size: 29rpx;
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;
text-align: center;
width: 100%;
height: 40rpx;
line-height: 40rpx;
text-align: left;
}
.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;
}
.book-list {
margin-top: 20rpx;
display: flex;
flex-wrap: wrap;
}
.book-list>.label {
padding: 10rpx;
display: block;
width: calc(100% - 20rpx);
height: 40rpx;
color: #333;
border-bottom: 2rpx solid #ccc;
}
.book-list>.label>.btn {
display: inline-block;
padding: 10rpx;
text-align: center;
width: 120rpx;
height: 30rpx;
line-height: 30rpx;
color: #fff;
background-color: #3c9cff;
border-radius: 10%;
margin-right: 10rpx;
}
.book-list>.container {
position: relative;
width: 100%;
overflow: hidden;
}
.book-list>.container>.product-grid {
display: flex;
flex-wrap: wrap;
gap: 10rpx;
}
@media screen and (max-width: 768rpx) {
.book-list>.container>.product-grid>.product-card {
width: calc(25% - 7rpx);
}
}
@media screen and (max-width: 480rpx) {
.book-list>.container>.product-grid>.product-card {
width: calc(50% - 5rpx);
}
.book-list>.container>.product-grid>.product-card>.product-image {
height: 200rpx;
}
}
.book-list>.container>.product-grid>.product-card {
width: calc(25% - 8rpx);
background-color: #ffffff;
border-radius: 12rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
overflow: hidden;
/* margin-bottom: 10rpx; */
flex-shrink: 0;
height: 180rpx;
display: flex;
flex-direction: column;
position: relative;
}
.book-list>.container>.product-grid>.product-card>.product-image-container {
position: relative;
width: 100%;
height: 140rpx;
overflow: hidden;
}
.book-list>.container>.product-grid>.product-card>.product-image-container>.product-image {
width: 100%;
height: 100%;
object-fit: contain;
flex: 0 0 auto;
background-color: #f5f5f5;
}
.book-list>.container>.product-grid>.product-card>.product-image-container>.product-info {
padding: 8rpx;
font-size: 24rpx;
flex: 1;
overflow: hidden;
text-align: center;
}
.book-list>.container>.product-grid>.product-card>.product-image-container>.product-info>.product-price {
font-size: 28rpx;
font-weight: bold;
color: #ff6b00;
display: block;
margin-bottom: 4rpx;
text-align: center;
}
.book-list>.container>.product-grid>.product-card>.product-image-container>.price-details {
font-size: 22rpx;
line-height: 1.2;
overflow: hidden;
text-overflow: ellipsis;
display: flex;
flex-direction: row;
justify-content: center;
gap: 8rpx;
color: #ffffff;
background-color: rgba(0, 0, 0, 0.5);
padding: 4rpx 0;
border-radius: 0 0 8rpx 8rpx;
position: absolute;
bottom: 0;
left: 0;
right: 0;
z-index: 1;
}
.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;
/* 给右侧按钮留出空间 */
text-align: left;
}
.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;
}
.section-title {
font-size: 28rpx;
color: #333;
}
.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;
}
.filter-section {
margin-bottom: 30rpx;
}
/* 筛选弹窗样式 */
.filter-popup {
padding: 30rpx;
background-color: #fff;
}
.nav-left,
.nav-right {
width: 50rpx;
}
.back-icon,
.more-icon {
font-size: 40rpx;
}
.filter-buttons {
display: flex;
justify-content: space-between;
margin-top: 40rpx;
/* padding: 0 20rpx; */
}
::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: 15rpx;
}
.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;
}
.u-toolbar__wrapper__cancel.data-v-55c89db1 {
color: #909193;
font-size: 25rpx;
padding: 0 15rpx;
}
::v-deep .u-toolbar__wrapper__cancel.data-v-55c89db1 {
color: #909193;
font-size: 30rpx;
padding: 0 15rpx;
}
::v-deep .u-toolbar__wrapper__confirm.data-v-55c89db1 {
color: #3c9cff;
font-size: 30rpx;
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;
}
.view-container {
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 20rpx;
background-color: #fff;
}
.half-item {
flex: 1;
display: flex;
align-items: center;
/* 可选:加间距 */
/* padding: 0 10rpx; */
box-sizing: border-box;
}
/* 新增横向标签样式 */
.label-horizontal {
display: flex;
padding: 1rpx 10rpx;
align-items: center;
justify-content: center;
text-align: center;
height: 60rpx;
line-height: 60rpx;
min-width: 80rpx;
color: #000;
font-size: 30rpx;
background-color: #ccc;
border-top-left-radius: 10rpx;
border-bottom-left-radius: 10rpx;
/* 确保文字横向显示 */
writing-mode: horizontal-tb;
}
/* 添加不识别复选框的样式 */
.unrecognized-checkbox {
display: flex;
align-items: center;
justify-content: flex-end;
margin-left: auto;
padding-right: 10rpx;
}
.checkbox-label {
font-size: 24rpx;
color: #666;
margin-left: 5rpx;
}
.input-group {
display: flex;
align-items: center;
width: 100%;
}
.market-tag {
color: #999;
font-size: 29rpx;
margin-right: 12rpx;
font-weight: normal;
background: none;
border: none;
border-radius: 0;
padding: 0;
}
.picker-content {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;
}
</style>