You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1113 lines
36 KiB
1113 lines
36 KiB
// 货源管理模块 - 抽离自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: [],
|
|
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;
|
|
|