// pages/express-order/express-order.js import request from '../../utils/request.js' const PAGE_SIZE = 50 const LINK_PAGE_SIZE = 5 Page({ data: { sjyue: '0.00', shangpinList: [], // 最终展示的商品类型列表(已倒序) selectedTypeId: null, selectedHuiyuanId: null, selectedYaoqiuleixing: null, currentTypeChenghaoList: [], searchParams: { keyword: '', minPrice: '', labelId: '' }, searchLabelName: '', isSearchMode: false, templateList: [], currentPage: 1, hasMoreData: true, isLoadingMore: false, linkMap: {}, showDetailModal: false, showAddModal: false, showDeleteConfirm: false, showNewLinkConfirm: false, currentTemplate: null, currentTemplateIndex: -1, isEditing: false, editJieshao: '', editJiage: '', editLabelId: '', editLabelName: '', editCommissionEnabled: false, editCommissionValue: '', addJieshao: '', addJiage: '', addLabelId: '', addLabelName: '', addCommissionEnabled: false, addCommissionValue: '', detailLinkFilter: 0, detailLinkList: [], detailLinkPage: 1, detailLinkHasMore: true, isLoadingLinks: false, isLoading: false }, onLoad() { this.loadShangjiaYue() this.loadShangpinTypes() }, onShow() { this.registerNotificationComponent() this.loadShangjiaYue() }, registerNotificationComponent() { const app = getApp() const comp = this.selectComponent('#global-notification') if (comp && comp.showNotification) { app.globalData.globalNotification = { show: data => comp.showNotification(data), hide: () => comp.hideNotification() } } }, loadShangjiaYue() { const app = getApp() const data = app.globalData.shangjia || {} this.setData({ sjyue: data.sjyue || '0.00' }) }, async loadShangpinTypes() { this.setData({ isLoading: true }) try { const res = await request({ url: '/dingdan/sjspleixing', method: 'POST' }) if (res && res.data.code === 200) { let list = res.data.data || [] // 强制倒序排列 list.reverse() this.setData({ shangpinList: list, isLoading: false }) if (list.length > 0) { this.setSelectedType(list[0]) } } } catch (e) { console.error(e) this.setData({ isLoading: false }) wx.showToast({ title: '加载类型失败', icon: 'error' }) } }, setSelectedType(item) { this.setData({ selectedTypeId: item.id, selectedHuiyuanId: item.huiyuan_id, selectedYaoqiuleixing: item.yaoqiuleixing, currentTypeChenghaoList: item.chenghaoList || [] }, () => { this.resetAndLoadTemplates() }) }, resetAndLoadTemplates() { this.setData({ templateList: [], currentPage: 1, hasMoreData: true, isSearchMode: false, searchParams: { keyword: '', minPrice: '', labelId: '' }, searchLabelName: '' }) this.loadTemplates() }, async loadTemplates() { const { selectedTypeId, currentPage, isSearchMode, searchParams, linkMap } = this.data if (!selectedTypeId) { wx.showToast({ title: '请先选择订单类型', icon: 'none' }) return } if (currentPage === 1) this.setData({ isLoading: true }) else this.setData({ isLoadingMore: true }) try { const postData = { shangpinTypeId: selectedTypeId, page: currentPage, pageSize: PAGE_SIZE, getType: isSearchMode ? 1 : 2 } if (isSearchMode) { if (searchParams.keyword) postData.keyword = searchParams.keyword.trim() if (searchParams.minPrice) postData.minPrice = searchParams.minPrice if (searchParams.labelId) postData.labelId = searchParams.labelId } const res = await request({ url: '/peizhi/sjddmblb', method: 'POST', data: postData }) if (res && res.data.code === 200) { const data = res.data.data || {} const newTemplates = data.list || [] const existingIds = new Set(this.data.templateList.map(item => item.mobanId)) const uniqueNew = newTemplates.filter(item => !existingIds.has(item.mobanId)) const processed = uniqueNew.map(item => { const mobanId = item.mobanId || item.id const cached = linkMap[mobanId] || {} return { ...item, hasGenerated: cached.hasGenerated || !!item.linkUrl, isCopied: cached.isCopied || false, linkUrl: cached.linkUrl || item.linkUrl || '', mobanId: mobanId, jieshao: item.jieshao || item.moban_jieshao, jiage: item.jiage || item.price, fabushuliang: item.fabushuliang || item.fabu_shuliang || 0, labelId: item.labelId, labelName: item.labelName || '', commissionEnabled: item.commissionEnabled, commissionValue: item.commissionValue } }) this.setData({ templateList: currentPage === 1 ? processed : [...this.data.templateList, ...processed], hasMoreData: data.hasMore !== false && processed.length === PAGE_SIZE, isLoading: false, isLoadingMore: false }) } else { this.setData({ isLoading: false, isLoadingMore: false, hasMoreData: false }) } } catch (e) { console.error(e) this.setData({ isLoading: false, isLoadingMore: false }) wx.showToast({ title: '加载模板失败', icon: 'error' }) } }, // ---------- 搜索相关 ---------- onSearchKeywordInput(e) { this.setData({ 'searchParams.keyword': e.detail.value }) }, onSearchMinPriceInput(e) { this.setData({ 'searchParams.minPrice': e.detail.value }) }, onSearchLabelChange(e) { const idx = e.detail.value const label = this.data.currentTypeChenghaoList[idx] this.setData({ 'searchParams.labelId': label ? label.id : '', searchLabelName: label ? label.mingcheng : '' }) }, onSearchConfirm() { const { searchParams } = this.data if (!searchParams.keyword && !searchParams.minPrice && !searchParams.labelId) { this.resetAndLoadTemplates() return } this.setData({ isSearchMode: true, currentPage: 1, templateList: [], hasMoreData: true }, () => this.loadTemplates()) }, onClearSearch() { this.resetAndLoadTemplates() }, // ---------- 卡片生成链接 ---------- async onGenerateLink(e) { const { id } = e.currentTarget.dataset const idx = this.data.templateList.findIndex(item => item.mobanId === id) if (idx === -1) return await this.generateLinkForTemplate(this.data.templateList[idx], idx) }, onCopyLink(e) { const { id } = e.currentTarget.dataset const idx = this.data.templateList.findIndex(item => item.mobanId === id) if (idx === -1) return const template = this.data.templateList[idx] if (!template.linkUrl) { wx.showToast({ title: '请先生成链接', icon: 'none' }) return } wx.setClipboardData({ data: template.linkUrl, success: () => { const { linkMap } = this.data const mobanId = template.mobanId const updatedLinkMap = { ...linkMap } if (updatedLinkMap[mobanId]) updatedLinkMap[mobanId].isCopied = true const updatedList = [...this.data.templateList] updatedList[idx].isCopied = true this.setData({ linkMap: updatedLinkMap, templateList: updatedList }) wx.showToast({ title: '链接已复制', icon: 'success' }) } }) }, async generateLinkForTemplate(template, templateIndex) { const { selectedTypeId, linkMap } = this.data if (!selectedTypeId) { wx.showToast({ title: '请选择订单类型', icon: 'none' }) return } wx.showLoading({ title: '生成中...', mask: true }) try { const res = await request({ url: '/peizhi/sjljhq', method: 'POST', data: { mobanId: template.mobanId, shangpinTypeId: selectedTypeId } }) if (res && res.data.code === 200) { const data = res.data.data || {} const mobanId = template.mobanId const updatedLinkMap = { ...linkMap } updatedLinkMap[mobanId] = { hasGenerated: true, linkUrl: data.linkUrl || '', isCopied: false, newBalance: data.newBalance } const updatedList = [...this.data.templateList] updatedList[templateIndex] = { ...updatedList[templateIndex], hasGenerated: true, linkUrl: data.linkUrl || '', isCopied: false, newBalance: data.newBalance } if (data.newBalance) { const app = getApp() if (app.globalData.shangjia) app.globalData.shangjia.sjyue = data.newBalance this.setData({ sjyue: data.newBalance }) } this.setData({ linkMap: updatedLinkMap, templateList: updatedList }) wx.showToast({ title: '链接生成成功', icon: 'success' }) } else { wx.showToast({ title: res.data.msg || '生成失败', icon: 'error' }) } } catch (e) { wx.showToast({ title: '生成失败', icon: 'error' }) } finally { wx.hideLoading() } }, onCardTap(e) { const { target } = e if (target.className && (target.className.includes('btn') || target.className.includes('action'))) return const { item } = e.currentTarget.dataset if (!item) return const idx = this.data.templateList.findIndex(t => t.mobanId === item.mobanId) this.setData({ currentTemplate: item, currentTemplateIndex: idx, showDetailModal: true, isEditing: false, editJieshao: item.jieshao || '', editJiage: item.jiage || '', editLabelId: item.labelId || '', editLabelName: item.labelName || '', editCommissionEnabled: item.commissionEnabled || false, editCommissionValue: item.commissionValue || '', detailLinkFilter: 0, detailLinkList: [], detailLinkPage: 1, detailLinkHasMore: true }) this.loadDetailLinks() }, hideDetailModal() { this.setData({ showDetailModal: false, isEditing: false }) }, showAddModal() { this.setData({ showAddModal: true, addJieshao: '', addJiage: '', addLabelId: '', addLabelName: '', addCommissionEnabled: false, addCommissionValue: '' }) }, hideAddModal() { this.setData({ showAddModal: false }) }, hideDeleteConfirm() { this.setData({ showDeleteConfirm: false }) }, hideNewLinkConfirm() { this.setData({ showNewLinkConfirm: false }) }, // ---------- 链接筛选与加载 ---------- onToggleLinkFilter() { const newFilter = this.data.detailLinkFilter === 0 ? 1 : 0 this.setData({ detailLinkFilter: newFilter, detailLinkList: [], detailLinkPage: 1, detailLinkHasMore: true }, () => this.loadDetailLinks()) }, async loadDetailLinks() { const { currentTemplate, detailLinkFilter, detailLinkPage, isLoadingLinks } = this.data if (!currentTemplate || isLoadingLinks) return this.setData({ isLoadingLinks: true }) try { const res = await request({ url: '/peizhi/hqsjlslj', method: 'POST', data: { mobanId: currentTemplate.mobanId, used: detailLinkFilter, page: detailLinkPage, pageSize: LINK_PAGE_SIZE } }) if (res && res.data.code === 200) { const data = res.data.data || {} const newLinks = data.list || [] const merged = detailLinkPage === 1 ? newLinks : [...this.data.detailLinkList, ...newLinks] this.setData({ detailLinkList: merged, detailLinkHasMore: newLinks.length === LINK_PAGE_SIZE, isLoadingLinks: false }) } else { this.setData({ isLoadingLinks: false }) } } catch (e) { this.setData({ isLoadingLinks: false }) wx.showToast({ title: '加载链接失败', icon: 'error' }) } }, onLoadMoreLinks() { if (!this.data.detailLinkHasMore || this.data.isLoadingLinks) return this.setData({ detailLinkPage: this.data.detailLinkPage + 1 }, () => this.loadDetailLinks()) }, onCopyLinkItem(e) { const url = e.currentTarget.dataset.url if (!url) return wx.setClipboardData({ data: url, success: () => wx.showToast({ title: '已复制', icon: 'success' }) }) }, // ---------- 弹窗内操作 ---------- onGenerateLinkModal() { const { currentTemplate, currentTemplateIndex } = this.data if (!currentTemplate) return if (currentTemplate.hasGenerated && !currentTemplate.isCopied) { this.setData({ showNewLinkConfirm: true }) return } this.generateLinkForTemplate(currentTemplate, currentTemplateIndex) }, onCopyLinkModal() { const { currentTemplate, linkMap } = this.data if (!currentTemplate || !currentTemplate.linkUrl) { wx.showToast({ title: '请先生成链接', icon: 'none' }) return } wx.setClipboardData({ data: currentTemplate.linkUrl, success: () => { const mobanId = currentTemplate.mobanId const updatedLinkMap = { ...linkMap } if (updatedLinkMap[mobanId]) updatedLinkMap[mobanId].isCopied = true const updatedList = [...this.data.templateList] if (this.data.currentTemplateIndex !== -1) { updatedList[this.data.currentTemplateIndex].isCopied = true } const updatedCurrent = { ...currentTemplate, isCopied: true } this.setData({ linkMap: updatedLinkMap, templateList: updatedList, currentTemplate: updatedCurrent }) wx.showToast({ title: '链接已复制', icon: 'success' }) } }) }, // ---------- 编辑 ---------- onEditTemplate() { if (!this.data.isEditing) this.setData({ isEditing: true }) else this.saveTemplateEdit() }, onEditJieshaoInput(e) { this.setData({ editJieshao: e.detail.value }) }, onEditJiageInput(e) { this.setData({ editJiage: e.detail.value }) }, onEditLabelChange(e) { const idx = e.detail.value const label = this.data.currentTypeChenghaoList[idx] this.setData({ editLabelId: label ? label.id : '', editLabelName: label ? label.mingcheng : '' }) }, onEditCommissionToggle() { this.setData({ editCommissionEnabled: !this.data.editCommissionEnabled }) }, onEditCommissionValueInput(e) { this.setData({ editCommissionValue: e.detail.value }) }, async saveTemplateEdit() { const { currentTemplate, selectedTypeId, editJieshao, editJiage, editLabelId, editCommissionEnabled, editCommissionValue } = this.data if (!currentTemplate || !selectedTypeId) return if (editCommissionEnabled && (!editCommissionValue || isNaN(parseFloat(editCommissionValue)))) { wx.showToast({ title: '请输入有效佣金金额', icon: 'none' }) return } wx.showLoading({ title: '保存中...', mask: true }) try { const res = await request({ url: '/peizhi/sjddmbgx', method: 'POST', data: { mobanId: currentTemplate.mobanId, shangpinTypeId: selectedTypeId, jieshao: editJieshao, jiage: editJiage, labelId: editLabelId || '', commissionEnabled: editCommissionEnabled, commissionValue: editCommissionValue } }) if (res && res.data.code === 200) { const updatedList = [...this.data.templateList] const idx = this.data.currentTemplateIndex if (idx !== -1) { updatedList[idx] = { ...updatedList[idx], jieshao: editJieshao, jiage: editJiage, labelId: editLabelId, labelName: this.getLabelNameById(editLabelId), commissionEnabled: editCommissionEnabled, commissionValue: editCommissionValue } this.setData({ templateList: updatedList, currentTemplate: updatedList[idx], isEditing: false }) } wx.showToast({ title: '修改成功', icon: 'success' }) } else { wx.showToast({ title: res.data.msg || '修改失败', icon: 'error' }) } } catch (e) { wx.showToast({ title: '修改失败', icon: 'error' }) } finally { wx.hideLoading() } }, onDeleteTemplate() { this.setData({ showDeleteConfirm: true }) }, async confirmDeleteTemplate() { const { currentTemplate, selectedTypeId, linkMap } = this.data if (!currentTemplate || !selectedTypeId) return wx.showLoading({ title: '删除中...', mask: true }) try { const res = await request({ url: '/peizhi/sjddmbsc', method: 'POST', data: { mobanId: currentTemplate.mobanId, shangpinTypeId: selectedTypeId } }) if (res && res.data.code === 200) { const updatedLinkMap = { ...linkMap } delete updatedLinkMap[currentTemplate.mobanId] const updatedList = [...this.data.templateList] updatedList.splice(this.data.currentTemplateIndex, 1) this.setData({ linkMap: updatedLinkMap, templateList: updatedList, showDetailModal: false, showDeleteConfirm: false, currentTemplate: null, currentTemplateIndex: -1 }) wx.showToast({ title: '删除成功', icon: 'success' }) } else { wx.showToast({ title: res.data.msg || '删除失败', icon: 'error' }) } } catch (e) { wx.showToast({ title: '删除失败', icon: 'error' }) } finally { wx.hideLoading() } }, async confirmNewLink() { const { currentTemplate, currentTemplateIndex } = this.data if (!currentTemplate) return this.setData({ showNewLinkConfirm: false }) await this.generateLinkForTemplate(currentTemplate, currentTemplateIndex) }, // ---------- 添加模板 ---------- onAddJieshaoInput(e) { this.setData({ addJieshao: e.detail.value }) }, onAddJiageInput(e) { this.setData({ addJiage: e.detail.value }) }, onAddLabelChange(e) { const idx = e.detail.value const label = this.data.currentTypeChenghaoList[idx] this.setData({ addLabelId: label ? label.id : '', addLabelName: label ? label.mingcheng : '' }) }, onAddCommissionToggle() { this.setData({ addCommissionEnabled: !this.data.addCommissionEnabled }) }, onAddCommissionValueInput(e) { this.setData({ addCommissionValue: e.detail.value }) }, async onAddTemplate() { const { selectedTypeId, addJieshao, addJiage, addLabelId, addCommissionEnabled, addCommissionValue } = this.data if (!selectedTypeId) { wx.showToast({ title: '请选择订单类型', icon: 'none' }) return } if (!addJieshao.trim()) { wx.showToast({ title: '请输入订单介绍', icon: 'none' }) return } if (!addJiage || isNaN(parseFloat(addJiage)) || parseFloat(addJiage) <= 0) { wx.showToast({ title: '请输入有效的价格', icon: 'none' }) return } if (addCommissionEnabled && (!addCommissionValue || isNaN(parseFloat(addCommissionValue)))) { wx.showToast({ title: '请输入有效的佣金金额', icon: 'none' }) return } wx.showLoading({ title: '添加中...', mask: true }) try { const res = await request({ url: '/peizhi/sjtjddmb', method: 'POST', data: { shangpinTypeId: selectedTypeId, jieshao: addJieshao.trim(), jiage: addJiage, labelId: addLabelId || '', commissionEnabled: addCommissionEnabled, commissionValue: addCommissionValue } }) if (res && res.data.code === 200) { const data = res.data.data || {} const newTemplate = { mobanId: data.mobanId, jieshao: addJieshao, jiage: addJiage, fabushuliang: 0, hasGenerated: false, isCopied: false, linkUrl: '', labelId: addLabelId, labelName: this.getLabelNameById(addLabelId), commissionEnabled: addCommissionEnabled, commissionValue: addCommissionValue } this.setData({ templateList: [newTemplate, ...this.data.templateList], showAddModal: false, addJieshao: '', addJiage: '', addLabelId: '', addLabelName: '', addCommissionEnabled: false, addCommissionValue: '' }) wx.showToast({ title: '添加成功', icon: 'success' }) } else { wx.showToast({ title: res.data.msg || '添加失败', icon: 'error' }) } } catch (e) { wx.showToast({ title: '添加失败', icon: 'error' }) } finally { wx.hideLoading() } }, getLabelNameById(labelId) { if (!labelId) return '' const list = this.data.currentTypeChenghaoList const found = list.find(item => item.id == labelId) return found ? found.mingcheng : '' }, onScrollToLower() { const { hasMoreData, isLoadingMore, isSearchMode } = this.data if (!hasMoreData || isLoadingMore || isSearchMode) return this.setData({ currentPage: this.data.currentPage + 1 }, () => this.loadTemplates()) }, onSelectType(e) { const { id, item } = e.currentTarget.dataset this.setSelectedType(item) } })