From 2767b352366db925f8567d8e73783122aec873a9 Mon Sep 17 00:00:00 2001 From: "1054425342@qq.com" <1054425342@qq.com> Date: Wed, 13 Aug 2025 10:55:46 +0800 Subject: [PATCH] style --- README_AreaPicker.md | 253 ++++ common/index.js | 10 +- components/AreaPicker.vue | 429 ++++++ components/ProductSection.vue | 31 +- components/header.vue | 175 ++- manifest.json | 14 +- pages.json | 12 +- pages/index/iSoul.vue | 2155 ++++++++++++++-------------- pages/index/index.vue | 436 +++--- pages/index/timeShopBank.vue | 6 +- static/js/request.js | 35 +- subPackages/equityGoods/detail.vue | 336 +++-- subPackages/equityGoods/index.vue | 25 +- subPackages/equityGoods/list.vue | 1275 ++++++++-------- subPackages/orderQy/confrim.vue | 793 +++++++++- subPackages/orderQy/detail.vue | 123 +- subPackages/orderQy/list.vue | 135 +- subPackages/user/collection.vue | 408 ++++++ utils/request.js | 4 +- 19 files changed, 4387 insertions(+), 2268 deletions(-) create mode 100644 README_AreaPicker.md create mode 100644 components/AreaPicker.vue create mode 100644 subPackages/user/collection.vue diff --git a/README_AreaPicker.md b/README_AreaPicker.md new file mode 100644 index 0000000..374ec7a --- /dev/null +++ b/README_AreaPicker.md @@ -0,0 +1,253 @@ +# 省市区选择组件使用说明 + +## 概述 + +`AreaPicker.vue` 是一个功能完整的省市区三级联动选择组件,支持自定义样式插槽,可以灵活地集成到各种页面中。 + +## 功能特性 + +- ✅ 省市区三级联动选择 +- ✅ 支持默认值设置 +- ✅ 支持插槽自定义显示样式 +- ✅ 完整的事件回调 +- ✅ 灵活的数据请求方式 +- ✅ 错误处理和容错机制 + +## Props + +| 参数 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| placeholder | String | '请选择' | 占位符文本 | +| defaultValue | Object | null | 默认选中值,格式:`{ provinceId, cityId, areaId }` | +| disabled | Boolean | false | 是否禁用 | + +## Events + +| 事件名 | 参数 | 说明 | +|--------|------|------| +| change | data | 选择改变时触发,返回选中的省市区信息 | + +### change 事件返回数据格式 + +```javascript +{ + provinceId: '110000', // 省份ID + cityId: '110100', // 城市ID + areaId: '110101', // 区域ID + fullText: '北京市北京市东城区' // 完整地址文本 +} +``` + +## Methods + +| 方法名 | 参数 | 返回值 | 说明 | +|--------|------|--------|------| +| getValue | - | Object | 获取当前选中的值 | +| reset | - | - | 重置选择 | + +## 插槽使用 + +组件提供了默认插槽,允许完全自定义显示样式。插槽提供以下数据: + +| 插槽参数 | 类型 | 说明 | +|----------|------|------| +| selectedText | String | 当前选中的完整文本 | +| placeholder | String | 占位符文本 | +| provinceData | Array | 省份数据列表 | +| cityData | Array | 城市数据列表 | +| areaData | Array | 区域数据列表 | +| multiIndex | Array | 当前选中的索引数组 | +| currentSelection | Object | 当前选中的详细信息 | + +### currentSelection 对象结构 + +```javascript +{ + province: { id: '110000', name: '北京市' }, + city: { id: '110100', name: '北京市' }, + area: { id: '110101', name: '东城区' }, + fullText: '北京市北京市东城区' +} +``` + +## 使用示例 + +### 基本使用 + +```vue + + + +``` + +### 自定义样式(插槽) + +```vue + + + + + +``` + +### 在 header 组件中使用 + +```vue + + + +``` + +## 数据接口要求 + +组件需要后端提供省市区数据接口,接口返回格式如下: + +```javascript +// 省份数据 +[ + { id: '110000', name: '北京市' }, + { id: '120000', name: '天津市' }, + // ... +] + +// 城市数据(根据省份ID获取) +[ + { id: '110100', name: '北京市', pid: '110000' }, + // ... +] + +// 区域数据(根据城市ID获取) +[ + { id: '110101', name: '东城区', pid: '110100' }, + { id: '110102', name: '西城区', pid: '110100' }, + // ... +] +``` + +## 注意事项 + +1. 组件会自动处理数据请求的多种方式(父组件 Post 方法、全局 Post 方法、uni.request) +2. 建议在使用前确保数据接口正常可用 +3. 插槽内容会完全替换默认的显示样式 +4. 可以通过 ref 调用组件的 getValue() 和 reset() 方法 +5. 组件支持设置默认值,会自动回显对应的省市区信息 + +## 完整示例 + +查看 `AreaPickerSlotExample.vue` 文件获取完整的使用示例,包含多种自定义样式的演示。 \ No newline at end of file diff --git a/common/index.js b/common/index.js index 3e90280..3c6081f 100644 --- a/common/index.js +++ b/common/index.js @@ -25,9 +25,13 @@ async function getLocationInfo() { location, success(response) { console.log(response) - let info = response.result; - location.province = info.address_component.province; - location.cityCode = info.ad_info.city_code.slice(3); + let info = response.result; + let _c = info.ad_info.adcode.slice(0,3) + location.cityId = info.ad_info.city_code.slice(3); + location.provinceId = _c.padEnd(6,'0'); + location.areaId = info.ad_info.adcode; + + location.province = info.address_component.province; location.city = info.address_component.city; location.area = info.address_component.district; location.street = info.address_component.street; diff --git a/components/AreaPicker.vue b/components/AreaPicker.vue new file mode 100644 index 0000000..5f116ca --- /dev/null +++ b/components/AreaPicker.vue @@ -0,0 +1,429 @@ + + + + + \ No newline at end of file diff --git a/components/ProductSection.vue b/components/ProductSection.vue index 9543d49..dca2437 100644 --- a/components/ProductSection.vue +++ b/components/ProductSection.vue @@ -50,7 +50,7 @@ {{ item.title }} {{ item.price }} { + // 显示提示 + const updatedItem = { ...item, type: !item.type }; + this.productList[index].type = !item.type + uni.showToast({ + title: updatedItem.type ? "已收藏" : "取消收藏", + icon: "none", + duration: 1500, + }); + this.$forceUpdate() + // 向父组件发送事件 + this.$emit("like-toggle", { item: updatedItem, index }); + }); - // 显示提示 - uni.showToast({ - title: updatedItem.isLiked ? "已收藏" : "取消收藏", - icon: "none", - duration: 1500, - }); - - // 向父组件发送事件 - this.$emit("like-toggle", { item: updatedItem, index }); + }, // 显示图片 diff --git a/components/header.vue b/components/header.vue index 1f9dd1a..25f79fa 100644 --- a/components/header.vue +++ b/components/header.vue @@ -8,15 +8,36 @@ :class="{ 'header-fixed': fixed }" :style="{ height: height + 'px', 'padding-top': statusBarHeight + 'px' }" > + - - {{ selectedLocation }} - + + + + + + + @@ -124,6 +211,56 @@ export default { align-items: center; flex: 1; + .area-picker-wrapper { + margin-right: 20rpx; + min-width: 200rpx; + max-width: 300rpx; +} + +.area-display { + display: flex; + align-items: center; + justify-content: space-between; + padding: 8rpx 16rpx; + border: 2rpx solid #e0e0e0; + border-radius: 8rpx; + background-color: #fff; + min-height: 60rpx; +} + +.area-text { + font-size: 30rpx; + color: #333; + flex: 1; + + &.placeholder { + color: #999; + } +} + +.dropdown-icon { + width: 24rpx; + height: 16rpx; + margin-left: 8rpx; +} + + + + .search-icon { + height: 36.16rpx; + } +} + +.logo { + height: 36.16rpx; + position: absolute; + left: 50%; + transform: translateX(-50%); +} + +.right-section { + flex: 1; +} .location-selector { display: flex; align-items: center; @@ -145,20 +282,4 @@ export default { height: 16rpx; } } - - .search-icon { - height: 36.16rpx; - } -} - -.logo { - height: 36.16rpx; - position: absolute; - left: 50%; - transform: translateX(-50%); -} - -.right-section { - flex: 1; -} diff --git a/manifest.json b/manifest.json index 61f440a..3e3f8c0 100644 --- a/manifest.json +++ b/manifest.json @@ -58,13 +58,13 @@ "minified" : true }, "usingComponents" : true, - "permission" : { - "scope.userLocation" : { - "desc" : "为了提供更好更快速的体验,需要获取您的当前位置" - } - }, - "lazyCodeLoading" : "requiredComponents", - "requiredPrivateInfos" : [ "getLocation", "chooseLocation" ] + "permission" : { + "scope.userLocation" : { + "desc" : "为了提供更好更快速的体验,需要获取您的当前位置" + } + }, + "lazyCodeLoading" : "requiredComponents", + "requiredPrivateInfos" : [ "getLocation", "chooseLocation" ] }, "mp-alipay" : { "usingComponents" : true diff --git a/pages.json b/pages.json index 7e24a4c..123031a 100644 --- a/pages.json +++ b/pages.json @@ -54,8 +54,8 @@ "path": "pages/notes/detail", "style": { "navigationBarTitleText": "笔记详情", - "navigationBarBackgroundColor": "#ffffff", - "navigationBarTextStyle": "black" + "navigationBarBackgroundColor": "#ffffff", + "navigationBarTextStyle": "black" } }, { @@ -189,6 +189,14 @@ "navigationBarTitleText": "修改昵称" } }, + { + "path": "user/collection", + "style": { + "navigationBarTitleText": "我的收藏", + "navigationBarBackgroundColor": "#ffffff", + "navigationBarTextStyle": "black" + } + }, { "path": "search/search", "style": { diff --git a/pages/index/iSoul.vue b/pages/index/iSoul.vue index 50c3a76..f9ca73b 100644 --- a/pages/index/iSoul.vue +++ b/pages/index/iSoul.vue @@ -1,107 +1,88 @@ + view { + box-sizing: border-box; + } + + .profile-container { + background: white; + min-height: 100vh; + padding-bottom: 200rpx; + color: white; + } + + /* 状态栏占位 */ + .status-bar-placeholder { + height: var(--status-bar-height); + width: 100%; + } + + /* 顶部导航 */ + .header { + display: flex; + justify-content: space-between; + align-items: center; + height: 48px; + } + + .back-btn, + .more-btn { + width: 60rpx; + height: 60rpx; + display: flex; + align-items: center; + justify-content: center; + font-size: 40rpx; + color: white; + } + + .dots { + font-size: 32rpx; + font-weight: bold; + } + + /* 用户信息区域 */ + .user-section { + display: flex; + align-items: center; + padding: 0 40rpx 30rpx; + } + + .user-avatar { + width: 120rpx; + height: 120rpx; + border-radius: 50%; + overflow: hidden; + margin-right: 30rpx; + } + + .avatar-img { + width: 100%; + height: 100%; + } + + .user-info { + flex: 1; + } + + .username { + font-size: 36rpx; + font-weight: bold; + color: white; + margin-bottom: 10rpx; + } + + .user-id { + font-size: 24rpx; + color: rgba(255, 255, 255, 0.8); + margin-bottom: 10rpx; + } + + .location { + display: flex; + align-items: center; + font-size: 24rpx; + color: rgba(255, 255, 255, 0.8); + } + + .location-icon, + .info-icon { + margin-right: 8rpx; + } + + /* 城市艺术漫游 */ + .city-art { + padding: 0 40rpx 20rpx; + display: flex; + align-items: center; + justify-content: space-between; + } + + .city-title { + display: flex; + align-items: center; + font-size: 28rpx; + color: rgba(255, 255, 255, 0.9); + } + + .pin-icon { + margin-right: 8rpx; + } + + .city-name { + font-size: 28rpx; + color: white; + font-weight: bold; + } + + .gender-icon { + width: 40rpx; + height: 40rpx; + background: rgba(255, 255, 255, 0.2); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 24rpx; + } + + /* 统计数据 */ + .stats-section { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 80rpx; + padding-bottom: 50rpx; + padding: 0 40rpx; + } + + .stats-left { + display: flex; + gap: 60rpx; + } + + .stat-item { + text-align: center; + min-width: 80rpx; + } + + .stat-number { + font-size: 32rpx; + font-weight: bold; + color: white; + margin-bottom: 8rpx; + } + + .stat-label { + font-size: 24rpx; + color: rgba(255, 255, 255, 0.8); + } + + /* 权益兑换入口 */ + .exchange-entry { + display: flex; + flex-direction: column; + align-items: center; + padding: 16rpx; + background: rgba(255, 255, 255, 0.1); + border-radius: 20rpx; + min-width: 120rpx; + transition: all 0.3s ease; + + &:active { + transform: scale(0.95); + background: rgba(255, 255, 255, 0.2); + } + } + + .exchange-icon { + font-size: 32rpx; + margin-bottom: 8rpx; + } + + .exchange-text { + font-size: 22rpx; + color: rgba(255, 255, 255, 0.9); + font-weight: 500; + } + + /* 操作按钮 */ + .action-buttons { + display: flex; + padding: 0 40rpx 40rpx; + gap: 20rpx; + } + + .follow-btn { + flex: 1; + background: #ff4757; + border-radius: 50rpx; + padding: 20rpx; + text-align: center; + color: white; + font-size: 28rpx; + font-weight: bold; + } + + .message-btn { + flex: 1; + background: rgba(255, 255, 255, 0.2); + border-radius: 50rpx; + padding: 20rpx; + text-align: center; + color: white; + font-size: 28rpx; + font-weight: bold; + } + + /* 待激活的Agent */ + .agent-section { + margin: 0 47rpx; + border-radius: 20rpx; + margin-bottom: 30rpx; + overflow: hidden; + display: flex; + align-items: center; + padding: 30rpx 0; + } + + .agent-header { + margin-right: 30rpx; + flex-shrink: 0; + } + + .agent-title { + font-size: 28rpx; + color: #000000; + } + + .agent-content { + flex: 1; + } + + .agent-scroll { + width: 430rpx; + white-space: nowrap; + /* 微信小程序隐藏横向滚动条 */ + overflow: hidden; + + /* Webkit浏览器 */ + &::-webkit-scrollbar { + display: none !important; + width: 0 !important; + height: 0 !important; + } + + /* Firefox */ + scrollbar-width: none; + /* IE和Edge */ + -ms-overflow-style: none; + } + + .agent-avatars { + display: inline-flex; + gap: 20rpx; + } + + .agent-avatar { + width: 104rpx; + height: 104rpx; + border-radius: 50%; + overflow: hidden; + flex-shrink: 0; + } + + .agent-img { + width: 100%; + height: 100%; + } + + /* 数字资产权益 */ + .digital-assets { + margin: 0 30rpx 0rpx; + } + + .asset-card { + border-radius: 20rpx; + overflow: hidden; + } + + .asset-bg { + padding: 40rpx 30rpx 30rpx; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + position: relative; + overflow: hidden; + } + + .asset-bg::before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: url('data:image/svg+xml,'); + pointer-events: none; + } + + .asset-title { + font-size: 32rpx; + color: white; + font-weight: 600; + position: relative; + z-index: 1; + } + + .asset-actions { + display: flex; + padding: 20rpx 0; + + background: white; + font-size: 25rpx; + } + + .asset-action { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + padding: 0 10rpx; + font-size: 24rpx; + color: #666; + position: relative; + } + + .asset-action.active { + color: #ff4757; + } + + .action-icon { + width: 36rpx; + height: 36rpx; + border-radius: 50%; + margin-bottom: 12rpx; + } + + .action-icon.red { + background: #ff4757; + } + + .action-icon.gray { + background: #ccc; + } + + /* 有感商品 */ + .feeling-goods { + margin: 20rpx 30rpx 30rpx; + } + + .goods-card { + border-radius: 20rpx; + overflow: hidden; + } + + .goods-bg { + padding: 40rpx 30rpx 20rpx; + position: relative; + } + + .goods-title { + font-size: 32rpx; + color: white; + font-weight: bold; + margin-bottom: 10rpx; + } + + .goods-brand { + font-size: 36rpx; + color: white; + font-weight: bold; + margin-bottom: 5rpx; + } + + .goods-subtitle { + font-size: 24rpx; + color: rgba(255, 255, 255, 0.8); + } + + .goods-actions { + display: flex; + background: white; + } + + .goods-action { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + padding: 20rpx 10rpx; + font-size: 24rpx; + color: #666; + } + + .goods-action.active { + color: #ff4757; + } + + /* 数字资产纪念册 */ + .memorial-section { + margin: 0 47rpx; + margin-bottom: 30rpx; + } + + .memorial-divider { + display: flex; + align-items: center; + padding: 30rpx 0; + margin-bottom: 30rpx; + } + + .divider-line { + flex: 1; + height: 2rpx; + background: #e0e0e0; + } + + .divider-text { + padding: 0 30rpx; + font-size: 28rpx; + color: #000000; + font-weight: 500; + white-space: nowrap; + } + + .memorial-cards { + display: flex; + gap: 20rpx; + } + + .memorial-card { + flex: 1; + border-radius: 10rpx; + overflow: hidden; + background: white; + } + + .memorial-img { + width: 100%; + height: 425rpx; + } + + .memorial-info { + padding: 20rpx 10rpx; + display: flex; + justify-content: space-between; + align-items: center; + } + + .memorial-title { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 22rpx; + color: #000000; + flex: 1; + } + + .memorial-more { + font-size: 14rpx; + color: #999; + } + + /* 底部菜单 */ + .bottom-menu { + padding: 40rpx 30rpx; + background: white; + margin: 0 30rpx; + border-radius: 20rpx; + margin-bottom: 30rpx; + } + + .menu-item { + padding: 30rpx 0; + border-bottom: 1rpx solid #f5f5f5; + font-size: 28rpx; + color: #333; + } + + .menu-item:last-child { + border-bottom: none; + } + + // 用户顶部背景区域 + .user-top { + background-size: cover; + background-position: center; + background-repeat: no-repeat; + padding-bottom: 20rpx; + } + + .digital-img { + height: 265rpx; + width: 100%; + border-radius: 20rpx; + } + + /* 权益兑换弹窗 */ + .exchange-popup { + width: 600rpx; + background-color: #ffffff; + border-radius: 16rpx; + overflow: hidden; + } + + .popup-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 30rpx; + border-bottom: 1px solid #f0f0f0; + } + + .popup-title { + font-size: 32rpx; + font-weight: 600; + color: #333; + } + + .popup-close { + font-size: 40rpx; + color: #999; + padding: 0 10rpx; + } + + .popup-content { + padding: 40rpx 30rpx 30rpx; + } + + .input-section { + margin-bottom: 40rpx; + } + + .input-label { + display: block; + font-size: 28rpx; + color: #333; + margin-bottom: 20rpx; + font-weight: 500; + } + + .exchange-input { + width: 100%; + height: 88rpx; + border: 2rpx solid #e0e0e0; + border-radius: 12rpx; + padding: 0 20rpx; + font-size: 28rpx; + color: #333; + box-sizing: border-box; + + &:focus { + border-color: #667eea; + } + } + + .popup-actions { + display: flex; + gap: 20rpx; + } + + .cancel-btn, + .confirm-btn { + flex: 1; + height: 80rpx; + border-radius: 12rpx; + font-size: 28rpx; + font-weight: 600; + border: none; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + + &:active { + transform: scale(0.98); + } + } + + .cancel-btn { + background: #f5f5f5; + color: #666; + } + + .confirm-btn { + background: #667eea; + color: #ffffff; + } + \ No newline at end of file diff --git a/pages/index/index.vue b/pages/index/index.vue index 7fc3b79..4eb4361 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -1,230 +1,240 @@ + .content { + height: calc(100vh - 123rpx); + width: 100%; + padding: 0 20rpx; + box-sizing: border-box; + margin-top: 20rpx; + } + + .tab-bar-placeholder { + height: 143rpx; + width: 100%; + } + \ No newline at end of file diff --git a/pages/index/timeShopBank.vue b/pages/index/timeShopBank.vue index 9127a06..9bebf11 100644 --- a/pages/index/timeShopBank.vue +++ b/pages/index/timeShopBank.vue @@ -378,9 +378,9 @@ page { } .fab-btn { - width: 120rpx; - height: 120rpx; - border-radius: 60rpx; + width: 80rpx; + height: 80rpx; + border-radius: 40rpx; background: linear-gradient(135deg, #ff4757, #ff6b7a); color: #fff; border: none; diff --git a/static/js/request.js b/static/js/request.js index 748927b..4b4cb20 100644 --- a/static/js/request.js +++ b/static/js/request.js @@ -2,10 +2,13 @@ import Vue from 'vue'; import store from '@/store'; // 定义 API URL +// const DEV_API_URL = 'https://epic.new.js-dyyj.com'; const DEV_API_URL = 'https://epic.js-dyyj.com'; const PROD_API_URL = 'https://epic.js-dyyj.com'; const NEWAPIURL = process.env.NODE_ENV === 'development' ? DEV_API_URL : PROD_API_URL; - +const DEV_API_URL_DES = 'http://192.168.124.118:8083/xcx'; +const PROD_API_URL_DES = 'http://192.168.124.118:8083/xcx'; +const NEWAPIURL_DES = process.env.NODE_ENV === 'development' ? DEV_API_URL_DES : PROD_API_URL_DES; // 获取token const getToken = () => { const userInfoFromStorage = uni.getStorageSync('userInfo'); @@ -17,7 +20,16 @@ const getToken = () => { } return store.state.user.userInfo.token; }; - +const getUserId = () => { + const userInfoFromStorage = uni.getStorageSync('userInfo'); + if (userInfoFromStorage) { + const userInfo = JSON.parse(userInfoFromStorage); + if (userInfo.id) { + return userInfo.id; + } + } + return store.state.user.userInfo.id; +}; // 定义错误处理函数 noForceLogin 不强制登录 const handleError = (res, reject, noForceLogin) => { if (res.data?.code === 401) { @@ -38,26 +50,39 @@ const handleError = (res, reject, noForceLogin) => { // 挂载到 Vue 原型上 Vue.prototype.NEWAPIURL = NEWAPIURL; +Vue.prototype.NEWAPIURL_DES = NEWAPIURL_DES; + // #ifdef H5 Vue.prototype.NEWAPIURL = '/api'; +Vue.prototype.NEWAPIURL_DES = '/api_des'; // #endif -Vue.prototype.Post = (params = {}, apiurl) => { +Vue.prototype.Post = (params = {}, apiurl,customUrl) => { const token = getToken(); if (token) { params.token = token; } + let baseUrl = Vue.prototype.NEWAPIURL + if (customUrl) { + const urls = { + DES: Vue.prototype.NEWAPIURL_DES, + } + baseUrl = urls[customUrl] + } else { + baseUrl = Vue.prototype.NEWAPIURL + } return new Promise((resolve, reject) => { uni.showLoading({ title: '加载中' }); uni.request({ method: params.method || 'GET', - url: Vue.prototype.NEWAPIURL + apiurl, + url:baseUrl + apiurl, data: params, header: { 'content-type': 'application/json', - 'token': token || '' + 'token': token || '', + 'userId': getUserId() || '', }, success: (res) => { console.log('success', res.data); diff --git a/subPackages/equityGoods/detail.vue b/subPackages/equityGoods/detail.vue index 1ca1150..b5c30ee 100644 --- a/subPackages/equityGoods/detail.vue +++ b/subPackages/equityGoods/detail.vue @@ -40,11 +40,11 @@ - 食在苏州|世界美食之都巡礼 + {{ goodsInfo.title||'-' }} 限量 - 1000份 - 剩余 900份 + {{ goodsInfo.publishQuantity||0 }}份 + 剩余 {{ goodsInfo.remainQuantity||0 }}份 @@ -52,15 +52,24 @@ ¥ - 699.00 + {{ goodsInfo.price||0 }} - 1700收藏 + + {{ goodsInfo.collectQuantity || 0 }}人收藏 @@ -98,8 +107,26 @@ :key="index" > - {{ item.label }} - {{ item.content }} + + + 产品{{ + ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十"][ + index + ] + }}: + + {{ item.goodsName }}{{ item.skuName || "" }} + X{{ item.bindQuantity }}份 - - - {{ tab.name }} + + + + {{ tab.name }} + - + @@ -133,43 +162,33 @@ + > + - + - - - - - - - + + + + + + + @@ -186,43 +205,14 @@ export default { data() { return { - topBanner: [ - "/uploads/20250731/5f6f00e6f037c5ca03423b3ed190c20d.png", - "/uploads/20250731/5f6f00e6f037c5ca03423b3ed190c20d.png", - ], + topBanner: [], list: [], swiperIndex: 0, isEquityExpanded: false, // 权益详情展开状态 currentTab: 0, // 当前选中的tab索引 - tabList: [ - { - name: "登记证书", - }, - { - name: "IP资产详情", - }, - { - name: "资源商品详情", - }, - { - name: "资源商品详情", - }, - ], - equityList: [ - // 权益列表数据 - { - label: "权益1:", - content: "数字资产*1、数字资产*1", - }, - { - label: "权益2:", - content: "IP文创公仔*1、IP文创公仔*1", - }, - { - label: "权益3:", - content: "XX园林门票*1、XX园林门票*1", - }, - ], + tabList: [], + equityList: [], + goodsInfo: null, }; }, computed: { @@ -234,7 +224,40 @@ export default { // this.equityList.slice(0, 2); }, }, + onLoad(e) { + this.getDetail(e.id); + }, methods: { + getDetail(benefitPackageId) { + this.Post( + {}, + `/framework/benefitPackage/detail/${benefitPackageId}`, + "DES" + ).then((res) => { + res.data.goodsVos.forEach((element) => { + element.detailUrl = this.addImgStyleToHtml(element.detailUrl); + }); + this.goodsInfo = res.data; + this.goodsInfo.ipDigitalAsset.detailUrl = this.addImgStyleToHtml( + this.goodsInfo.ipDigitalAsset.detailUrl + ); + this.topBanner = res.data.coverUrl.split(","); + this.equityList = res.data.benefitGoods; + this.generateTabList(); + }); + }, + handleLikeClick() { + this.Post( + { + packageId: this.goodsInfo.benefitPackageId, + type: !this.goodsInfo.type, + }, + "/framework/benefitPackage/collect", + "DES" + ).then((res) => { + this.goodsInfo.type = !this.goodsInfo.type; + }); + }, swiperChange(e) { this.swiperIndex = e.detail.current; }, @@ -252,15 +275,58 @@ export default { }); // 这里可以添加购买逻辑 }, - // 处理收藏点击 - handleLikeClick(item, index) { - console.log("收藏点击", item, index); - // 这里可以添加收藏逻辑 - }, + // 切换tab switchTab(index) { this.currentTab = index; }, + addImgStyleToHtml(htmlStr) { + return htmlStr.replace(/]*)>/gi, (match, attrs) => { + // 检查是否已有 style 属性 + console.log("====开始计算"); + if (/style\s*=/.test(attrs)) { + // 已有 style,合并 width:100% + return ` { + // 合并 width:100% 到已有 style + let newStyle = styleVal; + if (!/width\s*:\s*100%/.test(styleVal)) { + newStyle = `width:100%;${styleVal}`; + } + return `style=${quote}${newStyle}${quote}`; + } + )}>`; + } else { + // 没有 style,直接加 + return ``; + } + }); + }, + + // 根据商品信息动态生成Tab列表 + generateTabList() { + this.tabList = []; + + // 基础Tab - 始终显示 + this.tabList.push({ name: "登记证书" }); + this.tabList.push({ name: "IP资产详情" }); + + // 根据商品信息动态添加Tab + if (this.goodsInfo) { + // 如果有门票信息,添加门票详情Tab + if (this.goodsInfo.sku && this.goodsInfo.sku.product) { + this.tabList.push({ name: "门票详情" }); + } + + // 如果有goodsVos内容,添加商品详情Tab + if (this.goodsInfo.goodsVos) { + this.goodsInfo.goodsVos.forEach((element) => { + this.tabList.push({ name: "权益商品" }); + }); + } + } + }, }, }; @@ -345,7 +411,7 @@ export default { background: #94fafa; color: #333333; padding: 8rpx 16rpx; - font-size: 20rpx; + font-size: 26rpx; border-radius: 6rpx 0 0 6rpx; } @@ -353,13 +419,13 @@ export default { background: #f0f0f0; color: #000000; padding: 8rpx 16rpx; - font-size: 20rpx; + font-size: 26rpx; border-radius: 0rpx 6rpx 6rpx 0; } .remaining { color: #808080; - font-size: 22rpx; + font-size: 26rpx; margin-left: auto; } } @@ -474,28 +540,24 @@ export default { border-top: 1rpx solid #e5e5e5; padding-top: 60rpx; padding-bottom: 20rpx; + .equity-detail-item { - display: flex; - align-items: center; - justify-content: space-between; margin-bottom: 10rpx; line-height: 1.5; .detail-content-wrapper { - display: flex; - flex: 1; - .detail-label { - font-size: 26rpx; + font-size: 28rpx; color: #808080; font-weight: 500; + margin-right: 10rpx; } .detail-content { - font-size: 26rpx; + font-size: 28rpx; color: #808080; - flex: 1; font-weight: 500; + margin-right: 10rpx; } } @@ -535,28 +597,40 @@ export default { .tab-nav { margin: 0 40rpx; margin-top: 40rpx; - display: flex; - justify-content: space-between; + white-space: nowrap; - .tab-item { - padding: 10rpx 20rpx; - text-align: center; - color: #3e3a39; - cursor: pointer; - transition: all 0.3s ease; - background-color: #94fafa66; + .tab-container { display: flex; - align-items: center; - &.active { - background-color: #94fafa; - color: #525454; - font-size: 24rpx; - border-radius: 10rpx 10rpx 0 0; - font-weight: bold; - } + min-width: 100%; + + .tab-item { + padding: 10rpx 20rpx; + text-align: center; + color: #3e3a39; + cursor: pointer; + transition: all 0.3s ease; + background-color: #94fafa66; + display: flex; + align-items: center; + flex-shrink: 0; + margin-right: 16rpx; - .tab-text { - font-size: 24rpx; + &:last-child { + margin-right: 0; + } + + &.active { + background-color: #94fafa; + color: #525454; + font-size: 30rpx; + border-radius: 10rpx 10rpx 0 0; + font-weight: bold; + } + + .tab-text { + font-size: 30rpx; + white-space: nowrap; + } } } } @@ -576,6 +650,9 @@ export default { .tab-panel { min-height: 400rpx; + img { + width: 100%; + } // 证书容器 .certificate-container { @@ -653,6 +730,29 @@ export default { } } } + + // 权益详情列表 + .equity-detail-list { + .equity-detail-item { + margin-bottom: 30rpx; + padding: 20rpx; + background: #f8f9fa; + border-radius: 12rpx; + + .equity-name { + font-size: 28rpx; + color: #333; + font-weight: 600; + margin-bottom: 12rpx; + } + + .equity-desc { + font-size: 26rpx; + color: #666; + line-height: 1.5; + } + } + } } } } @@ -664,15 +764,15 @@ export default { left: 0; right: 0; background: white; - padding: 20rpx 30rpx 40rpx; + padding: 20rpx 30rpx; border-top: 1rpx solid #e5e5e5; z-index: 100; - padding-bottom: calc(env(safe-area-inset-bottom) + 20rpx); - padding-bottom: calc(constant(safe-area-inset-bottom) + 20rpx); + padding-bottom: calc(20rpx + env(safe-area-inset-bottom)); .purchase-button { - width: 100%; + width: 690rpx; height: 88rpx; + margin: 0 auto; background: #94fafa; border-radius: 44rpx; display: flex; diff --git a/subPackages/equityGoods/index.vue b/subPackages/equityGoods/index.vue index 35a613e..d7ef82c 100644 --- a/subPackages/equityGoods/index.vue +++ b/subPackages/equityGoods/index.vue @@ -1,13 +1,36 @@ + .equity-goods-page { + min-height: 100vh; + background: #f5f5f5; + padding-bottom: 40rpx; + } + + .header-section { + padding: 60rpx 30rpx 30rpx; + + .title { + font-size: 36rpx; + color: #000000; + text-align: center; + margin-bottom: 30rpx; + padding-bottom: 30rpx; + font-weight: 500; + border-bottom: 0.5rpx solid #999999; + } + + .filter-buttons { + display: flex; + justify-content: space-between; + gap: 40rpx; + + .filter-btn { + font-size: 28rpx; + color: #000000; + border-radius: 20rpx; + transition: all 0.3s; + + &.active { + background: #007aff; + color: white; + } + } + } + } + + .products-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 20rpx; + padding: 30rpx; + + .product-item { + overflow: hidden; + border-bottom: 0.5rpx solid #999999; + margin-bottom: 15rpx; + padding-bottom: 20rpx; + + &:active { + transform: scale(0.98); + } + + .product-image { + width: 100%; + height: 429rpx; + object-fit: cover; + border-radius: 20rpx; + } + + .product-info { + padding: 20rpx 0; + + .product-title { + font-size: 22rpx; + color: #000000; + margin-bottom: 16rpx; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-weight: 500; + } + + .product-price { + font-size: 36rpx; + font-weight: 500; + color: #000000; + } + + .product-details { + display: flex; + align-items: center; + justify-content: space-between; + + .detail-item { + font-size: 18rpx; + color: #808080; + } + } + } + } + } + + // 空状态样式 + .empty-state { + padding: 80rpx 30rpx; + min-height: 400rpx; + display: flex; + align-items: center; + justify-content: center; + + .empty-content { + text-align: center; + max-width: 400rpx; + + .empty-icon { + width: 120rpx; + height: 120rpx; + margin: 0 auto 40rpx; + opacity: 0.6; + } + + .empty-title { + font-size: 32rpx; + color: #666666; + font-weight: 500; + margin-bottom: 20rpx; + } + + .empty-desc { + font-size: 26rpx; + color: #999999; + line-height: 1.5; + margin-bottom: 16rpx; + } + + .empty-tip { + font-size: 24rpx; + color: #BBBBBB; + line-height: 1.4; + } + } + } + + .map-section { + border-top: 0.5rpx solid #999999; + margin: 30rpx 30rpx 0; + overflow: hidden; + + .map-title { + padding: 30rpx; + font-size: 22rpx; + font-weight: 500; + color: #000000; + text-align: center; + } + + .map-container { + position: relative; + height: 330rpx; + border: 6rpx solid white; + border-radius: 20rpx; + transform: translateY(0); + overflow: hidden; + + .map-component { + width: 100%; + height: 100%; + border-radius: 20rpx; + } + } + + .map-description { + padding: 30rpx; + + .location-info { + display: flex; + align-items: center; + justify-content: center; + gap: 16rpx; + + .location-icon { + width: 40rpx; + } + + .location-name { + font-size: 22rpx; + color: #808080; + } + } + } + } + + .heart-icon { + width: 35rpx; + height: 30rpx; + transition: all 0.3s ease; + flex-shrink: 0; + top: -2rpx; + position: relative; + margin-right: 6rpx; + + &.liked { + opacity: 1; + filter: hue-rotate(320deg) saturate(2); + } + + &:active { + transform: scale(1.2); + } + } + + .shop-icon { + width: 39rpx; + height: 36rpx; + transition: all 0.3s ease; + flex-shrink: 0; + margin-left: 10rpx; + + &.liked { + opacity: 1; + filter: hue-rotate(320deg) saturate(2); + } + + &:active { + transform: scale(1.2); + } + } + + .product-price-box { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 10rpx; + } + + .location-selector { + position: absolute; + top: 20rpx; + left: 20rpx; + display: flex; + align-items: center; + padding: 8rpx 16rpx; + // border: 2rpx solid #e0e0e0; + border-radius: 20rpx; + min-width: 100rpx; + margin-right: 20rpx; + + .location-text { + font-size: 30rpx; + color: white; + margin-right: 8rpx; + } + + .dropdown-icon { + width: 24rpx; + height: 16rpx; + } + } + + // 预约弹窗样式 + .reservation-popup { + width: 600rpx; + background: white; + border-radius: 24rpx; + overflow: hidden; + + .popup-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 32rpx 32rpx 24rpx; + border-bottom: 1rpx solid #f0f0f0; + + .popup-title { + font-size: 32rpx; + font-weight: 600; + color: #333; + } + + .popup-close { + font-size: 40rpx; + color: #999; + line-height: 1; + padding: 8rpx; + cursor: pointer; + transition: color 0.3s; + + &:active { + color: #666; + } + } + } + + .popup-content { + padding: 32rpx; + + .input-section { + margin-bottom: 32rpx; + + .input-label { + display: block; + font-size: 28rpx; + color: #333; + margin-bottom: 16rpx; + font-weight: 500; + } + + .reservation-input { + width: 100%; + height: 88rpx; + border: 2rpx solid #e0e0e0; + border-radius: 12rpx; + padding: 0 24rpx; + font-size: 28rpx; + color: #333; + background: #fafafa; + transition: all 0.3s; + box-sizing: border-box; + + &:focus { + border-color: #007aff; + background: white; + } + + &::placeholder { + color: #999; + } + } + } + + .popup-actions { + display: flex; + gap: 24rpx; + margin-top: 40rpx; + + .cancel-btn, + .confirm-btn { + flex: 1; + height: 74rpx; + border-radius: 12rpx; + font-size: 28rpx; + font-weight: 600; + border: none; + transition: all 0.3s; + + &:active { + transform: scale(0.98); + } + } + + .cancel-btn { + background: #f5f5f5; + color: #666; + + &:active { + background: #e8e8e8; + } + } + + .confirm-btn { + background: #007aff; + color: white; + + &:active { + background: #0056cc; + } + } + } + } + } + + // 地图标题点击样式 + .map-title { + cursor: pointer; + transition: all 0.3s; + } + \ No newline at end of file diff --git a/subPackages/orderQy/confrim.vue b/subPackages/orderQy/confrim.vue index a56336c..64a8170 100644 --- a/subPackages/orderQy/confrim.vue +++ b/subPackages/orderQy/confrim.vue @@ -60,20 +60,52 @@ IP资产供应商:{{ supplier || "苏州XXX博物馆" }} - + {{ - goodsInfo.name || "食在苏州 | 世界美食之都巡礼+实物探真" + item.name || "食在苏州 | 世界美食之都巡礼+实物探真" }} - {{ - goodsInfo.desc || "商品规格信息描述" - }} - ¥{{ goodsInfo.price || "699.00" }} + + + + + + 规格{{ specIndex + 1 }} + + {{ spec.selectedSpec || "请选择规格" }} + + + + + + + + + 添加规格 + + + + ¥{{ item.price || "699.00" }} @@ -123,6 +155,94 @@ + + + + + 选择规格 + × + + + + + + + + {{ currentGoods.name }} + + + + + + + + {{ specificationData.level1Title || "规格" }} + * + + + + {{ option.name }} + + + + + + + + {{ specificationData.level2Title || "子规格" }} + * + + + + {{ option.name }} + + + + + + + + + + + + + + + 0 + ) { + return this.selectedLevel2 >= 0; + } + + // 如果没有二级规格选项,只需要选择一级规格即可 + return true; + }, + }, + methods: { // 返回上一页 goBack() { @@ -295,26 +452,310 @@ export default { const goodsData = await this.getGoodsDetail(goodsId); this.goodsInfo = goodsData; this.supplier = goodsData.supplier; - this.totalAmount = goodsData.price; + + // 初始化商品列表 + this.goodsList = [ + { + id: goodsData.id, + name: goodsData.name, + price: goodsData.price, + image: goodsData.image, + quantity: 3, // 默认数量为3,可以根据实际需求调整 + specifications: [ + { + selectedSpec: "", + selectedLevel1: -1, + selectedLevel2: -1, + }, + ], + }, + ]; + + this.calculateTotalAmount(); } catch (error) { console.error("加载商品信息失败:", error); + // 使用模拟数据 + this.loadMockGoodsData(); } }, + // 加载模拟商品数据 + loadMockGoodsData() { + this.goodsList = [ + { + id: 1, + name: "食在苏州 | 世界美食之都巡礼+实物探真", + price: "699.00", + image: "/static/image/goods-sample.jpg", + quantity: 3, + specifications: [ + { + selectedSpec: "", + selectedLevel1: -1, + selectedLevel2: -1, + }, + ], + }, + { + id: 2, + name: "苏州园林文化体验套餐", + price: "899.00", + image: "/static/image/goods-sample.jpg", + quantity: 2, + specifications: [ + { + selectedSpec: "", + selectedLevel1: -1, + selectedLevel2: -1, + }, + ], + }, + ]; + this.calculateTotalAmount(); + }, + // 加载默认地址 async loadDefaultAddress() { try { + this.Post({ + isDefault:1 + }, + "/framework/concat/selectList", + 'DES' + ).then((res) => { + if(res.data){ + this.updateAddressInfo(res.data[0]); + } + }); // 这里调用实际的API接口获取默认地址 - const addressData = await this.getDefaultAddress(); - if (addressData && !this.address.id) { - // 只有当前没有地址时才设置默认地址 - this.updateAddressInfo(addressData); - } } catch (error) { console.error("加载默认地址失败:", error); } }, + // 选择规格 + selectSpecification(goodsIndex, specIndex) { + this.currentGoodsIndex = goodsIndex; + this.currentSpecIndex = specIndex; + this.currentGoods = this.goodsList[goodsIndex]; + this.loadSpecificationData(this.currentGoods.id); + + // 回显之前的选择 + const currentSpec = this.currentGoods.specifications[specIndex]; + this.selectedLevel1 = currentSpec.selectedLevel1 || -1; + this.selectedLevel2 = currentSpec.selectedLevel2 || -1; + this.quantity = this.currentGoods.quantity || 1; + + this.$refs.specificationPopup.open(); + }, + + // 添加规格 + addSpecification(goodsIndex) { + const goods = this.goodsList[goodsIndex]; + if (goods.specifications.length < goods.quantity) { + goods.specifications.push({ + selectedSpec: "", + selectedLevel1: -1, + selectedLevel2: -1, + }); + } + }, + + // 关闭规格选择弹窗 + closeSpecificationPopup() { + this.$refs.specificationPopup.close(); + this.resetSpecificationData(); + }, + + // 重置规格选择数据 + resetSpecificationData() { + this.selectedLevel1 = -1; + this.selectedLevel2 = -1; + this.quantity = 1; // 保持默认数量为1 + }, + + // 加载规格数据 + async loadSpecificationData(goodsId) { + try { + const specData = await this.getSpecificationData(goodsId); + this.specificationData = specData; + + // 如果有之前的选择,需要更新二级规格选项 + if ( + this.selectedLevel1 >= 0 && + this.specificationData.level1Options[this.selectedLevel1] + ) { + const level1Option = + this.specificationData.level1Options[this.selectedLevel1]; + if (level1Option.children) { + this.specificationData.level2Options = level1Option.children; + } else { + this.specificationData.level2Options = []; + } + } + } catch (error) { + console.error("加载规格数据失败:", error); + // 使用模拟数据 + this.loadMockSpecificationData(); + } + }, + + // 选择一级规格 + selectLevel1(index) { + this.selectedLevel1 = index; + this.selectedLevel2 = -1; // 重置二级选择 + + // 根据一级选择更新二级选项 + if ( + this.specificationData.level1Options[index] && + this.specificationData.level1Options[index].children + ) { + this.specificationData.level2Options = + this.specificationData.level1Options[index].children; + } else { + this.specificationData.level2Options = []; + } + }, + + // 选择二级规格 + selectLevel2(index) { + this.selectedLevel2 = index; + }, + + // 减少数量 + decreaseQuantity() { + if (this.quantity > 1) { + this.quantity--; + } + }, + + // 增加数量 + increaseQuantity() { + this.quantity++; + }, + + // 确认规格选择 + confirmSpecification() { + // 校验一级规格 + if (this.selectedLevel1 < 0) { + uni.showToast({ + title: "请选择一级规格", + icon: "none", + }); + return; + } + + // 校验二级规格(如果有二级规格选项) + if ( + this.specificationData.level2Options && + this.specificationData.level2Options.length > 0 + ) { + if (this.selectedLevel2 < 0) { + uni.showToast({ + title: "请选择二级规格", + icon: "none", + }); + return; + } + } + + const level1Option = + this.specificationData.level1Options[this.selectedLevel1]; + const level2Option = + this.selectedLevel2 >= 0 + ? this.specificationData.level2Options[this.selectedLevel2] + : null; + + // 构建规格文本 + let specText = level1Option.name; + if (level2Option) { + specText += ` / ${level2Option.name}`; + } + // if (this.quantity > 1) { + // specText += ` × ${this.quantity}`; + // } + + // 更新商品规格信息 + this.goodsList[this.currentGoodsIndex].specifications[ + this.currentSpecIndex + ].selectedSpec = specText; + this.goodsList[this.currentGoodsIndex].specifications[ + this.currentSpecIndex + ].selectedLevel1 = this.selectedLevel1; + this.goodsList[this.currentGoodsIndex].specifications[ + this.currentSpecIndex + ].selectedLevel2 = this.selectedLevel2; + + // 更新价格 + let price = level1Option.price || this.currentGoods.price; + if (level2Option && level2Option.price) { + price = level2Option.price; + } + this.goodsList[this.currentGoodsIndex].price = price; + + // 重新计算总金额 + this.calculateTotalAmount(); + + this.closeSpecificationPopup(); + + uni.showToast({ + title: "规格选择成功", + icon: "success", + }); + }, + + // 计算总金额 + calculateTotalAmount() { + let total = 0; + this.goodsList.forEach((item) => { + if (item.price) { + // 计算已选择规格的数量 + const selectedSpecsCount = item.specifications.filter( + (spec) => spec.selectedSpec + ).length; + total += parseFloat(item.price) * selectedSpecsCount; + } + }); + this.totalAmount = total.toFixed(2); + }, + + // 加载模拟规格数据 + loadMockSpecificationData() { + this.specificationData = { + level1Title: "套餐类型", + level1Options: [ + { + name: "标准套餐", + price: "699.00", + children: [ + { name: "单人套餐", price: "699.00" }, + { name: "双人套餐", price: "1299.00" }, + { name: "家庭套餐", price: "1899.00" }, + ], + }, + { + name: "豪华套餐", + price: "999.00", + children: [ + { name: "VIP单人", price: "999.00" }, + { name: "VIP双人", price: "1799.00" }, + { name: "VIP家庭", price: "2599.00" }, + ], + }, + { + name: "定制套餐", + price: "1299.00", + children: [ + { name: "定制单人", price: "1299.00" }, + { name: "定制双人", price: "2299.00" }, + ], + }, + ], + level2Title: "具体套餐", + level2Options: [], + }; + }, + // 提交订单 async submitOrder() { // 验证必填项 @@ -326,9 +767,14 @@ export default { return; } - if (!this.deliveryMethod) { + // 验证所有商品是否已选择规格 + const unselectedGoods = this.goodsList.filter((item) => { + // 检查是否有规格未选择 + return item.specifications.some((spec) => !spec.selectedSpec); + }); + if (unselectedGoods.length > 0) { uni.showToast({ - title: "请选择履约方式", + title: "请选择所有商品的规格", icon: "none", }); return; @@ -400,26 +846,50 @@ export default { }); }, - // API接口 - 获取默认地址 - async getDefaultAddress() { + // API接口 - 获取规格数据 + async getSpecificationData(goodsId) { // 模拟API数据 return new Promise((resolve) => { setTimeout(() => { resolve({ - id: 1, - name: "XX先生", - tel: "18312341234", - address: "江苏省苏州市姑苏区XXXXXX", - province_text: "江苏省", - city_text: "苏州市", - district_text: "姑苏区", - detail_addr: "XXXXXX", - is_default: 1, + level1Title: "套餐类型", + level1Options: [ + { + name: "标准套餐", + price: "699.00", + children: [ + { name: "单人套餐", price: "699.00" }, + { name: "双人套餐", price: "1299.00" }, + { name: "家庭套餐", price: "1899.00" }, + ], + }, + { + name: "豪华套餐", + price: "999.00", + children: [ + { name: "VIP单人", price: "999.00" }, + { name: "VIP双人", price: "1799.00" }, + { name: "VIP家庭", price: "2599.00" }, + ], + }, + { + name: "定制套餐", + price: "1299.00", + children: [ + { name: "定制单人", price: "1299.00" }, + { name: "定制双人", price: "2299.00" }, + ], + }, + ], + level2Title: "具体套餐", + level2Options: [], }); - }, 500); + }, 300); }); }, + + // API接口 - 创建订单 async createOrder(orderData) { // 模拟API调用 @@ -769,4 +1239,273 @@ $bg-light: #f7fafc; background-color: rgba(45, 55, 72, 0.8); } } + +// 规格选择弹窗样式 +.specification-popup { + background: white; + border-radius: 24rpx 24rpx 0 0; + max-height: 80vh; + overflow: hidden; +} + +.popup-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 32rpx 30rpx 24rpx; + border-bottom: 1rpx solid $border-color; + + .popup-title { + font-size: 32rpx; + font-weight: 600; + color: $text-primary; + } + + .popup-close { + font-size: 40rpx; + color: $text-muted; + line-height: 1; + padding: 8rpx; + cursor: pointer; + transition: color 0.3s; + + &:active { + color: $text-secondary; + } + } +} + +.popup-content { + padding: 30rpx; + max-height: 60vh; + overflow-y: auto; +} + +// 商品预览 +.goods-preview { + display: flex; + align-items: center; + gap: 20rpx; + padding: 24rpx; + background: $bg-light; + border-radius: 16rpx; + margin-bottom: 30rpx; + + .preview-image { + width: 80rpx; + height: 80rpx; + border-radius: 12rpx; + flex-shrink: 0; + } + + .preview-info { + flex: 1; + display: flex; + flex-direction: column; + gap: 8rpx; + } + + .preview-name { + font-size: 26rpx; + color: $text-primary; + font-weight: 500; + line-height: 1.3; + } + + .preview-price { + font-size: 28rpx; + color: $danger-color; + font-weight: 600; + } +} + +// 规格选择区域 +.spec-section { + margin-bottom: 30rpx; + + .spec-title { + font-size: 28rpx; + color: $text-primary; + font-weight: 600; + margin-bottom: 20rpx; + display: block; + + .required { + color: $danger-color; + margin-left: 4rpx; + } + } + + .spec-options { + display: flex; + flex-wrap: wrap; + gap: 16rpx; + } + + .spec-option { + padding: 16rpx 24rpx; + border: 2rpx solid $border-color; + border-radius: 12rpx; + background: white; + transition: all 0.3s ease; + cursor: pointer; + + &:active { + transform: scale(0.95); + } + + &.active { + border-color: $primary-color; + background: rgba(102, 126, 234, 0.1); + } + + .option-text { + font-size: 26rpx; + color: $text-primary; + font-weight: 500; + } + } +} + +// 数量选择 +.quantity-section { + display: flex; + justify-content: space-between; + align-items: center; + padding: 24rpx 0; + border-top: 1rpx solid $border-color; + + .quantity-title { + font-size: 28rpx; + color: $text-primary; + font-weight: 600; + } + + .quantity-control { + display: flex; + align-items: center; + gap: 20rpx; + } + + .quantity-btn { + width: 60rpx; + height: 60rpx; + border: 2rpx solid $border-color; + border-radius: 12rpx; + display: flex; + align-items: center; + justify-content: center; + font-size: 32rpx; + color: $text-primary; + font-weight: 600; + background: white; + transition: all 0.3s ease; + cursor: pointer; + + &:active { + background: $bg-light; + border-color: $primary-color; + } + } + + .quantity-value { + font-size: 28rpx; + color: $text-primary; + font-weight: 600; + min-width: 60rpx; + text-align: center; + } +} + +// 确认按钮 +.popup-actions { + padding: 24rpx 30rpx 40rpx; + border-top: 1rpx solid $border-color; + background: white; + + .confirm-spec-btn { + width: 100%; + height: 88rpx; + background: $primary-color; + color: white; + border: none; + border-radius: 44rpx; + font-size: 32rpx; + font-weight: 600; + transition: all 0.3s ease; + + &:active { + transform: scale(0.98); + background: rgba(102, 126, 234, 0.8); + } + + &:disabled { + background: $text-muted; + cursor: not-allowed; + } + } +} + +// 商品卡片中的规格信息样式 +.specifications-list { + margin: 12rpx 0; +} + +.spec-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 16rpx 0; + border-bottom: 1rpx solid #f0f0f0; + + &:last-child { + border-bottom: none; + } +} + +.spec-content { + flex: 1; + display: flex; + flex-direction: column; + gap: 8rpx; +} + +.spec-label { + font-size: 22rpx; + color: $text-secondary; + font-weight: 500; +} + +.spec-text { + font-size: 24rpx; + color: $text-primary; + font-weight: 500; + + &.placeholder { + color: $text-muted; + } +} + +.add-spec-btn { + display: flex; + align-items: center; + justify-content: center; + padding: 20rpx 0; + margin-top: 8rpx; + border: 2rpx dashed $border-color; + border-radius: 12rpx; + background: rgba(102, 126, 234, 0.02); + transition: all 0.3s ease; + + &:active { + background: rgba(102, 126, 234, 0.1); + border-color: $primary-color; + } +} + +.add-spec-text { + font-size: 24rpx; + color: $primary-color; + font-weight: 500; +} diff --git a/subPackages/orderQy/detail.vue b/subPackages/orderQy/detail.vue index 0c92641..2454f60 100644 --- a/subPackages/orderQy/detail.vue +++ b/subPackages/orderQy/detail.vue @@ -53,8 +53,11 @@ > - - + + @@ -62,14 +65,32 @@ {{ goods.description || goods.spec }} + 数量:{{ goods.quantity || 1 }} - + + + + + 订单金额 + ¥{{ orderDetail.goodsAmount }} + + + 运费 + ¥{{ orderDetail.shippingFee || "5.00" }} + + @@ -690,7 +711,7 @@ export default { font-size: 28rpx; font-weight: 600; color: #333; - margin-bottom: 20rpx; + margin-bottom: 0; } // 商品列表 @@ -717,12 +738,12 @@ export default { } .checkbox-icon { - width: 150rpx; - height:150rpx; - image{ - width: 100%; - height: 100%; - border-radius: 10rpx; + width: 100rpx; + height: 100rpx; + image { + width: 100%; + height: 100%; + border-radius: 10rpx; } } @@ -749,6 +770,13 @@ export default { font-size: 24rpx; color: #666; line-height: 1.4; + margin-bottom: 8rpx; +} + +.goods-quantity { + font-size: 22rpx; + color: #999; + font-weight: 500; } .goods-actions { @@ -761,22 +789,50 @@ export default { font-size: 24rpx; border: none; - &.btn-view { - background-color: #f0f0f0; - color: #666; - } + padding: 0rpx 20rpx; + border-radius: 10rpx; + font-size: 24rpx; + font-weight: 600; + border: none; + color: #333333; + transition: all 0.3s ease; + min-width: 100rpx; + text-align: center; + background-color: #77f3f9; + height: 55rpx; + line-height: 55rpx; +} - &.btn-logistics { - background-color: #007aff; - color: #fff; - } +// 金额汇总 +.amount-summary { + padding: 20rpx 30rpx; + border-top: 1rpx solid #f0f0f0; + background-color: white; +} - &.btn-used { - background-color: #34c759; - color: #fff; +.summary-row { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 12rpx; + + &:last-child { + margin-bottom: 0; } } +.summary-label { + font-size: 26rpx; + color: #666; + font-weight: 500; +} + +.summary-value { + font-size: 26rpx; + color: #333; + font-weight: 600; +} + // 订单信息 .order-info-section { background-color: #fff; @@ -844,21 +900,18 @@ export default { .action-btn { flex: 1; - height: 80rpx; - border-radius: 40rpx; - font-size: 28rpx; - border: none; + padding: 0rpx 20rpx; + border-radius: 10rpx; + font-size: 24rpx; font-weight: 600; - - &.secondary { - background-color: #f0f0f0; - color: #666; - } - - &.primary { - background-color: #333; - color: #fff; - } + border: none; + color: #333333; + transition: all 0.3s ease; + min-width: 100rpx; + text-align: center; + background-color: #77f3f9; + height: 55rpx; + line-height: 55rpx; } } diff --git a/subPackages/orderQy/list.vue b/subPackages/orderQy/list.vue index 2e24388..7fe9661 100644 --- a/subPackages/orderQy/list.vue +++ b/subPackages/orderQy/list.vue @@ -4,7 +4,7 @@ - - - - 订单号 - {{ order.orderNo }} - - - - - {{ getStatusText(order.status) }} - - - - 📦 {{ order.packageName }} + {{ getStatusText(order.status) }} - 商品清单 - + {{ goods.name }} {{ getGoodsTypeName(goods.type) }} + 数量:{{ goods.quantity || 1 }} @@ -86,10 +79,6 @@ - - 下单时间 - {{ formatTime(order.createTime) }} - 实付金额 ¥{{ order.totalAmount }} @@ -101,7 +90,6 @@ @click.stop="showEquityCode(order)" v-if="order.status !== 0" > - 🎫 权益码 @@ -189,7 +177,10 @@ export default { }, }; }, - onLoad() { + onLoad(e) { + if(e.status){ + this.currentTab = e.status + } this.loadOrderList(); }, methods: { @@ -330,6 +321,9 @@ export default { title: "查看数字资产", icon: "none", }); + uni.navigateTo({ + url:'/subPackages/memorialAlbum/detail' + }) }, // 预约发货 @@ -505,8 +499,9 @@ $bg-light: #f7fafc; // Tab样式 .tab-container { display: flex; - background-color: $primary-color; + background-color: #ffffff; border-bottom: 1px solid rgba(255, 255, 255, 0.1); + color: black; position: sticky; top: 0; z-index: 10; @@ -518,10 +513,11 @@ $bg-light: #f7fafc; text-align: center; position: relative; transition: all 0.3s ease; + color: #333333; &.active { .tab-text { - color: #ffffff; + color: #77f3f9; font-weight: 600; } @@ -533,21 +529,21 @@ $bg-light: #f7fafc; transform: translateX(-50%); width: 60rpx; height: 4rpx; - background-color: #ffffff; + background-color: #77f3f9; border-radius: 2rpx; } } &:not(.active) { .tab-text { - opacity: 0.7; + opacity: 1; } } } .tab-text { font-size: 26rpx; - color: #ffffff; + color: #333333; font-weight: 600; transition: all 0.3s ease; } @@ -647,22 +643,28 @@ $bg-light: #f7fafc; // 权益商品包 .package-section { display: flex; + justify-content: space-between; align-items: center; - padding: 20rpx 28rpx; - margin: 0 20rpx; - margin-top: -6rpx; -} - -.package-icon { - font-size: 36rpx; - margin-right: 20rpx; + padding: 20rpx 20rpx; } .package-name { + flex: 1; font-size: 30rpx; color: $text-primary; font-weight: 600; letter-spacing: 0.5rpx; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + margin-right: 20rpx; +} + +.status-name { + font-size: 26rpx; + color: $text-secondary; + font-weight: 500; + flex-shrink: 0; } // 商品部分 @@ -718,7 +720,7 @@ $bg-light: #f7fafc; .goods-name { display: block; - font-size: 30rpx; + font-size: 26rpx; color: $text-primary; font-weight: 600; margin-bottom: 12rpx; @@ -737,10 +739,17 @@ $bg-light: #f7fafc; .goods-type { font-size: 24rpx; color: $text-secondary; - background: $secondary-color; - padding: 8rpx 16rpx; + // background: $secondary-color; + // padding: 8rpx 16rpx; border-radius: 20rpx; font-weight: 500; + margin-right: 16rpx; +} + +.goods-quantity { + font-size: 22rpx; + color: $text-muted; + font-weight: 500; } .goods-price { @@ -753,30 +762,32 @@ $bg-light: #f7fafc; .goods-action { .action-btn { padding: 0rpx 20rpx; - border-radius: 20rpx; + border-radius: 10rpx; font-size: 24rpx; font-weight: 600; border: none; - color: #ffffff; + color: #333333; transition: all 0.3s ease; min-width: 100rpx; text-align: center; - + background-color: #77f3f9; + height: 55rpx; + line-height: 55rpx; &:active { transform: scale(0.95); } - &.btn-view { - background: $primary-color; - } + // &.btn-view { + // background: $primary-color; + // } - &.btn-reserve { - background: $warning-color; - } + // &.btn-reserve { + // background: $warning-color; + // } - &.btn-use { - background: $success-color; - } + // &.btn-use { + // background: $success-color; + // } } } @@ -786,7 +797,7 @@ $bg-light: #f7fafc; justify-content: space-between; align-items: center; padding: 24rpx 28rpx; - background: $secondary-color; + background: white; margin-top: 20rpx; } @@ -798,13 +809,11 @@ $bg-light: #f7fafc; .order-time-section, .order-total-section { - display: flex; - flex-direction: column; - gap: 6rpx; } .time-label, .total-label { + margin-right: 10rpx; font-size: 22rpx; color: $text-muted; font-weight: 500; @@ -832,15 +841,15 @@ $bg-light: #f7fafc; align-items: center; gap: 10rpx; padding: 2rpx 24rpx; - background: $primary-color; - color: #ffffff; - border-radius: 24rpx; + background: white; + color: #333333; + border-radius: 10rpx; font-size: 24rpx; font-weight: 600; - border: none; + border: 1rpx solid #77f3f9; transition: all 0.3s ease; - box-shadow: 0 2rpx 8rpx rgba(102, 126, 234, 0.2); - + height: 55rpx; + line-height: 55rpx; &:active { transform: scale(0.95); } diff --git a/subPackages/user/collection.vue b/subPackages/user/collection.vue new file mode 100644 index 0000000..617a1fb --- /dev/null +++ b/subPackages/user/collection.vue @@ -0,0 +1,408 @@ + + + + + + + diff --git a/utils/request.js b/utils/request.js index a153675..5654641 100644 --- a/utils/request.js +++ b/utils/request.js @@ -10,9 +10,9 @@ * @returns {Promise} - 返回Promise对象 */ -const DOMAIN = 'https://m.dayunyuanjian.com'; - export const request = (options = {}) => { + const DOMAIN = 'https://m.dayunyuanjian.com'; + return new Promise((resolve, reject) => { options.url = options.url.startsWith('/') ? `${DOMAIN}${options.url}` : options.url; // 默认配置