diff --git a/supply-manager.example.js b/supply-manager.example.js deleted file mode 100644 index f1e9837..0000000 --- a/supply-manager.example.js +++ /dev/null @@ -1,66 +0,0 @@ -// 货源管理模块使用示例 -// 本文件展示如何在页面中使用SupplyManager类 - -const SupplyManager = require('./supply-manager.js'); - -// 页面实例示例 -const pageInstance = { - data: {}, - setData: function(data) { - this.data = { ...this.data, ...data }; - console.log('页面数据更新:', this.data); - } -}; - -// 初始化货源管理器 -const supplyManager = new SupplyManager(pageInstance); - -// 使用示例 -async function exampleUsage() { - console.log('===== 货源管理模块使用示例 ====='); - - try { - // 1. 加载货源列表 - console.log('1. 加载货源列表...'); - await supplyManager.loadSupplies(); - console.log(' 加载完成,货源数量:', supplyManager.data.supplies.length); - - // 2. 搜索货源 - console.log('2. 搜索货源...'); - supplyManager.data.searchKeyword = '罗曼粉'; - supplyManager.searchSupplies(); - console.log(' 搜索完成,结果数量:', supplyManager.data.publishedSupplies.length); - - // 3. 添加新货源 - console.log('3. 添加新货源...'); - supplyManager.data.newSupply = { - name: '罗曼粉', - price: '10.5', - minOrder: '50', - yolk: '红心', - spec: '格子装', - region: '北京市 北京市 朝阳区', - imageUrls: [] - }; - // 注意:实际添加货源需要登录状态和网络请求 - // await supplyManager.addSupply(); - console.log(' 新货源准备完成,等待发布'); - - // 4. 处理图片 - console.log('4. 处理图片URL...'); - const processedImages = supplyManager.processImageUrls(['http://example.com/image1.jpg', 'placeholder://example']); - console.log(' 图片处理结果:', processedImages); - - // 5. 格式化时间 - console.log('5. 格式化时间...'); - const formattedTime = supplyManager.formatCreateTime(new Date()); - console.log(' 格式化后的时间:', formattedTime); - - console.log('===== 示例运行完成 ====='); - } catch (error) { - console.error('示例运行出错:', error); - } -} - -// 运行示例 -exampleUsage(); diff --git a/supply-manager.js b/supply-manager.js deleted file mode 100644 index a22c956..0000000 --- a/supply-manager.js +++ /dev/null @@ -1,1120 +0,0 @@ -// 货源管理模块 - 抽离自seller页面 -// 不包含联系客服和入驻功能 - -const API = require('./api.js'); - -class SupplyManager { - constructor(pageInstance) { - this.page = pageInstance; - this.data = { - supplies: [], - publishedSupplies: [], - pendingSupplies: [], - rejectedSupplies: [], - draftSupplies: [], - showModal: false, - showEditModal: false, - showRejectReasonModal: false, - currentRejectSupply: null, - rejectReason: '', - showTabBar: true, - showSpecSelectModal: false, - modalSpecSearchKeyword: '', - filteredModalSpecOptions: [], - selectedModalSpecIndex: -1, - currentSpecMode: 'create', - showNameSelectModal: false, - showYolkSelectModal: false, - selectedNameIndex: -1, - selectedYolkIndex: -1, - productNameOptions: ['罗曼粉', '伊莎粉', '罗曼灰', '海蓝灰', '海蓝褐', '绿壳', '粉一', '粉二', '粉八', '京粉1号', '京红', '京粉6号', '京粉3号', '农大系列', '黑鸡土蛋', '双黄蛋', '大午金凤', '黑凤'], - yolkOptions: ['红心', '黄心', '双色'], - specOptions: ['格子装', '散托', '不限规格', '净重47+', '净重46-47', '净重45-46', '净重44-45', '净重43-44', '净重42-43', '净重41-42', '净重40-41', '净重39-40', '净重38-39', '净重37-39', '净重37-38', '净重36-38', '净重36-37', '净重35-36', '净重34-35', '净重33-34', '净重32-33', '净重32-34', '净重31-32', '净重30-35', '净重30-34', '净重30-32', '净重30-31', '净重29-31', '净重29-30', '净重28-29', '净重28以下', '毛重52以上', '毛重50-51', '毛重48-49', '毛重47-48', '毛重46-47', '毛重45-47', '毛重45-46', '毛重44-45', '毛重43-44', '毛重42-43', '毛重41-42', '毛重40-41', '毛重38-39', '毛重36-37', '毛重34-35', '毛重32-33', '毛重30-31', '毛重30以下'], - specSearchKeyword: '', - editSpecSearchKeyword: '', - filteredSpecOptions: [], - filteredEditSpecOptions: [], - productingOptions: ['1*360枚新包装', '1*360枚旧包新拖', '1*360枚旧包旧拖', '1*420枚新包装', '1*480枚新包装', '30枚蛋托散装', '360枚散托'], - productingSearchKeyword: '', - editProductingSearchKeyword: '', - filteredProductingOptions: [], - filteredEditProductingOptions: [], - showProductingSelectModal: false, - currentProductingMode: 'create', - showRegionSelectModal: false, - currentRegionMode: 'create', - regionOptions: [ - // 地区数据 - 这里简化处理,实际使用时可以从原始文件复制完整数据 - { - name: '北京市', - cities: [{ - name: '北京市', - districts: ['东城区', '西城区', '朝阳区', '丰台区', '石景山区', '海淀区'] - }] - } - // 更多地区数据可以根据需要添加 - ], - selectedProvinceIndex: 0, - selectedCityIndex: 0, - selectedDistrictIndex: 0, - currentCities: [], - currentDistricts: [], - regionSearchKeyword: '', - editRegionSearchKeyword: '', - filteredRegionOptions: [], - showSearchResults: false, - newSupply: { - name: '', - price: '', - minOrder: '', - yolk: '', - yolkIndex: 0, - spec: '', - specIndex: 0, - region: '', - grossWeight: '', - imageUrls: [] - }, - newSupplyRegionArray: [], - editSupplyRegionArray: [], - editSupply: { - yolkIndex: 0, - specIndex: 0 - }, - currentImageIndex: 0, - searchKeyword: '', - scale: 1, - offsetX: 0, - offsetY: 0, - lastDistance: 0, - lastTouchPoint: null, - imageWidth: 375, - imageHeight: 375, - minScale: 1, - maxScale: 4, - doubleTapTimeout: null, - doubleTapCount: 0, - pagination: { - published: { page: 1, pageSize: 20, hasMore: true, loading: false }, - pending: { page: 1, pageSize: 20, hasMore: true, loading: false }, - rejected: { page: 1, pageSize: 20, hasMore: true, loading: false }, - draft: { page: 1, pageSize: 20, hasMore: true, loading: false } - }, - currentLoadingType: null, - isPublishedExpanded: true, - isPendingExpanded: true, - isRejectedExpanded: true, - isDraftExpanded: true, - autoPublishAfterEdit: false, - _hasLoadedOnShow: false, - pageScrollLock: false, - touchMoveBlocked: false, - showAuthModal: false, - showOneKeyLoginModal: false, - pendingUserType: 'seller', - avatarUrl: '/images/default-avatar.png', - partnerstatus: '' - }; - - // 初始化规格搜索相关数据 - this.initData(); - } - - initData() { - this.data.filteredSpecOptions = this.data.specOptions; - this.data.filteredEditSpecOptions = this.data.specOptions; - this.data.currentCities = this.data.regionOptions[this.data.selectedProvinceIndex].cities; - this.data.currentDistricts = this.data.regionOptions[this.data.selectedProvinceIndex].cities[this.data.selectedCityIndex].districts; - - // 更新页面数据 - this.updatePageData(); - } - - updatePageData() { - if (this.page && this.page.setData) { - this.page.setData(this.data); - } - } - - // 加载货源列表 - loadSupplies() { - console.log('开始加载货源数据 - 分页模式'); - - // 重置所有分页状态 - this.resetAllPagination(); - - // 并行加载所有类型的货源 - return Promise.all([ - this.loadSuppliesFromServer('published', 1), - this.loadSuppliesFromServer('pending', 1), - this.loadSuppliesFromServer('rejected', 1), - this.loadSuppliesFromServer('draft', 1) - ]); - } - - // 重置所有分页状态 - resetAllPagination() { - this.data.pagination.published = { page: 1, pageSize: 20, hasMore: true, loading: false }; - this.data.pagination.pending = { page: 1, pageSize: 20, hasMore: true, loading: false }; - this.data.pagination.rejected = { page: 1, pageSize: 20, hasMore: true, loading: false }; - this.data.pagination.draft = { page: 1, pageSize: 20, hasMore: true, loading: false }; - this.data.currentLoadingType = null; - - this.updatePageData(); - } - - // 搜索货源 - searchSupplies() { - console.log('搜索货源,关键词:', this.data.searchKeyword); - - const keyword = this.data.searchKeyword.toLowerCase().trim(); - if (!keyword) { - // 如果关键词为空,重新加载所有数据 - return this.loadSupplies(); - } - - // 从所有货源中搜索 - const allSupplies = this.data.supplies; - - // 过滤符合条件的货源 - const filteredSupplies = allSupplies.filter(supply => { - const name = (supply.name || '').toLowerCase(); - const productName = (supply.productName || '').toLowerCase(); - const yolk = (supply.yolk || '').toLowerCase(); - const spec = (supply.spec || '').toLowerCase(); - - return name.includes(keyword) || - productName.includes(keyword) || - yolk.includes(keyword) || - spec.includes(keyword); - }); - - // 将过滤后的货源按照状态分类 - this.data.publishedSupplies = filteredSupplies.filter(s => s.status === 'published'); - this.data.pendingSupplies = filteredSupplies.filter(s => s.status === 'pending_review' || s.status === 'reviewed'); - this.data.rejectedSupplies = filteredSupplies.filter(s => s.status === 'rejected'); - this.data.draftSupplies = filteredSupplies.filter(s => s.status === 'draft' || s.status === 'sold_out'); - - this.updatePageData(); - } - - // 处理图片URL - processImageUrls(imageUrls) { - if (!imageUrls || !Array.isArray(imageUrls)) { - return []; - } - - return imageUrls.map(url => { - if (!url || typeof url !== 'string') return ''; - - let processedUrl = url.trim(); - - // 处理占位符URL - 替换为本地默认图片 - if (processedUrl.startsWith('placeholder://')) { - return '/images/default-product.png'; - } - - // 处理临时文件路径 - if (processedUrl.startsWith('http://tmp/') || processedUrl.startsWith('wxfile://')) { - return processedUrl; - } - - // 确保HTTP URL格式正确 - if (processedUrl.startsWith('//')) { - processedUrl = 'https:' + processedUrl; - } else if (!processedUrl.startsWith('http') && !processedUrl.startsWith('/')) { - processedUrl = '/' + processedUrl; - } - - return processedUrl; - }).filter(url => url && url !== ''); - } - - // 从服务器获取货源数据 - loadSuppliesFromServer(type = 'all', page = 1) { - return new Promise((resolve, reject) => { - const openid = wx.getStorageSync('openid'); - console.log(`loadSuppliesFromServer - type: ${type}, page: ${page}, openid:`, openid); - - if (!openid) { - console.warn('openid不存在,显示空数据状态'); - this.data.supplies = []; - this.data.publishedSupplies = []; - this.data.pendingSupplies = []; - this.data.rejectedSupplies = []; - this.data.draftSupplies = []; - this.updatePageData(); - resolve([]); - return; - } - - let status = []; - let pageSize = 20; - - switch (type) { - case 'published': - status = ['published']; - pageSize = this.data.pagination.published.pageSize; - this.data.pagination.published.loading = true; - this.data.currentLoadingType = 'published'; - break; - case 'pending': - status = ['pending_review', 'reviewed']; - pageSize = this.data.pagination.pending.pageSize; - this.data.pagination.pending.loading = true; - this.data.currentLoadingType = 'pending'; - break; - case 'rejected': - status = ['rejected']; - pageSize = this.data.pagination.rejected.pageSize; - this.data.pagination.rejected.loading = true; - this.data.currentLoadingType = 'rejected'; - break; - case 'draft': - status = ['draft', 'sold_out']; - pageSize = this.data.pagination.draft.pageSize; - this.data.pagination.draft.loading = true; - this.data.currentLoadingType = 'draft'; - break; - default: - status = ['all']; - pageSize = 100; - } - - const requestData = { - openid: openid, - viewMode: 'seller', - status: status, - page: page, - pageSize: pageSize - }; - - API.getAllSupplies(requestData) - .then(res => { - console.log(`从服务器获取${type}类型数据响应:`, res); - - if (res && res.success && res.products) { - const serverSupplies = res.products - .filter(product => product.status !== 'hidden') - .map(serverProduct => { - const mappedStatus = serverProduct.status; - let imageUrls = this.processImageUrls(serverProduct.imageUrls); - const createdAt = serverProduct.created_at || null; - const formattedCreatedAt = this.formatCreateTime(createdAt); - - return { - id: serverProduct.productId, - name: serverProduct.productName, - productName: serverProduct.productName, - price: serverProduct.price, - minOrder: serverProduct.quantity, - grossWeight: serverProduct.grossWeight, - yolk: serverProduct.yolk, - spec: serverProduct.specification, - region: serverProduct.region || '未知地区', - serverProductId: serverProduct.productId, - status: mappedStatus, - rejectReason: serverProduct.rejectReason || '', - imageUrls: imageUrls, - created_at: createdAt, - formattedCreatedAt: formattedCreatedAt, - currentImageIndex: 0, - product_contact: serverProduct.product_contact || '', - contact_phone: serverProduct.contact_phone || '' - }; - }); - - this.updateSuppliesByType(type, serverSupplies, res, page); - resolve(serverSupplies); - } else { - this.handleNoData(type); - resolve([]); - } - }) - .catch(err => { - console.error(`从服务器获取${type}类型数据失败:`, err); - this.handleLoadError(type, err); - reject(err); - }) - .finally(() => { - this.resetLoadingState(type); - }); - }); - } - - // 根据类型更新货源数据 - updateSuppliesByType(type, newSupplies, response, currentPage) { - const paginationKey = `pagination.${type}`; - - // 更新分页信息 - const hasMore = currentPage < (response.totalPages || 1); - this.data.pagination[type].hasMore = hasMore; - this.data.pagination[type].page = currentPage; - - // 更新货源列表 - if (currentPage === 1) { - this.data[`${type}Supplies`] = newSupplies; - } else { - const existingSupplies = this.data[`${type}Supplies`] || []; - this.data[`${type}Supplies`] = [...existingSupplies, ...newSupplies]; - } - - // 更新总列表 - this.updateAllSupplies(); - - this.updatePageData(); - } - - // 更新所有货源列表 - updateAllSupplies() { - this.data.supplies = [ - ...this.data.publishedSupplies, - ...this.data.pendingSupplies, - ...this.data.rejectedSupplies, - ...this.data.draftSupplies - ]; - } - - // 处理无数据情况 - handleNoData(type) { - this.data.pagination[type].hasMore = false; - this.data[`${type}Supplies`] = []; - this.updatePageData(); - } - - // 处理加载错误 - handleLoadError(type, err) { - this.data.pagination[type].loading = false; - this.updatePageData(); - } - - // 重置加载状态 - resetLoadingState(type) { - if (type !== 'all') { - this.data.pagination[type].loading = false; - this.data.currentLoadingType = null; - this.updatePageData(); - } - } - - // 加载更多货源 - loadMoreSupplies(type) { - const pagination = this.data.pagination[type]; - - if (!pagination.hasMore || pagination.loading) { - return; - } - - const nextPage = pagination.page + 1; - return this.loadSuppliesFromServer(type, nextPage); - } - - // 格式化创建时间 - formatCreateTime(timeValue) { - if (!timeValue) { - return '无'; - } - - try { - let date; - - if (typeof timeValue === 'string') { - date = new Date(timeValue); - - if (isNaN(date.getTime())) { - const cleanTime = timeValue.replace(/[^\d\-T:.]/g, ''); - date = new Date(cleanTime); - } - } else if (typeof timeValue === 'number') { - date = new Date(timeValue); - } else { - date = new Date(timeValue); - } - - if (isNaN(date.getTime())) { - return '无'; - } - - const year = date.getFullYear(); - const month = (date.getMonth() + 1).toString().padStart(2, '0'); - const day = date.getDate().toString().padStart(2, '0'); - const hours = date.getHours().toString().padStart(2, '0'); - const minutes = date.getMinutes().toString().padStart(2, '0'); - - return `${year}/${month}/${day} ${hours}:${minutes}`; - } catch (error) { - console.error('时间格式化错误:', error); - return '无'; - } - } - - // 显示添加货源弹窗 - showAddSupply(e) { - if (e && e.stopPropagation) { - e.stopPropagation(); - } - - // 尝试从本地存储加载保存的表单数据,支持多种格式 - let savedSupply = wx.getStorageSync('newSupplyDraft'); - let webFormDraft = wx.getStorageSync('supplyFormDraft'); - - // 如果没有找到保存的数据,使用默认数据 - if (!savedSupply || typeof savedSupply !== 'object') { - savedSupply = { name: '', price: '', minOrder: '', yolk: '', spec: '', grossWeight: '', region: '', imageUrls: [] }; - } - - // 如果有web格式的表单数据,优先使用 - if (webFormDraft) { - try { - const formData = typeof webFormDraft === 'string' ? JSON.parse(webFormDraft) : webFormDraft; - // 转换字段名以匹配小程序格式 - savedSupply = { - name: formData.productName || savedSupply.name, - price: formData.price || savedSupply.price, - minOrder: formData.quantity || savedSupply.minOrder, - grossWeight: formData.grossWeight || savedSupply.grossWeight, - yolk: formData.yolk || savedSupply.yolk, - spec: formData.specification || savedSupply.spec, - region: formData.region || savedSupply.region, - imageUrls: formData.imageUrls || savedSupply.imageUrls || [] - }; - console.log('已加载web格式的表单数据'); - } catch (e) { - console.error('加载web格式表单数据失败:', e); - } - } - - this.data.showImagePreview = false; - this.data.showModal = true; - this.data.newSupply = savedSupply; - - this.updatePageData(); - this.disablePageScroll(); - console.log('已加载保存的货源草稿数据'); - } - - // 隐藏弹窗 - hideModal() { - this.data.showModal = false; - this.data.showImagePreview = false; - this.updatePageData(); - this.enablePageScroll(); - } - - // 输入内容处理 - onInput(e) { - const field = e.currentTarget.dataset.field; - const value = e.detail.value; - this.data.newSupply[field] = value; - this.updatePageData(); - - // 实时保存到本地存储,支持多种格式以兼容不同页面 - wx.setStorageSync('newSupplyDraft', this.data.newSupply); - - // 同时保存为web格式,以便与网页端兼容 - const webFormData = { - productName: this.data.newSupply.name, - price: this.data.newSupply.price, - quantity: this.data.newSupply.minOrder, - grossWeight: this.data.newSupply.grossWeight, - yolk: this.data.newSupply.yolk, - specification: this.data.newSupply.spec, - region: this.data.newSupply.region, - imageUrls: this.data.newSupply.imageUrls || [] - }; - wx.setStorageSync('supplyFormDraft', JSON.stringify(webFormData)); - - console.log(`字段 ${field} 已更新并保存`); - } - - // 编辑输入处理 - onEditInput(e) { - const field = e.currentTarget.dataset.field; - const value = e.detail.value; - this.data.editSupply[field] = value; - this.updatePageData(); - } - - // 添加新货源 - addSupply() { - const userId = wx.getStorageSync('userId'); - const openid = wx.getStorageSync('openid'); - const userInfo = wx.getStorageSync('userInfo'); - - if (!userId || !openid || !userInfo) { - wx.showModal({ - title: '登录提示', - content: '请先登录再发布商品', - showCancel: true, - confirmText: '去登录', - success: (res) => { - if (res.confirm) { - this.data.showAuthModal = true; - this.updatePageData(); - } - } - }); - return; - } - - const { name, price, minOrder, yolk, spec, region, imageUrls, grossWeight } = this.data.newSupply; - if (!name || !price || !minOrder || !yolk) { - wx.showToast({ title: '请填写完整信息', icon: 'none', duration: 2000 }); - return; - } - - wx.showLoading({ title: '正在创建商品...', mask: true }); - - const productData = { - productName: name, - price: price, - quantity: Number(minOrder), - grossWeight: grossWeight && grossWeight !== '' ? grossWeight : "", - yolk: yolk, - specification: spec || '', - region: region || '', - rejectReason: '', - imageUrls: [] - }; - - API.publishProduct(productData) - .then(res => { - console.log('商品创建成功:', res); - - // 第二步:如果有图片,上传图片到已创建的商品 - if (imageUrls && imageUrls.length > 0) { - const productId = res.productId || res.data?.productId || res.product?.productId; - if (productId) { - return this.uploadImagesToExistingProduct(productId, imageUrls, openid); - } - } - return res; - }) - .then(finalRes => { - wx.hideLoading(); - wx.showToast({ - title: imageUrls && imageUrls.length > 0 ? '创建成功,图片已上传' : '创建成功', - duration: 3000 - }); - - // 重置表单 - this.data.showModal = false; - this.data.newSupply = { name: '', price: '', minOrder: '', yolk: '', spec: '', grossWeight: '', region: '', imageUrls: [] }; - - // 清除所有保存的草稿数据,包括小程序和网页格式 - wx.removeStorageSync('newSupplyDraft'); - wx.removeStorageSync('supplyFormDraft'); - - this.updatePageData(); - this.enablePageScroll(); - this.loadSupplies(); - - console.log('商品创建成功,所有草稿数据已清除'); - }) - .catch(err => { - console.error('商品创建或图片上传失败:', err); - wx.hideLoading(); - - let errorMsg = '上传服务器失败'; - if (err.message && err.message.includes('商品不存在')) { - errorMsg = '商品创建失败,无法上传图片'; - } - wx.showModal({ - title: '发布失败', - content: errorMsg + '\n\n错误详情: ' + (err.message || JSON.stringify(err)), - showCancel: false, - success: () => { - this.loadSupplies(); - } - }); - - // 失败时保持保存的草稿数据 - console.log('商品创建失败,保持草稿数据'); - }); - } - - // 上传图片到已存在商品 - uploadImagesToExistingProduct(productId, imageUrls, openid) { - return new Promise((resolve, reject) => { - if (!productId) { - reject(new Error('商品ID不能为空')); - return; - } - - if (!imageUrls || imageUrls.length === 0) { - resolve({ success: true, message: '没有图片需要上传' }); - return; - } - - const uploadSequentially = async () => { - const results = []; - - for (let i = 0; i < imageUrls.length; i++) { - try { - const result = await new Promise((resolveUpload, rejectUpload) => { - const formData = { - productId: productId, - openid: openid, - action: 'add_images_only', - imageIndex: i, - totalImages: imageUrls.length, - isUpdate: 'true', - timestamp: Date.now() - }; - - wx.uploadFile({ - url: API.BASE_URL + '/api/products/upload', - filePath: imageUrls[i], - name: 'images', - formData: formData, - success: (res) => { - if (res.statusCode === 200) { - try { - const data = JSON.parse(res.data); - if (data.success) { - resolveUpload(data); - } else { - rejectUpload(new Error(data.message || '图片上传失败')); - } - } catch (parseError) { - rejectUpload(new Error('服务器响应格式错误')); - } - } else { - rejectUpload(new Error(`HTTP ${res.statusCode}`)); - } - }, - fail: (err) => { - rejectUpload(new Error('网络错误: ' + err.errMsg)); - } - }); - }); - - results.push(result); - - // 添加延迟,避免服务器处理压力过大 - if (i < imageUrls.length - 1) { - await new Promise(resolve => setTimeout(resolve, 500)); - } - } catch (error) { - results.push({ success: false, error: error.message }); - } - } - - return results; - }; - - uploadSequentially() - .then(results => { - const successfulResults = results.filter(r => r && r.success); - if (successfulResults.length > 0) { - const lastResult = successfulResults[successfulResults.length - 1]; - resolve({ - success: true, - message: `成功上传${successfulResults.length}张图片`, - imageUrls: lastResult.imageUrls || [], - allImageUrls: lastResult.allImageUrls || [], - uploadedCount: successfulResults.length, - totalCount: lastResult.totalCount || successfulResults.length, - results: results - }); - } else { - reject(new Error('所有图片上传失败')); - } - }) - .catch(error => { - console.error('图片上传失败:', error); - reject(error); - }); - }); - } - - // 显示编辑弹窗 - showEditSupply(e, isPublishOperation = false) { - this.data.showImagePreview = false; - this.updatePageData(); - - const id = e.currentTarget.dataset.id; - if (!id) { - wx.showToast({ title: '操作失败,缺少货源信息', icon: 'none', duration: 2000 }); - return; - } - - // 在所有货源列表中查找 - let supply = this.data.supplies.find(s => s.id === id); - - if (!supply) { - wx.showToast({ title: '未找到该货源', icon: 'none', duration: 2000 }); - this.loadSupplies(); - return; - } - - // 计算蛋黄和规格的索引值 - const yolkIndex = this.data.yolkOptions.indexOf(supply.yolk) >= 0 ? this.data.yolkOptions.indexOf(supply.yolk) : 0; - const specIndex = this.data.specOptions.indexOf(supply.spec) >= 0 ? this.data.specOptions.indexOf(supply.spec) : 0; - - // 设置编辑货源数据 - const productName = supply.productName || supply.name; - this.data.editSupply = { - ...supply, - formattedCreatedAt: this.formatCreateTime(supply.created_at), - region: supply.region || '', - name: productName, - productName: productName, - yolkIndex: yolkIndex, - specIndex: specIndex - }; - - // 解析地区字符串为省市区数组 - let editSupplyRegionArray = []; - if (supply.region) { - editSupplyRegionArray = supply.region.split(' ').filter(item => item.trim() !== ''); - } - this.data.editSupplyRegionArray = editSupplyRegionArray; - - // 设置自动上架标志 - this.data.autoPublishAfterEdit = isPublishOperation; - this.data.showEditModal = true; - - this.updatePageData(); - this.disablePageScroll(); - } - - // 保存编辑后的货源信息 - saveEdit() { - const { editSupply, autoPublishAfterEdit } = this.data; - - if (!editSupply.name || !editSupply.price || !editSupply.minOrder || !editSupply.yolk) { - wx.showToast({ title: '请填写完整信息', icon: 'none', duration: 2000 }); - return; - } - - wx.showLoading({ title: '正在同步...', mask: true }); - - const openid = wx.getStorageSync('openid'); - - if (!openid) { - wx.hideLoading(); - wx.showModal({ - title: '登录状态异常', - content: '您的登录状态已失效,请重新登录后再尝试保存', - showCancel: false, - success: () => { - this.data.showEditModal = false; - this.updatePageData(); - this.enablePageScroll(); - } - }); - return; - } - - const productName = editSupply.productName || editSupply.name; - const productData = { - productName: productName, - price: editSupply.price, - quantity: Number(editSupply.minOrder), - grossWeight: editSupply.grossWeight !== undefined && editSupply.grossWeight !== null && editSupply.grossWeight !== '' ? editSupply.grossWeight : "", - yolk: editSupply.yolk, - specification: editSupply.spec || '', - region: editSupply.region || '', - imageUrls: editSupply.imageUrls || [], - created_at: new Date().toISOString(), - status: autoPublishAfterEdit ? 'pending_review' : '' - }; - - if (editSupply.serverProductId) { - // 编辑现有商品 - productData.productId = editSupply.serverProductId; - - const requestData = { - openid: openid, - productId: editSupply.serverProductId, - product: { - productName: productData.productName, - price: productData.price, - quantity: productData.quantity, - grossWeight: productData.grossWeight, - yolk: productData.yolk, - specification: productData.specification, - region: productData.region, - imageUrls: productData.imageUrls - }, - status: productData.status || '' - }; - - wx.request({ - url: API.BASE_URL + '/api/product/edit', - method: 'POST', - data: requestData, - success: (res) => { - wx.hideLoading(); - this.data.showEditModal = false; - this.updatePageData(); - this.enablePageScroll(); - wx.showToast({ title: '更新成功', duration: 2000 }); - this.loadSupplies(); - }, - fail: (err) => { - console.error('编辑商品失败:', err); - wx.hideLoading(); - wx.showToast({ title: '保存失败,请重试', icon: 'none', duration: 2000 }); - } - }); - } else { - // 创建新商品 - wx.request({ - url: API.BASE_URL + '/api/product/add', - method: 'POST', - data: productData, - success: (res) => { - wx.hideLoading(); - this.data.showEditModal = false; - this.updatePageData(); - this.enablePageScroll(); - wx.showToast({ title: '更新成功,等待审核', duration: 2000 }); - this.loadSupplies(); - }, - fail: (err) => { - console.error('商品创建失败:', err); - wx.hideLoading(); - wx.showToast({ title: '创建失败,请重试', icon: 'none', duration: 2000 }); - } - }); - } - } - - // 下架货源 - unpublishSupply(e) { - const supplyId = e.currentTarget.dataset.id; - - wx.showModal({ - title: '确认下架', - content: '确定要下架该商品吗?', - confirmText: '确定', - cancelText: '取消', - success: (res) => { - if (res.confirm) { - let supply = this.data.supplies.find(s => s.id === supplyId); - - if (!supply) { - supply = this.data.publishedSupplies.find(s => s.id === supplyId); - } - - if (!supply) { - // 直接使用ID尝试下架 - this.disablePageScroll(); - wx.showLoading({ title: '下架中...', mask: true }); - - API.hideProduct(supplyId) - .then(res => { - wx.hideLoading(); - this.enablePageScroll(); - wx.showToast({ title: '已下架', icon: 'success', duration: 2000 }); - this.loadSupplies(); - }) - .catch(err => { - wx.hideLoading(); - this.enablePageScroll(); - wx.showToast({ title: '下架失败,请重试', icon: 'none', duration: 2000 }); - }); - return; - } - - if (!supply.serverProductId) { - wx.showToast({ title: '无法下架,商品未上传到服务器', icon: 'none', duration: 2000 }); - return; - } - - this.disablePageScroll(); - wx.showLoading({ title: '下架中...', mask: true }); - - API.hideProduct(supply.serverProductId) - .then(res => { - wx.hideLoading(); - this.enablePageScroll(); - wx.showToast({ title: '已下架', icon: 'success', duration: 2000 }); - this.loadSupplies(); - }) - .catch(err => { - wx.hideLoading(); - this.enablePageScroll(); - wx.showToast({ title: '服务器同步失败,请重试', icon: 'none', duration: 3000 }); - this.loadSupplies(); - }); - } - } - }); - } - - // 删除货源 - deleteSupply(e) { - const id = e.currentTarget.dataset.id; - const supply = this.data.supplies.find(s => s.id === id); - - if (!supply) { - wx.showToast({ title: '货源不存在', icon: 'none', duration: 2000 }); - return; - } - - wx.showModal({ - title: '确认删除', - content: '确定要删除该货源吗?删除后将不再显示,但数据会保留。', - success: (res) => { - if (res.confirm) { - wx.showLoading({ title: '删除中...' }); - - let productIdToHide; - const idStr = String(id); - - if (supply.serverProductId) { - productIdToHide = supply.serverProductId; - } else if (idStr.startsWith('product_')) { - productIdToHide = id; - } else { - productIdToHide = id; - } - - API.deleteProduct(productIdToHide).then(() => { - wx.hideLoading(); - wx.showToast({ title: '删除成功', icon: 'success', duration: 2000 }); - this.loadSupplies(); - }).catch(error => { - wx.hideLoading(); - this.loadSupplies(); - wx.showToast({ title: '删除失败,请重试', icon: 'none', duration: 3000 }); - }); - } - } - }); - } - - // 显示审核失败原因弹窗 - showRejectReason(e) { - const id = e.currentTarget.dataset.id; - - wx.showLoading({ - title: '获取最新审核原因...', - mask: true - }); - - API.getProductList('rejected', { - page: 1, - pageSize: 20, - timestamp: new Date().getTime() - }).then(data => { - if (data && data.products && Array.isArray(data.products)) { - const supply = data.products.find(product => product.id === id); - - if (supply) { - this.data.rejectedSupplies = data.products; - this.data.currentRejectSupply = supply; - this.data.rejectReason = supply.rejectReason || '暂无详细的审核失败原因'; - this.data.showRejectReasonModal = true; - this.updatePageData(); - this.disablePageScroll(); - } else { - wx.showToast({ title: '未找到该货源', icon: 'none', duration: 2000 }); - } - } - }).catch(err => { - console.error('获取审核失败商品列表失败:', err); - let localSupply = this.data.supplies.find(s => s.id === id); - - if (localSupply) { - this.data.currentRejectSupply = localSupply; - this.data.rejectReason = localSupply.rejectReason || '暂无详细的审核失败原因'; - this.data.showRejectReasonModal = true; - this.updatePageData(); - this.disablePageScroll(); - } else { - wx.showToast({ title: '未找到该货源', icon: 'none', duration: 2000 }); - } - }).finally(() => { - wx.hideLoading(); - }); - } - - // 关闭审核失败原因弹窗 - closeRejectReasonModal() { - this.data.showRejectReasonModal = false; - this.updatePageData(); - this.enablePageScroll(); - } - - // 选择图片方法 - chooseImage(e) { - const type = e.currentTarget.dataset.type || 'new'; - let currentImages = type === 'new' ? this.data.newSupply.imageUrls || [] : this.data.editSupply.imageUrls || []; - - const maxCount = 5 - currentImages.length; - if (maxCount <= 0) { - wx.showToast({ title: '最多只能上传5张图片', icon: 'none', duration: 2000 }); - return; - } - - wx.chooseImage({ - count: maxCount, - sizeType: ['compressed'], - sourceType: ['album', 'camera'], - success: (res) => { - const tempFilePaths = res.tempFilePaths; - const updatedImages = [...currentImages, ...tempFilePaths]; - - if (type === 'new') { - this.data.newSupply.imageUrls = updatedImages; - } else { - this.data.editSupply.imageUrls = updatedImages; - } - - this.updatePageData(); - - // 实时保存到本地存储 - if (type === 'new') { - wx.setStorageSync('newSupplyDraft', this.data.newSupply); - } - }, - fail: (err) => { - console.error('选择图片失败:', err); - if (err.errMsg !== 'chooseImage:fail cancel') { - wx.showToast({ title: '选择图片失败,请重试', icon: 'none', duration: 2000 }); - } - } - }); - } - - // 删除图片 - deleteImage(e) { - const index = e.currentTarget.dataset.index; - const type = e.currentTarget.dataset.type || 'new'; - - if (type === 'new') { - this.data.newSupply.imageUrls.splice(index, 1); - this.updatePageData(); - wx.setStorageSync('newSupplyDraft', this.data.newSupply); - } else { - this.data.editSupply.imageUrls.splice(index, 1); - this.updatePageData(); - } - } - - // 禁用页面滚动 - disablePageScroll() { - if (this.page) { - this.page.setData({ pageScrollLock: true }); - } - } - - // 启用页面滚动 - enablePageScroll() { - if (this.page) { - this.page.setData({ pageScrollLock: false }); - } - } - - // iOS设备检测 - isIOS() { - const systemInfo = wx.getSystemInfoSync(); - return systemInfo.platform === 'ios'; - } -} - -module.exports = SupplyManager; diff --git a/supply.html b/supply.html index 1863e4f..7a60cd5 100644 --- a/supply.html +++ b/supply.html @@ -666,6 +666,18 @@ background-color: #ff4d4f; } + /* 禁用按钮样式 */ + .btn-disabled { + background-color: #d9d9d9; + color: #999; + cursor: not-allowed; + pointer-events: none; + } + + .btn-disabled:hover { + background-color: #d9d9d9; + } + /* 模态框按钮样式 */ .modal-btn { padding: 10px 24px; @@ -1107,7 +1119,29 @@ + + + +
+
+
+

选择新鲜程度

+ +
+ +
+
+ +
+
+
+
@@ -1259,6 +1293,16 @@
+ +
+ +
+ 请选择新鲜程度 + + +
+
+
@@ -1663,6 +1707,16 @@
+ + +
+ +
+ 请选择新鲜程度 + + +
+
@@ -3060,6 +3114,84 @@ } } + // 新鲜程度选择功能 + let allFreshnessOptions = ['正常质量(1-4天)', '一般质量(3天以内)', '一般质量(4天以上)', '精品']; + let filteredFreshnessOptions = [...allFreshnessOptions]; + let selectedFreshness = ''; + + // 显示新鲜程度选择弹窗 + function showFreshnessSelectModal() { + const freshnessSelectModal = document.getElementById('freshnessSelectModal'); + freshnessSelectModal.classList.add('active'); + // 重置搜索输入 + document.getElementById('freshnessSearchInput').value = ''; + filteredFreshnessOptions = [...allFreshnessOptions]; + generateFreshnessOptions(); + } + + // 隐藏新鲜程度选择弹窗 + function hideFreshnessSelectModal() { + const freshnessSelectModal = document.getElementById('freshnessSelectModal'); + freshnessSelectModal.classList.remove('active'); + } + + // 生成新鲜程度选项 + function generateFreshnessOptions() { + const freshnessOptionsList = document.getElementById('freshnessOptionsList'); + freshnessOptionsList.innerHTML = ''; + + filteredFreshnessOptions.forEach(freshness => { + const option = document.createElement('div'); + option.className = 'select-item'; + option.textContent = freshness; + option.onclick = () => { + // 移除所有选项的选中状态 + document.querySelectorAll('#freshnessOptionsList .select-item').forEach(item => { + item.classList.remove('selected'); + }); + // 添加当前选项的选中状态 + option.classList.add('selected'); + selectedFreshness = freshness; + }; + option.ondblclick = () => { + // 双击直接确认选择 + const freshnessDisplayText = document.getElementById('freshnessDisplayText'); + const freshnessInput = document.getElementById('freshness'); + + freshnessDisplayText.textContent = freshness; + freshnessInput.value = freshness; + hideFreshnessSelectModal(); + saveFormData(); // 保存选择 + }; + freshnessOptionsList.appendChild(option); + }); + } + + // 过滤新鲜程度选项 + function filterFreshnessOptions() { + const searchInput = document.getElementById('freshnessSearchInput'); + const searchKeyword = searchInput.value.toLowerCase(); + + filteredFreshnessOptions = allFreshnessOptions.filter(freshness => { + return freshness.toLowerCase().includes(searchKeyword); + }); + + generateFreshnessOptions(); + } + + // 确认新鲜程度选择 + function confirmFreshnessSelection() { + if (selectedFreshness) { + const freshnessDisplayText = document.getElementById('freshnessDisplayText'); + const freshnessInput = document.getElementById('freshness'); + + freshnessDisplayText.textContent = selectedFreshness; + freshnessInput.value = selectedFreshness; + hideFreshnessSelectModal(); + saveFormData(); // 保存选择 + } + } + // 地区选择功能 let allRegionOptions = [ { province: '北京市', cities: [ @@ -4077,13 +4209,13 @@ `; } else if (supply.status === 'rejected') { actionsHTML = ` - + `; } else if (supply.status === 'hidden' || supply.status === 'sold_out') { actionsHTML = ` - + `; } @@ -5294,6 +5426,7 @@ description: document.getElementById('description').value, region: document.getElementById('regionValue').value, contactId: document.getElementById('contactId').value, + freshness: document.getElementById('freshness').value, imageUrls: supplyData.uploadedImages, sellerId: userInfo.userId, // 添加当前登录用户的userId作为sellerId autoOfflineDays: null, // 不再使用天数,设置为null @@ -5910,11 +6043,14 @@ let specifications = []; let quantities = []; - // 解析规格(中文逗号分隔字符串) + // 解析规格(支持中英文逗号分隔字符串) try { if (supply.specification) { if (typeof supply.specification === 'string') { - specifications = supply.specification.split(',').filter(spec => spec.trim()); + specifications = supply.specification + .split(/[,,]/) // 同时处理中英文逗号 + .map(spec => spec.trim()) + .filter(spec => spec); } else if (Array.isArray(supply.specification)) { specifications = supply.specification; } else { @@ -5952,12 +6088,16 @@ addEditSpecQuantityPair(); } else { // 根据规格数量生成相应的规格-件数对 - for (let i = 0; i < specifications.length; i++) { + for (let i = 0; i < Math.max(specifications.length, quantities.length); i++) { + // 确保即使数量不匹配,也能正确显示对应的数据 + const spec = specifications[i] || ''; + const qty = quantities[i] || ''; + const pair = document.createElement('div'); pair.className = 'spec-quantity-pair'; pair.innerHTML = ` - - + + `; specQuantityPairs.appendChild(pair); @@ -6325,6 +6465,76 @@ hideEditProductingSelectModal(); } + // 编辑新鲜程度选择功能 + let editAllFreshnessOptions = ['正常质量(1-4天)', '一般质量(3天以内)', '一般质量(4天以上)', '精品']; + let editFilteredFreshnessOptions = [...editAllFreshnessOptions]; + let editSelectedFreshness = ''; + + // 显示编辑新鲜程度选择弹窗 + function showEditFreshnessSelectModal() { + const editFreshnessSelectModal = document.getElementById('editFreshnessSelectModal'); + editFreshnessSelectModal.classList.add('active'); + // 重置搜索输入 + document.getElementById('editFreshnessSearchInput').value = ''; + editFilteredFreshnessOptions = [...editAllFreshnessOptions]; + generateEditFreshnessOptions(); + } + + // 隐藏编辑新鲜程度选择弹窗 + function hideEditFreshnessSelectModal() { + const editFreshnessSelectModal = document.getElementById('editFreshnessSelectModal'); + editFreshnessSelectModal.classList.remove('active'); + } + + // 生成编辑新鲜程度选项 + function generateEditFreshnessOptions() { + const editFreshnessOptionsList = document.getElementById('editFreshnessOptionsList'); + editFreshnessOptionsList.innerHTML = ''; + + editFilteredFreshnessOptions.forEach(freshness => { + const option = document.createElement('div'); + option.className = 'select-item'; + option.textContent = freshness; + option.onclick = () => { + // 移除所有选项的选中状态 + document.querySelectorAll('#editFreshnessOptionsList .select-item').forEach(item => { + item.classList.remove('selected'); + }); + // 添加当前选项的选中状态 + option.classList.add('selected'); + editSelectedFreshness = freshness; + }; + option.ondblclick = () => { + // 双击直接确认选择 + document.getElementById('editFreshnessDisplayText').textContent = freshness; + document.getElementById('editFreshness').value = freshness; + hideEditFreshnessSelectModal(); + }; + editFreshnessOptionsList.appendChild(option); + }); + } + + // 过滤编辑新鲜程度选项 + function filterEditFreshnessOptions() { + const searchInput = document.getElementById('editFreshnessSearchInput'); + const searchKeyword = searchInput.value.toLowerCase(); + + editFilteredFreshnessOptions = editAllFreshnessOptions.filter(freshness => { + return freshness.toLowerCase().includes(searchKeyword); + }); + + generateEditFreshnessOptions(); + } + + // 确认编辑新鲜程度选择 + function confirmEditFreshnessSelection() { + if (editSelectedFreshness) { + document.getElementById('editFreshnessDisplayText').textContent = editSelectedFreshness; + document.getElementById('editFreshness').value = editSelectedFreshness; + } + hideEditFreshnessSelectModal(); + } + // 编辑地区选择功能 // 显示编辑地区选择弹窗 function showEditRegionSelectModal() { @@ -6898,10 +7108,10 @@ const specValue = pair.querySelector('.spec-value').value.trim(); const quantityValue = pair.querySelector('.quantity-input').value.trim(); - if (specValue && quantityValue) { - specifications.push(specValue); - quantities.push(quantityValue); - } + // 保存所有添加的规格和件数对,即使其中一个为空 + // 这样可以保持记忆功能,下次编辑时还能看到之前添加的对 + specifications.push(specValue); + quantities.push(quantityValue); }); @@ -6933,7 +7143,7 @@ description: document.getElementById('editDescription').value, region: document.getElementById('editRegionValue').value, contactId: document.getElementById('editContactId').value, - + freshness: document.getElementById('editFreshness').value, imageUrls: editCurrentImages, // 添加编辑后的图片列表 autoOfflineTime: autoOfflineTime, // 自动下架时间 autoOfflineDays: null, // 不再使用天数,设置为null