diff --git a/app.json b/app.json index 42a3cbf..2078840 100644 --- a/app.json +++ b/app.json @@ -22,6 +22,7 @@ "pages/cooperation/index", "pages/goods/index", "pages/order/index", + "pages/order/detail/index", "pages/company/company" ], "subpackages": [ @@ -50,7 +51,8 @@ "phone-test", "clear-storage", "gross-weight-tester", - "fix-connection" + "fix-connection", + "order-test" ], "independent": false } diff --git a/pages/order/detail/index.js b/pages/order/detail/index.js new file mode 100644 index 0000000..a5a2978 --- /dev/null +++ b/pages/order/detail/index.js @@ -0,0 +1,79 @@ +// pages/order/detail/index.js +Page({ + // 分享给朋友/群聊 + onShareAppMessage() { + return { + title: '鸡蛋贸易平台 - 订单详情', + path: '/pages/order/detail/index', + imageUrl: '/images/你有好蛋.png' + } + }, + + // 分享到朋友圈 + onShareTimeline() { + return { + title: '鸡蛋贸易平台 - 订单详情', + query: '', + imageUrl: '/images/你有好蛋.png' + } + }, + + data: { + orderId: '', + orderDetail: null, + loading: false, + error: '' + }, + + onLoad(options) { + if (options.orderId) { + this.setData({ orderId: options.orderId }); + this.loadOrderDetail(); + } + }, + + // 加载订单详情 + loadOrderDetail() { + const orderId = this.data.orderId; + if (!orderId) { + this.setData({ error: '订单ID不能为空' }); + return; + } + + this.setData({ loading: true, error: '' }); + + wx.request({ + url: `http://localhost:3003/api/orders/detail/${orderId}`, + method: 'GET', + header: { + 'Content-Type': 'application/json' + }, + success: (res) => { + console.log('获取订单详情成功:', res.data); + if (res.data.success) { + this.setData({ + orderDetail: res.data.data, + loading: false + }); + } else { + this.setData({ + error: res.data.message || '获取订单详情失败', + loading: false + }); + } + }, + fail: (err) => { + console.error('获取订单详情失败:', err); + this.setData({ + error: '网络请求失败,请稍后重试', + loading: false + }); + } + }); + }, + + // 返回上一页 + goBack() { + wx.navigateBack(); + } +}) \ No newline at end of file diff --git a/pages/order/detail/index.json b/pages/order/detail/index.json new file mode 100644 index 0000000..95c7a35 --- /dev/null +++ b/pages/order/detail/index.json @@ -0,0 +1,4 @@ +{ + "navigationBarTitleText": "订单详情", + "usingComponents": {} +} \ No newline at end of file diff --git a/pages/order/detail/index.wxml b/pages/order/detail/index.wxml new file mode 100644 index 0000000..0ccd5fc --- /dev/null +++ b/pages/order/detail/index.wxml @@ -0,0 +1,106 @@ + + + + 加载中... + + + + + {{error}} + + + + + + + + 订单号: {{orderDetail.sales_no}} + {{orderDetail.order_date}} + + + + + 客户信息 + + + 公司名称: + {{orderDetail.customer_company}} + + + 联系人: + {{orderDetail.contact_person}} + + + 联系电话: + {{orderDetail.phone}} + + + 联系地址: + {{orderDetail.address}} + + + + + + + 订单摘要 + + + 总金额: + ¥{{orderDetail.total_amount}} + + + 总件数: + {{orderDetail.total_pieces}} + + + 总斤数: + {{orderDetail.total_weight}} + + + 支付状态: + {{orderDetail.payment_status}} + + + 订单状态: + {{orderDetail.order_status}} + + + + + + + 产品详情 + + + + {{item.product_name}} + + + + 销售件数: + {{item.sales_pieces}} + + + 销售斤数: + {{item.sales_weight}} + + + 单价: + ¥{{item.unit_price}} + + + 小计: + ¥{{item.sales_amount}} + + + + + + + + + + 暂无订单详情 + + \ No newline at end of file diff --git a/pages/order/detail/index.wxss b/pages/order/detail/index.wxss new file mode 100644 index 0000000..89a03c2 --- /dev/null +++ b/pages/order/detail/index.wxss @@ -0,0 +1,206 @@ +/* pages/order/detail/index.wxss */ +.order-detail-page { + min-height: 100vh; + background-color: #f5f5f5; + padding: 20rpx; +} + +/* 加载中 */ +.loading { + display: flex; + justify-content: center; + align-items: center; + padding: 120rpx 0; + background-color: #fff; + border-radius: 12rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + font-size: 32rpx; + color: #666; +} + +/* 错误提示 */ +.error { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 120rpx 40rpx; + background-color: #fff; + border-radius: 12rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + font-size: 32rpx; + color: #ff4d4f; + text-align: center; +} + +.error button { + margin-top: 40rpx; + background-color: #1677ff; + color: #fff; + border: none; + padding: 20rpx 80rpx; + border-radius: 60rpx; + font-size: 28rpx; + font-weight: bold; +} + +/* 订单内容 */ +.order-content { + background-color: #fff; + border-radius: 12rpx; + padding: 30rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); +} + +/* 订单头部 */ +.order-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 30rpx; + padding-bottom: 30rpx; + border-bottom: 1rpx solid #f0f0f0; +} + +.order-no { + font-size: 28rpx; + color: #333; + font-weight: bold; +} + +.order-date { + font-size: 26rpx; + color: #999; +} + +/* 区块样式 */ +.section { + margin-bottom: 30rpx; +} + +.section-title { + font-size: 30rpx; + color: #333; + font-weight: bold; + margin-bottom: 20rpx; + padding-left: 20rpx; + border-left: 6rpx solid #1677ff; +} + +/* 客户信息 */ +.customer-info { + background-color: #f9f9f9; + border-radius: 8rpx; + padding: 20rpx; +} + +/* 订单摘要 */ +.order-summary { + background-color: #f9f9f9; + border-radius: 8rpx; + padding: 20rpx; +} + +/* 信息项 */ +.info-item { + display: flex; + margin-bottom: 16rpx; + align-items: flex-start; +} + +.info-item:last-child { + margin-bottom: 0; +} + +.label { + width: 140rpx; + font-size: 26rpx; + color: #666; + font-weight: bold; + flex-shrink: 0; +} + +.value { + flex: 1; + font-size: 26rpx; + color: #333; + word-break: break-all; + line-height: 1.4; +} + +/* 总金额样式 */ +.total-amount { + font-size: 28rpx; + color: #ff4d4f; + font-weight: bold; +} + +/* 状态样式 */ +.payment-status { + color: #52c41a; + font-weight: bold; +} + +.order-status { + color: #1677ff; + font-weight: bold; +} + +/* 产品列表 */ +.products-list { + background-color: #f9f9f9; + border-radius: 8rpx; + padding: 20rpx; +} + +/* 产品项 */ +.product-item { + background-color: #fff; + border-radius: 8rpx; + padding: 20rpx; + margin-bottom: 16rpx; + box-shadow: 0 1rpx 4rpx rgba(0, 0, 0, 0.05); +} + +.product-item:last-child { + margin-bottom: 0; +} + +/* 产品头部 */ +.product-header { + margin-bottom: 16rpx; + padding-bottom: 16rpx; + border-bottom: 1rpx solid #f0f0f0; +} + +.product-name { + font-size: 28rpx; + color: #333; + font-weight: bold; +} + +/* 产品详情 */ +.product-details { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 16rpx; +} + +@media (max-width: 375px) { + .product-details { + grid-template-columns: 1fr; + } +} + +/* 无数据提示 */ +.no-data { + display: flex; + justify-content: center; + align-items: center; + padding: 120rpx 0; + background-color: #fff; + border-radius: 12rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + font-size: 32rpx; + color: #999; +} diff --git a/pages/order/index.js b/pages/order/index.js index bc7e551..c2897d7 100644 --- a/pages/order/index.js +++ b/pages/order/index.js @@ -20,38 +20,210 @@ Page({ data: { userInfo: {}, - orders: [] + orders: [], + loading: false, + error: '', + // 订单状态标签 + activeTab: 'all', + // 时间筛选相关 + dateRange: { + start: '', + end: '' + }, + // 分页相关 + page: 1, + pageSize: 10, + hasMore: true, + loadingMore: false }, onLoad() { // 页面加载时的初始化逻辑 - this.loadUserInfo(); + this.loadUserInfo(() => { + this.loadOrders(); + }); }, onShow() { // 页面显示时的逻辑 - this.loadUserInfo(); - // 更新自定义tabBar状态 - if (typeof this.getTabBar === 'function' && this.getTabBar()) { - this.getTabBar().setData({ - selected: 4 // 保持与个人中心相同的选中状态 - }); - } + this.loadUserInfo(() => { + this.loadOrders(); + // 更新自定义tabBar状态 + if (typeof this.getTabBar === 'function' && this.getTabBar()) { + this.getTabBar().setData({ + selected: 4 // 保持与个人中心相同的选中状态 + }); + } + }); }, // 加载用户信息 - loadUserInfo() { + loadUserInfo(callback) { const app = getApp(); + let userInfo = {}; + if (app.globalData.userInfo) { - this.setData({ userInfo: app.globalData.userInfo }); + userInfo = app.globalData.userInfo; } else { - const localUserInfo = wx.getStorageSync('userInfo') || {}; - this.setData({ userInfo: localUserInfo }); + userInfo = wx.getStorageSync('userInfo') || {}; } + + // 同步更新用户信息,确保loadOrders能获取到最新数据 + this.data.userInfo = userInfo; + + // 同时异步更新UI + this.setData({ userInfo: userInfo }, () => { + if (callback) callback(); + }); + }, + + // 加载订单数据 + loadOrders(isLoadMore = false, activeTab = this.data.activeTab) { + const userInfo = this.data.userInfo; + const phoneNumber = userInfo.phoneNumber; + + if (!phoneNumber) { + this.setData({ + error: '请先登录并绑定电话号码', + orders: [] + }); + return; + } + + if (isLoadMore) { + this.setData({ loadingMore: true }); + } else { + this.setData({ loading: true, error: '' }); + } + + const page = isLoadMore ? this.data.page + 1 : 1; + const pageSize = this.data.pageSize; + + // 根据标签确定付款状态 + let paymentStatus = ''; + if (activeTab === 'unpaid') { + paymentStatus = '未收款'; + } else if (activeTab === 'completed') { + paymentStatus = '全款'; + } + + console.log('loadOrders - activeTab:', activeTab, 'paymentStatus:', paymentStatus, 'page:', page); + + wx.request({ + url: 'http://localhost:3003/api/orders/list', + method: 'POST', + header: { + 'Content-Type': 'application/json' + }, + data: { + phoneNumber: phoneNumber, + startDate: this.data.dateRange.start, + endDate: this.data.dateRange.end, + paymentStatus: paymentStatus, + page: page, + pageSize: pageSize + }, + success: (res) => { + console.log('获取订单列表成功:', res.data); + if (res.data.success) { + const newOrders = res.data.data.orders || []; + const totalOrders = isLoadMore ? [...this.data.orders, ...newOrders] : newOrders; + const hasMore = newOrders.length === pageSize; + + this.setData({ + orders: totalOrders, + page: page, + hasMore: hasMore, + loading: false, + loadingMore: false + }); + } else { + this.setData({ + error: res.data.message || '获取订单失败', + loading: false, + loadingMore: false + }); + } + }, + fail: (err) => { + console.error('获取订单列表失败:', err); + this.setData({ + error: '网络请求失败,请稍后重试', + loading: false, + loadingMore: false + }); + } + }); }, // 返回上一页 goBack() { wx.navigateBack(); + }, + + // 查看订单详情 + viewOrderDetail(e) { + const orderId = e.currentTarget.dataset.orderId; + wx.navigateTo({ + url: `/pages/order/detail/index?orderId=${orderId}` + }); + }, + + // 去首页购物 + goToHome() { + wx.switchTab({ + url: '/pages/index/index' + }); + }, + + // 选择开始日期 + bindStartDateChange(e) { + const startDate = e.detail.value; + this.setData({ + 'dateRange.start': startDate + }); + }, + + // 选择结束日期 + bindEndDateChange(e) { + const endDate = e.detail.value; + this.setData({ + 'dateRange.end': endDate + }); + }, + + // 重置日期筛选 + resetDateFilter() { + this.setData({ + 'dateRange.start': '', + 'dateRange.end': '' + }); + this.loadOrders(); + }, + + // 应用日期筛选 + applyDateFilter() { + this.loadOrders(); + }, + + // 切换订单状态标签 + switchTab(e) { + const tab = e.currentTarget.dataset.tab; + console.log('switchTab - tab:', tab); + this.setData({ + activeTab: tab, + page: 1, + orders: [] + }, () => { + console.log('switchTab - after setData, activeTab:', this.data.activeTab); + this.loadOrders(false, tab); + }); + }, + + // 滚动到底部的预加载逻辑 + onReachBottom() { + if (!this.data.loadingMore && this.data.hasMore) { + this.loadOrders(true, this.data.activeTab); + } } }) diff --git a/pages/order/index.wxml b/pages/order/index.wxml index 73b2a92..f8d81e2 100644 --- a/pages/order/index.wxml +++ b/pages/order/index.wxml @@ -1,21 +1,98 @@ - 全部 - 待付款 - 待发货 - 待收货 - 已完成 + 全部 + 待付款 + 已完成 + + + + + + + 开始日期: + + + {{dateRange.start || '请选择'}} + + + + + 结束日期: + + + {{dateRange.end || '请选择'}} + + + + + + + + - - + + + 加载中... + + + + + {{error}} + + + + 📦 空空如也~ 您还没有任何订单,快去选购吧 + + + + + + + 订单号: {{item.sales_no}} + {{item.order_date}} + + + + + + {{item.customer_company}} + {{item.contact_person}} {{item.phone}} + + + 总金额: ¥{{item.total_amount}} + 总件数: {{item.total_pieces}} + 总斤数: {{item.total_weight}} + + + + + + + {{item.payment_status}} + {{item.order_status}} + + + + + + + + + 加载中... + + + 没有更多数据了 + + + diff --git a/pages/order/index.wxss b/pages/order/index.wxss index f357f79..cd49fe6 100644 --- a/pages/order/index.wxss +++ b/pages/order/index.wxss @@ -9,23 +9,25 @@ display: flex; background-color: #fff; border-bottom: 1rpx solid #e0e0e0; - overflow-x: auto; - white-space: nowrap; } .tab-item { flex: 1; - min-width: 160rpx; text-align: center; - padding: 24rpx 0; - font-size: 32rpx; + padding: 20rpx 0; + font-size: 28rpx; color: #666; position: relative; + transition: all 0.2s ease; +} + +.tab-item:hover { + color: #1677ff; } .tab-item.active { color: #1677ff; - font-weight: bold; + font-weight: 500; } .tab-item.active::after { @@ -34,10 +36,117 @@ bottom: 0; left: 50%; transform: translateX(-50%); - width: 60rpx; - height: 6rpx; + width: 50rpx; + height: 5rpx; background-color: #1677ff; border-radius: 3rpx; + transition: all 0.2s ease; +} + + +/* 时间筛选组件 */ +.date-filter { + background-color: #fff; + padding: 16rpx; + margin: 8rpx; + border-radius: 10rpx; + box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04); +} + +.date-filter-row { + display: flex; + justify-content: space-between; + margin-bottom: 16rpx; + gap: 12rpx; +} + +.date-picker { + flex: 1; + display: flex; + flex-direction: column; +} + +.date-label { + font-size: 22rpx; + color: #666; + margin-bottom: 6rpx; + font-weight: 500; +} + +.picker { + border: 1rpx solid #e8e8e8; + border-radius: 6rpx; + padding: 14rpx; + font-size: 22rpx; + color: #333; + background-color: #f9f9f9; + transition: all 0.2s ease; +} + +.picker:hover { + border-color: #1677ff; + background-color: #f0f7ff; +} + +.filter-actions { + display: flex; + justify-content: flex-end; + gap: 12rpx; + padding-top: 12rpx; + border-top: 1rpx solid #f5f5f5; +} + +.reset-btn { + padding: 12rpx 32rpx; + border-radius: 24rpx; + font-size: 22rpx; + border: 1rpx solid #d9d9d9; + color: #666; + background-color: #f9f9f9; + transition: all 0.2s ease; +} + +.reset-btn:hover { + border-color: #999; + background-color: #f0f0f0; +} + +.apply-btn { + padding: 12rpx 32rpx; + border-radius: 24rpx; + font-size: 22rpx; + border: 1rpx solid #1677ff; + color: #1677ff; + background-color: #fff; + font-weight: 500; + transition: all 0.2s ease; +} + +.apply-btn:hover { + background-color: #1677ff; + color: #fff; +} + +/* 响应式设计 */ +@media (max-width: 375px) { + .date-filter-row { + flex-direction: column; + } + + .date-picker { + flex-direction: row; + align-items: center; + } + + .date-label { + margin-bottom: 0; + margin-right: 10rpx; + min-width: 120rpx; + } + + .picker { + flex: 1; + } } /* 订单列表 */ @@ -45,6 +154,33 @@ padding: 20rpx; } +/* 加载中 */ +.loading { + display: flex; + justify-content: center; + align-items: center; + padding: 120rpx 0; + background-color: #fff; + border-radius: 12rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + font-size: 32rpx; + color: #666; +} + +/* 错误提示 */ +.error { + display: flex; + justify-content: center; + align-items: center; + padding: 120rpx 40rpx; + background-color: #fff; + border-radius: 12rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + font-size: 32rpx; + color: #ff4d4f; + text-align: center; +} + /* 暂无订单提示 */ .no-orders { display: flex; @@ -85,13 +221,19 @@ font-weight: bold; } -/* 订单卡片样式(预留) */ +/* 订单卡片样式 */ .order-card { background-color: #fff; border-radius: 12rpx; padding: 30rpx; margin-bottom: 20rpx; box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.order-card:active { + transform: translateY(2rpx); + box-shadow: 0 1rpx 5rpx rgba(0, 0, 0, 0.05); } .order-header { @@ -103,60 +245,75 @@ border-bottom: 1rpx solid #f0f0f0; } -.order-info { +.order-no { font-size: 28rpx; - color: #666; + color: #333; + font-weight: bold; } -.order-status { - font-size: 28rpx; - color: #1677ff; - font-weight: bold; +.order-date { + font-size: 26rpx; + color: #999; } -.order-goods { +.order-body { margin-bottom: 20rpx; } -.goods-item { - display: flex; +.customer-info { margin-bottom: 20rpx; } -.goods-image { - width: 120rpx; - height: 120rpx; - border-radius: 8rpx; - margin-right: 20rpx; +.customer-company { + font-size: 30rpx; + color: #333; + font-weight: bold; + margin-bottom: 10rpx; } -.goods-info { - flex: 1; +.contact-person { + font-size: 26rpx; + color: #666; +} + +.order-summary { display: flex; - flex-direction: column; - justify-content: space-between; + flex-wrap: wrap; + gap: 30rpx; + padding: 20rpx; + background-color: #f9f9f9; + border-radius: 8rpx; } -.goods-name { - font-size: 32rpx; +.total-amount { + font-size: 28rpx; color: #333; - margin-bottom: 10rpx; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; + font-weight: bold; } -.goods-spec { - font-size: 26rpx; - color: #999; - margin-bottom: 10rpx; +.total-amount::before { + content: "💰 "; + font-size: 24rpx; } -.goods-price { - font-size: 32rpx; - color: #ff4d4f; - font-weight: bold; +.total-pieces { + font-size: 28rpx; + color: #666; +} + +.total-pieces::before { + content: "📦 "; + font-size: 24rpx; +} + +.total-weight { + font-size: 28rpx; + color: #666; +} + +.total-weight::before { + content: "⚖️ "; + font-size: 24rpx; } .order-footer { @@ -167,31 +324,61 @@ border-top: 1rpx solid #f0f0f0; } -.total-price { - font-size: 32rpx; - color: #333; +.status-container { + display: flex; + gap: 20rpx; + align-items: center; } -.total-price .price { - color: #ff4d4f; +.payment-status { + font-size: 26rpx; + color: #52c41a; font-weight: bold; + padding: 6rpx 16rpx; + background-color: #f6ffed; + border-radius: 20rpx; + border: 1rpx solid #b7eb8f; } -.order-actions { +.order-status { + font-size: 26rpx; + color: #1677ff; + font-weight: bold; + padding: 6rpx 16rpx; + background-color: #e6f7ff; + border-radius: 20rpx; + border: 1rpx solid #91d5ff; +} + +.arrow-icon { + font-size: 32rpx; + color: #999; + font-weight: bold; +} + +/* 分页加载相关样式 */ +.load-more { + padding: 30rpx 0; + text-align: center; +} + +.loading-more { display: flex; + justify-content: center; + align-items: center; + padding: 20rpx 0; } -.action-btn { - padding: 12rpx 30rpx; - border-radius: 40rpx; +.loading-more text { font-size: 28rpx; - margin-left: 20rpx; - border: 2rpx solid #1677ff; - color: #1677ff; - background-color: #fff; + color: #666; } -.action-btn.primary { - background-color: #1677ff; - color: #fff; +.no-more { + padding: 20rpx 0; +} + +.no-more text { + font-size: 26rpx; + color: #999; } diff --git a/project.private.config.json b/project.private.config.json index 67dfd8e..3d49d96 100644 --- a/project.private.config.json +++ b/project.private.config.json @@ -19,5 +19,17 @@ "ignoreDevUnusedFiles": true, "bigPackageSizeSupport": false }, - "condition": {} + "condition": { + "miniprogram": { + "list": [ + { + "name": "pages/test-tools/order-test", + "pathName": "pages/test-tools/order-test", + "query": "", + "scene": null, + "launchMode": "default" + } + ] + } + } } \ No newline at end of file diff --git a/server-example/server-mysql.js b/server-example/server-mysql.js index 61ecd3e..c224f1b 100644 --- a/server-example/server-mysql.js +++ b/server-example/server-mysql.js @@ -399,6 +399,29 @@ const userLoginSequelize = new Sequelize( } ); +// 3. trade_library数据源连接(新添加) +const tradeLibrarySequelize = new Sequelize( + 'trade_library', + dbConfig.user, + dbConfig.password, + { + host: dbConfig.host, + port: dbConfig.port, + dialect: 'mysql', + pool: { + max: 10, + min: 0, + acquire: 30000, + idle: 10000 + }, + logging: console.log, + define: { + timestamps: false + }, + timezone: '+08:00' // 设置时区为UTC+8 + } +); + // 为保持兼容性,保留默认sequelize引用(指向wechat_app) const sequelize = wechatAppSequelize; @@ -1296,8 +1319,239 @@ Cover.init({ timestamps: false }); +// 简道云销售订单主表模型(新添加) +class JdSalesMain extends Model { } +JdSalesMain.init({ + dataid: { + type: DataTypes.STRING(50), + primaryKey: true, + allowNull: false, + comment: '主表自增主键(简道云插件关联用)' + }, + sales_no: { + type: DataTypes.STRING(50), + allowNull: false, + unique: true, + comment: '销售单号(业务唯一编号)' + }, + order_date: { + type: DataTypes.DATEONLY, + allowNull: false, + comment: '下单日期' + }, + customer_company: { + type: DataTypes.STRING(200), + allowNull: false, + comment: '客户公司' + }, + contact_person: { + type: DataTypes.STRING(100), + allowNull: false, + comment: '联系人' + }, + phone: { + type: DataTypes.STRING(20), + allowNull: true, + comment: '联系电话(允许带区号等特殊字符,用字符串存储)' + }, + salesman: { + type: DataTypes.STRING(100), + allowNull: true, + comment: '销售员' + }, + merchandiser: { + type: DataTypes.STRING(100), + allowNull: true, + comment: '跟单员' + }, + address: { + type: DataTypes.STRING(500), + allowNull: true, + comment: '地址' + }, + total_pieces: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + comment: '总件数' + }, + total_weight: { + type: DataTypes.DECIMAL(10, 3), + allowNull: false, + defaultValue: 0.000, + comment: '总斤数(保留3位小数)' + }, + total_amount: { + type: DataTypes.DECIMAL(12, 2), + allowNull: false, + defaultValue: 0.00, + comment: '总金额(保留2位小数)' + }, + vehicle_scale: { + type: DataTypes.STRING(100), + allowNull: true, + comment: '车辆规模' + }, + payment_voucher: { + type: DataTypes.STRING(255), + allowNull: true, + comment: '支付凭证(存储照片路径)' + }, + invoice: { + type: DataTypes.STRING(255), + allowNull: true, + comment: '发票(存储照片路径)' + }, + payment_status: { + type: DataTypes.STRING(50), + allowNull: true, + comment: '付款状态(如:未付款/部分付款/已付清)' + }, + order_status: { + type: DataTypes.STRING(50), + allowNull: true + }, + chepai: { + type: DataTypes.STRING(255), + allowNull: true, + comment: '车牌' + } +}, { + sequelize: tradeLibrarySequelize, + modelName: 'JdSalesMain', + tableName: 'jd_sales_main', + timestamps: false, + indexes: [ + { + unique: true, + fields: ['sales_no'], + name: 'idx_sales_no', + comment: '销售单号唯一索引(避免重复)' + } + ] +}); + +// 简道云销售订单明细表模型(新添加) +class JdSalesSub extends Model { } +JdSalesSub.init({ + sub_id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + comment: '子表自增主键' + }, + dataid: { + type: DataTypes.STRING(50), + allowNull: false, + comment: '关联主表dataid' + }, + product_name: { + type: DataTypes.STRING(200), + allowNull: false, + comment: '产品名称' + }, + batch_no: { + type: DataTypes.STRING(100), + allowNull: true, + comment: '批次号' + }, + unit: { + type: DataTypes.STRING(50), + allowNull: true, + comment: '单位(件,斤)' + }, + yolk: { + type: DataTypes.STRING(50), + allowNull: true, + comment: '蛋黄(描述信息)' + }, + specification: { + type: DataTypes.STRING(100), + allowNull: true, + comment: '规格' + }, + sales_pieces: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + comment: '销售件数' + }, + sales_weight: { + type: DataTypes.DECIMAL(10, 3), + allowNull: false, + defaultValue: 0.000, + comment: '销售斤数(保留3位小数)' + }, + unit_price: { + type: DataTypes.DECIMAL(10, 2), + allowNull: false, + defaultValue: 0.00, + comment: '单价(保留2位小数)' + }, + purchase_price: { + type: DataTypes.DECIMAL(10, 2), + allowNull: true, + comment: '采购价(保留2位小数)' + }, + sales_amount: { + type: DataTypes.DECIMAL(12, 2), + allowNull: false, + defaultValue: 0.00, + comment: '销售金额' + }, + discount_amount: { + type: DataTypes.DECIMAL(10, 2), + allowNull: true, + defaultValue: 0.00, + comment: '优惠金额' + }, + rebate_amount: { + type: DataTypes.DECIMAL(10, 2), + allowNull: true, + defaultValue: 0.00, + comment: '折扣金额' + }, + purchase_amount: { + type: DataTypes.DECIMAL(12, 2), + allowNull: true, + comment: '采购金额' + }, + discount_reason: { + type: DataTypes.STRING(500), + allowNull: true, + comment: '优惠原因' + } +}, { + sequelize: tradeLibrarySequelize, + modelName: 'JdSalesSub', + tableName: 'jd_sales_sub', + timestamps: false, + indexes: [ + { + fields: ['dataid'], + name: 'idx_main_id', + comment: '关联主表索引(加速查询)' + } + ] +}); + // 定义模型之间的关联关系 +// 简道云销售订单主表和明细表的关联关系 +JdSalesMain.hasMany(JdSalesSub, { + foreignKey: 'dataid', + sourceKey: 'dataid', + as: 'subItems', + onDelete: 'CASCADE', + onUpdate: 'CASCADE' +}); + +JdSalesSub.belongsTo(JdSalesMain, { + foreignKey: 'dataid', + targetKey: 'dataid', + as: 'mainOrder' +}); + // 用户和商品的一对多关系 (卖家发布商品) User.hasMany(Product, { foreignKey: 'sellerId', // 外键字段名 @@ -9871,13 +10125,239 @@ updateProductContacts().then(() => { }); }); +// 订单查询API端点 - 根据登录用户的电话号码查询订单信息 +app.post('/api/orders/list', async (req, res) => { + try { + const { phoneNumber, startDate, endDate, paymentStatus, page = 1, pageSize = 10 } = req.body; + console.log('获取订单列表请求:', { phoneNumber, startDate, endDate, paymentStatus, page, pageSize }); + console.log('请求体完整内容:', req.body); + + if (!phoneNumber) { + return res.status(400).json({ + success: false, + code: 400, + message: '用户电话号码不能为空' + }); + } + + // 构建查询条件 + const whereCondition = { + phone: phoneNumber + }; + + // 添加时间范围过滤 + if (startDate) { + whereCondition.order_date = { + ...whereCondition.order_date, + [Op.gte]: startDate + }; + console.log('添加开始日期过滤:', startDate); + } + + if (endDate) { + whereCondition.order_date = { + ...whereCondition.order_date, + [Op.lte]: endDate + }; + console.log('添加结束日期过滤:', endDate); + } + + // 添加付款状态过滤 + if (paymentStatus) { + whereCondition.payment_status = paymentStatus; + console.log('添加付款状态过滤:', paymentStatus); + } + + console.log('最终查询条件:', whereCondition); + + // 计算分页偏移量 + const offset = (page - 1) * pageSize; + console.log('分页参数:', { page, pageSize, offset }); + + // 查询trade_library数据库中的订单主表,根据电话号码和时间范围过滤 + const orders = await JdSalesMain.findAll({ + where: whereCondition, + include: [ + { + model: JdSalesSub, + as: 'subItems', + attributes: [ + 'sub_id', + 'product_name', + 'batch_no', + 'unit', + 'yolk', + 'specification', + 'sales_pieces', + 'sales_weight', + 'unit_price', + 'sales_amount', + 'discount_amount', + 'rebate_amount', + 'discount_reason' + ] + } + ], + order: [['order_date', 'DESC']], + limit: pageSize, + offset: offset + }); + + console.log('查询到的订单数量:', orders.length); + + // 格式化响应数据 + const formattedOrders = orders.map(order => { + const orderData = order.toJSON(); + + // 确保order_date是字符串格式 + if (orderData.order_date instanceof Date) { + orderData.order_date = orderData.order_date.toISOString().split('T')[0]; + } + + // 确保数值字段正确格式化 + orderData.total_pieces = parseInt(orderData.total_pieces) || 0; + orderData.total_weight = parseFloat(orderData.total_weight) || 0; + orderData.total_amount = parseFloat(orderData.total_amount) || 0; + + // 格式化子项数据 + if (orderData.subItems) { + orderData.subItems = orderData.subItems.map(subItem => ({ + ...subItem, + sales_pieces: parseInt(subItem.sales_pieces) || 0, + sales_weight: parseFloat(subItem.sales_weight) || 0, + unit_price: parseFloat(subItem.unit_price) || 0, + sales_amount: parseFloat(subItem.sales_amount) || 0, + discount_amount: parseFloat(subItem.discount_amount) || 0, + rebate_amount: parseFloat(subItem.rebate_amount) || 0 + })); + } + + return orderData; + }); + + res.status(200).json({ + success: true, + code: 200, + message: '获取订单列表成功', + data: { + orders: formattedOrders, + totalCount: formattedOrders.length + } + }); + + } catch (error) { + console.error('获取订单列表失败:', error); + res.status(500).json({ + success: false, + code: 500, + message: '获取订单列表失败: ' + error.message + }); + } +}); + +// 订单详情API端点 - 根据订单ID查询订单详情 +app.get('/api/orders/detail/:dataid', async (req, res) => { + try { + const { dataid } = req.params; + console.log('获取订单详情请求:', { dataid }); + + if (!dataid) { + return res.status(400).json({ + success: false, + code: 400, + message: '订单ID不能为空' + }); + } + + // 查询订单详情 + const order = await JdSalesMain.findOne({ + where: { + dataid + }, + include: [ + { + model: JdSalesSub, + as: 'subItems', + attributes: [ + 'sub_id', + 'product_name', + 'batch_no', + 'unit', + 'yolk', + 'specification', + 'sales_pieces', + 'sales_weight', + 'unit_price', + 'sales_amount', + 'discount_amount', + 'rebate_amount', + 'discount_reason' + ] + } + ] + }); + + if (!order) { + return res.status(404).json({ + success: false, + code: 404, + message: '订单不存在' + }); + } + + // 格式化响应数据 + const orderData = order.toJSON(); + + // 确保order_date是字符串格式 + if (orderData.order_date instanceof Date) { + orderData.order_date = orderData.order_date.toISOString().split('T')[0]; + } + + // 确保数值字段正确格式化 + orderData.total_pieces = parseInt(orderData.total_pieces) || 0; + orderData.total_weight = parseFloat(orderData.total_weight) || 0; + orderData.total_amount = parseFloat(orderData.total_amount) || 0; + + // 格式化子项数据 + if (orderData.subItems) { + orderData.subItems = orderData.subItems.map(subItem => ({ + ...subItem, + sales_pieces: parseInt(subItem.sales_pieces) || 0, + sales_weight: parseFloat(subItem.sales_weight) || 0, + unit_price: parseFloat(subItem.unit_price) || 0, + sales_amount: parseFloat(subItem.sales_amount) || 0, + discount_amount: parseFloat(subItem.discount_amount) || 0, + rebate_amount: parseFloat(subItem.rebate_amount) || 0 + })); + } + + res.status(200).json({ + success: true, + code: 200, + message: '获取订单详情成功', + data: orderData + }); + + } catch (error) { + console.error('获取订单详情失败:', error); + res.status(500).json({ + success: false, + code: 500, + message: '获取订单详情失败: ' + error.message + }); + } +}); + // 导出模型和Express应用供其他模块使用 module.exports = { User, Product, CartItem, Resources, + JdSalesMain, + JdSalesSub, sequelize, + tradeLibrarySequelize, createUserAssociations, app, PORT