diff --git a/manifest.json b/manifest.json index a00f5eb..1db2efb 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { "name" : "香水有毒", - "appid" : "", + "appid" : "__UNI__E8ED88D", "description" : "", "versionName" : "1.0.0", "versionCode" : "100", diff --git a/pages.json b/pages.json index 352f417..c8bb6b5 100644 --- a/pages.json +++ b/pages.json @@ -48,6 +48,42 @@ "style": { "navigationBarTitleText": "用户登录" } + }, + { + "path": "pages/shoppingCart/index", + "style": { + "navigationBarTitleText": "购物车" + } + }, + { + "path": "pages/shopDetail/index", + "style": { + "navigationBarTitleText": "商品详情" + } + }, + { + "path": "pages/order/create", + "style": { + "navigationBarTitleText": "确认订单" + } + }, + { + "path": "pages/order/index", + "style": { + "navigationBarTitleText": "我的订单" + } + }, + { + "path": "pages/order/detail", + "style": { + "navigationBarTitleText": "订单详情" + } + }, + { + "path": "pages/pointsLog/index", + "style": { + "navigationBarTitleText": "积分流水" + } } ], "globalStyle": { diff --git a/pages/index/index.vue b/pages/index/index.vue index e6486c4..c8570c9 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -54,7 +54,7 @@ - + @@ -76,25 +76,26 @@ --> - {{item.name}} + {{ item.name }} - {{item.description}} + {{ item.description }} - {{item.rating}} + {{ item.rating }} (156条评价) - {{item.like_count}} 人喜欢 + {{ item.like_count }} 人喜欢 - - ¥{{ item.skus[0].price }} - ¥{{ item.skus[0].original_price }} + + ¥{{ formatPrice(item.skus[0].price) }} + ¥{{ formatPrice(item.skus[0].original_price) }} - + - {{item.like_count}} + + {{ item.like_count }} @@ -230,8 +231,17 @@ export default { this.getShopList() }, methods: { - - getShopList(){ + // 格式化价格 + formatPrice(value) { + if (!value) { + return 0.00; + } + // 分转换为元 + value = value / 100; + // 保留两位小数 + return value.toFixed(2); + }, + getShopList() { request('xcx/products', 'get', { page: this.page, page_size: this.page_size @@ -239,9 +249,9 @@ export default { this.shopList = res.list }) }, - async userIsLogin(){ + async userIsLogin() { const token = await uni.getStorageSync('access_token') - if(token){ + if (token) { return } else { uni.navigateTo({ @@ -270,7 +280,13 @@ export default { } }) }) - + + }, + async goShopDetail(item) { + await uni.setStorageSync('product_info', item) + uni.navigateTo({ + url: `/pages/shopDetail/index?id=${item.id}` + }) } } } diff --git a/pages/login/index.vue b/pages/login/index.vue index cb569f3..552d76b 100644 --- a/pages/login/index.vue +++ b/pages/login/index.vue @@ -54,24 +54,27 @@ export default { if (!loginRes.code) { throw new Error('获取微信登录code失败'); } + + const open_id = (await request('xcx/basic_login', 'post', {code: loginRes.code})).openid // 调用登录接口,传递code和加密数据 const loginData = { code: e.detail.code, - invitation_code: e.detail.encryptedData, + invitation_code: '', + openid: open_id // iv: e.detail.iv }; const result = await request('xcx/quick_login', 'POST', loginData); await wx.setStorageSync('access_token', result.token); await wx.setStorageSync('is_personal_information_complete', result.is_personal_information_complete); - if (result.is_personal_information_complete) { + // if (result.is_personal_information_complete) { wx.navigateBack(); - } else { - wx.navigateTo({ - url: `/pages/my/editInfo/index`, - }); - } + // } else { + // wx.navigateTo({ + // url: `/pages/my/editInfo/index`, + // }); + // } // 保存token // if (result.token) { // wx.setStorageSync('access_token', result.token); diff --git a/pages/my/index.vue b/pages/my/index.vue index ba5071a..0e1baef 100644 --- a/pages/my/index.vue +++ b/pages/my/index.vue @@ -25,7 +25,8 @@ 编辑资料 - + {{ item.icon }} {{ item.value }} {{ item.label }} @@ -96,7 +97,7 @@ 我的订单 - 查看全部 + 查看全部 @@ -127,6 +128,10 @@ + + 📦 + 暂无订单 + @@ -370,6 +375,7 @@ export default { } else { this.loadProfile(); this.loadSignInfo(); + this.loadOrders(); } }, methods: { @@ -386,16 +392,117 @@ export default { console.warn('加载个人信息失败', error); } }, + loadOrders() { + try { + request('xcx/orders', 'GET', { + page: 1, + page_size: 3 + }).then(res => { + // 处理返回数据 + let orderList = []; + if (Array.isArray(res)) { + orderList = res; + } else if (res.list && Array.isArray(res.list)) { + orderList = res.list; + } else if (res.data && Array.isArray(res.data)) { + orderList = res.data; + } + + // 只取前三条 + orderList = orderList.slice(0, 3); + + // 转换为页面需要的格式 + this.orders = orderList.map(order => { + // 获取第一个商品信息 + const firstItem = (order.items && order.items.length > 0) ? order.items[0] : order; + + // 格式化状态 + const statusMap = { + 'pending': { text: '待付款', class: 'pending' }, + 'paid': { text: '待发货', class: 'warning' }, + 'shipped': { text: '待收货', class: 'warning' }, + 'completed': { text: '已完成', class: 'success' }, + 'cancelled': { text: '已取消', class: 'cancelled' }, + 'refunded': { text: '已退款', class: 'cancelled' } + }; + const statusInfo = statusMap[order.status] || { text: order.status || '未知', class: '' }; + + // 格式化价格 + const formatPrice = (price) => { + if (!price && price !== 0) return '0.00'; + if (price < 1000) return parseFloat(price).toFixed(2); + return (price / 100).toFixed(2); + }; + + // 格式化日期 + const formatDate = (dateStr) => { + if (!dateStr) return ''; + const date = new Date(dateStr); + const year = date.getFullYear(); + const month = this.padZero(date.getMonth() + 1); + const day = this.padZero(date.getDate()); + return `${year}-${month}-${day}`; + }; + + // 获取操作按钮 + const getActions = (status) => { + if (status === 'pending') { + return [{ label: '查看详情' }, { label: '立即付款' }]; + } else if (status === 'shipped') { + return [{ label: '查看详情' }, { label: '确认收货' }]; + } else if (status === 'completed') { + return [{ label: '查看详情' }, { label: '再次购买' }]; + } + return [{ label: '查看详情' }]; + }; + + return { + no: order.order_no || order.no || order.id, + type: order.order_type || '普通订单', + status: statusInfo.text, + statusClass: statusInfo.class, + date: formatDate(order.created_at || order.date), + product: firstItem.product_name || firstItem.name || order.product_name || '商品', + spec: firstItem.sku_name || firstItem.spec || `¥${formatPrice(firstItem.price || order.price)} × ${firstItem.quantity || order.quantity || 1}`, + amount: `¥${formatPrice(order.final_price || order.total_price || order.amount)}`, + actions: getActions(order.status) + }; + }); + }).catch(error => { + console.warn('加载订单列表失败', error); + // 失败时保持默认数据或清空 + this.orders = []; + }); + } catch (error) { + console.warn('获取订单列表异常', error); + this.orders = []; + } + }, loadSignInfo() { try { - return request('xcx/sign_in', 'GET').then(res => { + return request('xcx/user_checkins', 'GET', { + time_month: this.getMonthLabel() + }).then(res => { const info = res || {}; - const monthLabel = info.current_month || this.getMonthLabel(); - const calendar = this.buildMonthlyCalendar(info.month_records || info.recent_records, monthLabel); + // 处理签到列表,提取日期 + const checkinList = info.list || []; + const monthLabel = this.getMonthLabel(); + + // 判断今天是否已签到 + const today = new Date(); + const todayStr = `${today.getFullYear()}-${this.padZero(today.getMonth() + 1)}-${this.padZero(today.getDate())}`; + const signedToday = checkinList.some(item => { + if (!item.checkin_time) return false; + // 从 "2025-11-23 14:51:27" 提取日期部分 "2025-11-23" + const dateStr = item.checkin_time.split(' ')[0]; + return dateStr === todayStr; + }); + + const calendar = this.buildMonthlyCalendar(checkinList, monthLabel); this.signCalendar = calendar; const updatedSignInfo = { ...this.signInfo, - signedToday: !!info.signed_today, + signedToday, continuousDays: info.continuous_days || 0, totalPoints: info.total_points || 0, todayReward: info.today_reward || 0, @@ -416,6 +523,7 @@ export default { this.signCalendar = this.buildMonthlyCalendar(); this.signInfo = { ...this.signInfo, + signedToday: false, monthLabel: this.getMonthLabel(), monthSignedDays: 0 }; @@ -425,6 +533,7 @@ export default { this.signCalendar = this.buildMonthlyCalendar(); this.signInfo = { ...this.signInfo, + signedToday: false, monthLabel: this.getMonthLabel(), monthSignedDays: 0 }; @@ -443,21 +552,22 @@ export default { const firstDay = new Date(year, month - 1, 1); const totalDays = new Date(year, month, 0).getDate(); const prefixDays = firstDay.getDay(); - const recordMap = {}; + + // 从签到列表中提取日期,构建日期映射表 + // list 格式: [{ checkin_time: "2025-11-23 14:51:27" }, ...] + const signedDates = new Set(); if (Array.isArray(list)) { list.forEach(item => { - const dateStr = item?.date || item?.day || item?.label; - if (dateStr) { - const status = - item?.checked ?? - item?.signed ?? - (typeof item?.status !== 'undefined' ? item.status === 1 : undefined) ?? - item?.is_signed ?? - false; - recordMap[dateStr] = !!status; + if (item.checkin_time) { + // 从 "2025-11-23 14:51:27" 提取日期部分 "2025-11-23" + const dateStr = item.checkin_time.split(' ')[0]; + if (dateStr && /^\d{4}-\d{2}-\d{2}$/.test(dateStr)) { + signedDates.add(dateStr); + } } }); } + const calendar = []; for (let i = 0; i < prefixDays; i++) { calendar.push({ label: '', isPlaceholder: true }); @@ -467,7 +577,7 @@ export default { const targetDate = new Date(year, month - 1, day); const isToday = this.isSameDate(targetDate, todayStart); const isFuture = targetDate.getTime() > todayStart.getTime(); - const signed = !!recordMap[dateStr]; + const signed = signedDates.has(dateStr); calendar.push({ label: day, date: dateStr, @@ -503,7 +613,7 @@ export default { } this.signLoading = true; try { - const res = await request('xcx/sign_in', 'POST'); + const res = await request('xcx/user_checkin', 'POST'); const rewardText = res?.message || '签到成功'; uni.showToast({ title: rewardText, @@ -584,6 +694,12 @@ export default { icon: 'none' }); }); + }, + handleStatCardClick(item) { + // 点击"当前积分"卡片时跳转到积分流水记录页面 + if (item.label === '当前积分') { + this.navigateTo('/pages/pointsLog/index'); + } } } }; @@ -1503,4 +1619,23 @@ export default { font-size: 24rpx; color: #4f5f7a; } + +.order-empty { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 80rpx 32rpx; + gap: 24rpx; +} + +.order-empty-icon { + font-size: 80rpx; + opacity: 0.5; +} + +.order-empty-text { + font-size: 28rpx; + color: #8c94a3; +} \ No newline at end of file diff --git a/pages/order/create.vue b/pages/order/create.vue new file mode 100644 index 0000000..903fe21 --- /dev/null +++ b/pages/order/create.vue @@ -0,0 +1,769 @@ + + + + + diff --git a/pages/order/detail.vue b/pages/order/detail.vue new file mode 100644 index 0000000..1d7e208 --- /dev/null +++ b/pages/order/detail.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/pages/order/index.vue b/pages/order/index.vue new file mode 100644 index 0000000..684d0c5 --- /dev/null +++ b/pages/order/index.vue @@ -0,0 +1,702 @@ + + + + + diff --git a/pages/pointsLog/index.vue b/pages/pointsLog/index.vue new file mode 100644 index 0000000..174a7d8 --- /dev/null +++ b/pages/pointsLog/index.vue @@ -0,0 +1,345 @@ + + + + + + diff --git a/pages/shopDetail/index.vue b/pages/shopDetail/index.vue new file mode 100644 index 0000000..50d84d1 --- /dev/null +++ b/pages/shopDetail/index.vue @@ -0,0 +1,1257 @@ + + + + + diff --git a/pages/shoppingCart/index.vue b/pages/shoppingCart/index.vue new file mode 100644 index 0000000..8b2e7c9 --- /dev/null +++ b/pages/shoppingCart/index.vue @@ -0,0 +1,559 @@ + + + + + \ No newline at end of file diff --git a/static/font/index.css b/static/font/index.css index 213fd81..03611e9 100644 --- a/static/font/index.css +++ b/static/font/index.css @@ -1,8 +1,8 @@ @font-face { font-family: "iconfont"; /* Project id 5057334 */ - src: url('//at.alicdn.com/t/c/font_5057334_7ak9qra77f.woff2?t=1763287992869') format('woff2'), - url('//at.alicdn.com/t/c/font_5057334_7ak9qra77f.woff?t=1763287992869') format('woff'), - url('//at.alicdn.com/t/c/font_5057334_7ak9qra77f.ttf?t=1763287992869') format('truetype'); + src: url('//at.alicdn.com/t/c/font_5057334_65098frmpc4.woff2?t=1763879647176') format('woff2'), + url('//at.alicdn.com/t/c/font_5057334_65098frmpc4.woff?t=1763879647176') format('woff'), + url('//at.alicdn.com/t/c/font_5057334_65098frmpc4.ttf?t=1763879647176') format('truetype'); } .iconfont { @@ -13,6 +13,22 @@ -moz-osx-font-smoothing: grayscale; } +.icon-gou:before { + content: "\e786"; +} + +.icon-zhengpinbaozhang:before { + content: "\e602"; +} + +.icon-wuliu:before { + content: "\e70d"; +} + +.icon-cangpeitubiao_shanchu:before { + content: "\e618"; +} + .icon-xin:before { content: "\e641"; }