diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/car_front.iml b/.idea/car_front.iml new file mode 100644 index 0000000..c956989 --- /dev/null +++ b/.idea/car_front.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..5af3735 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/php.xml b/.idea/php.xml new file mode 100644 index 0000000..f324872 --- /dev/null +++ b/.idea/php.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app.json b/app.json index 042e029..1198b19 100644 --- a/app.json +++ b/app.json @@ -1,7 +1,8 @@ { "pages": [ "pages/index/index", - "pages/logs/logs" + "pages/info/info", + "pages/car_new/car_new" ], "window": { "navigationBarTextStyle": "black", @@ -12,4 +13,4 @@ "componentFramework": "glass-easel", "sitemapLocation": "sitemap.json", "lazyCodeLoading": "requiredComponents" -} +} \ No newline at end of file diff --git a/pages/car_new/car_new.js b/pages/car_new/car_new.js new file mode 100644 index 0000000..2768d21 --- /dev/null +++ b/pages/car_new/car_new.js @@ -0,0 +1,203 @@ +const request = require('../../utils/request'); +Page({ + data: { + carList: [], + selectedSort: 'default', + selectedBrand: '', + selectedPrice: '', + filterParams: {}, + mainActiveIndex: 0, + selectedSeriesId: null, + selectedBrandLabel:"品牌", + brandTree: [], + sortOptions: [ + { text: '默认排序', value: 'default' }, + { text: '价格升序', value: 'priceAsc' }, + { text: '价格降序', value: 'priceDesc' } + ], + priceOptions: [ + { text: '全部价格', value: '' }, + { text: '5万以下', value: '<5' }, + { text: '5-10万', value: '5-10'}, + { text: '10万以上', value: '>10' } + ], + extendFields: [] // 筛选配置 + }, + onBrandClick(e) { + const index = e.detail.index; + const brand = this.data.brandTree[index]; + this.setData({ + mainActiveIndex: e.detail.index + }); + // ✅ 如果该品牌没有子系列(children) + if (!brand.children || brand.children.length === 0) { + this.setData({ + selectedSeriesId: null, // 没有选中的 series + selectedBrandLabel: brand.text + }); + + this.reloadList(); // 触发列表加载 + this.selectComponent('#dropdownItemBrand').toggle(false); // 关闭下拉菜单 + } + }, + + onSeriesSelect(e) { + const selectedId = e.detail.id; + const selectedText = e.detail.text; + + this.setData({ + selectedSeriesId: selectedId, + selectedBrandLabel: selectedText // ✅ 更新 dropdown 显示的值 + }); + + this.reloadList(); + this.selectComponent('#dropdownItemBrand').toggle(false); // 关闭 + // TODO: 发起请求,用 selectedId 作为筛选条件 + }, + onSortChange(e) { + this.setData({ selectedSort: e.detail }); + this.reloadList(); + }, + onPriceChange(e) { + this.setData({ selectedPrice: e.detail }); + this.reloadList(); + }, + onParamChange(e) { + const value = e.detail.value; + this.setData({ selectedParam: value }); + this.reloadList(); + }, + + async reloadList() { + // TODO: 根据筛选值重新加载列表 + const data = { + sort:this.data.selectedSort, + brand:this.data.selectedSeriesId, + price:this.data.selectedPrice, + attr:this.data.filterParams, + } + try { + const raw = await request({ + url: '/admin/wechat/api/car', + method: 'POST', + data: data + }); + this.setData({carList:raw.items}) + } catch (err) { + console.error('加载品牌失败', err); + } + }, + openMap() { + const { latitude, longitude, address, name } = this.data.company + wx.openLocation({ + latitude, + longitude, + scale: 18, + name, + address + }) + }, + onLoad(){ + this.loadBrandData(); + }, + async loadBrandData() { + try { + const raw = await request({ + url: '/admin/wechat/api/select' + }); + + const brandTree = raw.brands.map(brand => ({ + text: brand.label, + children: (brand.children || []).map(series => ({ + id: series.value, + text: series.label + })) + })); + + const fields = raw.extend.map(f => { + // 为 range 类型添加 start/end 临时字段 + if (f.type === 'range') { + f._rangeStart = ''; + f._rangeEnd = ''; + } else if (f.type === 'checkbox') { + f.value = []; // 默认空数组 + } + return f; + }); + this.setData({ extendFields:fields }); + this.setData({ brandTree }); + this.reloadList(); + } catch (err) { + console.error('加载品牌失败', err); + } + }, + + onTagToggle(e) { + const name = e.currentTarget.dataset.name; + const value = String(e.currentTarget.dataset.value); + + const fields = this.data.extendFields.map(field => { + if (field.name === name) { + let list = (field.value || []).map(String); + const index = list.indexOf(value); + if (index > -1) { + list.splice(index, 1); + } else { + list.push(value); + } + field.value = list; + + // ✅ 同步 checked 状态 + field.options.forEach(opt => { + opt._checked = list.includes(String(opt.value)); + }); + } + return field; + }); + + this.setData({ extendFields: fields }); + }, + goToCarDetail(e) { + const id = e.currentTarget.dataset.id; + console.log(`/pages/info/info?id=${id}`) + wx.navigateTo({ + url: `/pages/info/info?id=${id}` + }); + }, + onSliderChange(e) { + const name = e.currentTarget.dataset.name; + const [start, end] = e.detail; + + const fields = this.data.extendFields.map(field => { + if (field.name === name) { + field._rangeStart = start; + field._rangeEnd = end; + } + return field; + }); + + this.setData({ extendFields: fields }); + }, + + onExtendConfirm() { + const filterParams = {}; + + this.data.extendFields.forEach(field => { + if (field.type === 'checkbox') { + if (field.value?.length > 0) { + filterParams[field.name] = field.value; + } + } else if (field.type === 'range') { + if (field._rangeStart || field._rangeEnd) { + filterParams[field.name] = { + start: field._rangeStart, + end: field._rangeEnd + }; + } + } + }); + this.selectComponent('#dropdownItemParam').toggle(false); // 关闭 + this.setData({filterParams:filterParams}); + this.reloadList(); + } +}) diff --git a/pages/car_new/car_new.json b/pages/car_new/car_new.json new file mode 100644 index 0000000..91d054c --- /dev/null +++ b/pages/car_new/car_new.json @@ -0,0 +1,11 @@ +{ + "usingComponents": { + "van-icon": "@vant/weapp/icon/index", + "van-dropdown-menu": "@vant/weapp/dropdown-menu/index", + "van-dropdown-item": "@vant/weapp/dropdown-item/index", + "van-tree-select": "@vant/weapp/tree-select/index", + "van-slider": "@vant/weapp/slider/index", + "van-tag": "@vant/weapp/tag/index", + "van-button": "@vant/weapp/button/index" + } +} \ No newline at end of file diff --git a/pages/car_new/car_new.wxml b/pages/car_new/car_new.wxml new file mode 100644 index 0000000..00ec598 --- /dev/null +++ b/pages/car_new/car_new.wxml @@ -0,0 +1,156 @@ + + + + + + + + + + + + {{item.label}} + + + + + + {{opt.key}} + + + + + + + + + {{item.label}}:{{item._rangeStart || item.options.start}}{{item.options.unit}} - {{item._rangeEnd || item.options.end}}{{item.options.unit}} + + + + + + + 确认 + + + + + + + + + + + 新车 + 租车 + 二手车 + + + + + + {{item.title}} + + + + ¥{{item.price}}万起 + 指导价 ¥{{item.re_price}}万 + + + + + ¥{{item.price}}/天 + 月租 ¥{{item.re_price}} + + + + + ¥{{item.price}}万 + 新车价 ¥{{item.re_price}}万 + + + + + + + + {{opt}} + + 全新上市 + 限时优惠 + + + + + + {{opt}} + + 现车可租 + 含保险 + + + + + + {{opt}} + + {{item.mileage}}万公里 + {{item.car_age}}年车龄 + 官方认证 + + + + + + + {{item.dealer_name}} + + + 取车点:{{item.pickup_location}} + + + + 首次上牌:{{item.first_license_date}} + 质保剩余:{{item.warranty_remain}} + + + + + \ No newline at end of file diff --git a/pages/car_new/car_new.wxss b/pages/car_new/car_new.wxss new file mode 100644 index 0000000..3ae7db9 --- /dev/null +++ b/pages/car_new/car_new.wxss @@ -0,0 +1,380 @@ + +/* 筛选栏样式 */ +.sticky-filter { + background: #ffffff; + box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08); + overflow: hidden; + position: sticky; + top: 0; + z-index: 100; +} + +/* 筛选扩展面板 */ +.filter-extend { + padding: 32rpx 24rpx; + background: #ffffff; + max-height: 80vh; + overflow-y: auto; +} + +.filter-group { + margin-bottom: 32rpx; +} + +.filter-label { + font-size: 32rpx; + font-weight: 600; + color: #2c3e50; + margin-bottom: 16rpx; + position: relative; + padding-left: 12rpx; +} + +.filter-label::before { + content: ''; + position: absolute; + left: 0; + top: 50%; + transform: translateY(-50%); + width: 6rpx; + height: 24rpx; + background: linear-gradient(135deg, #667eea, #764ba2); + border-radius: 3rpx; +} + +/* 标签筛选样式 */ +.filter-tags { + display: flex; + flex-wrap: wrap; + gap: 12rpx; +} + +.filter-tag-item { + transition: all 0.3s ease; +} + +.filter-tag-item:active { + transform: scale(0.95); +} + +.mytag { + transition: all 0.3s ease; + border-radius: 20rpx !important; + font-size: 26rpx !important; + padding: 8rpx 16rpx !important; + border: 2rpx solid #e1e8ed !important; +} + + +.mytag[type="success"] { + background: linear-gradient(135deg, #11998e, #38ef7d) !important; + border-color: #11998e !important; + color: #ffffff !important; + box-shadow: 0 4rpx 12rpx rgba(17, 153, 142, 0.3); +} + +/* 滑块筛选样式 */ +.filter-slider-group { + padding: 24rpx; + background: #f8f9fa; + border-radius: 16rpx; + border: 2rpx solid #e9ecef; +} + +.slider-label { + font-size: 28rpx; + color: #495057; + margin-bottom: 20rpx; + font-weight: 500; + text-align: center; +} + +/* 确认按钮样式 */ +.filter-extend .van-button { + background: linear-gradient(135deg, #667eea, #764ba2) !important; + border: none !important; + border-radius: 20rpx !important; + font-weight: 600 !important; + font-size: 32rpx !important; + padding: 20rpx 0 !important; + box-shadow: 0 8rpx 24rpx rgba(102, 126, 234, 0.3); + margin-top: 24rpx; +} + +/* 汽车列表样式 */ +.car-list { + padding: 24rpx; + padding-top: 16rpx; +} + +.car-item { + background: #ffffff; + border-radius: 24rpx; + margin-bottom: 24rpx; + overflow: hidden; + box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.06); + transition: all 0.3s ease; + position: relative; +} + +.car-item::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, transparent 0%, rgba(102, 126, 234, 0.05) 100%); + opacity: 0; + transition: opacity 0.3s ease; + pointer-events: none; +} + +.car-item:active { + transform: translateY(-4rpx); + box-shadow: 0 16rpx 48rpx rgba(0, 0, 0, 0.12); +} + +.car-item:active::before { + opacity: 1; +} + +.car-image { + width: 100%; + height: 300rpx; + background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); + position: relative; +} + +.car-info { + padding: 24rpx; + position: relative; +} + +.car-title { + font-size: 32rpx; + font-weight: 700; + color: #2c3e50; + margin-bottom: 16rpx; + line-height: 1.4; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.car-price { + display: flex; + align-items: baseline; + gap: 12rpx; + margin-bottom: 20rpx; +} + +.price-new { + font-size: 36rpx; + font-weight: 800; + background: linear-gradient(135deg, #667eea, #764ba2); + background-clip: text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + color: #667eea; +} + +.price-old { + font-size: 26rpx; + color: #95a5a6; + text-decoration: line-through; + position: relative; +} + +.price-old::after { + content: ''; + position: absolute; + top: 50%; + left: 0; + right: 0; + height: 2rpx; + background: #95a5a6; +} + +.car-attrs { + display: flex; + flex-wrap: wrap; + gap: 8rpx; +} + +.car-attrs .van-tag { + background: linear-gradient(135deg, #ffeaa7, #fab1a0) !important; + color: #2d3436 !important; + border: none !important; + border-radius: 12rpx !important; + font-size: 22rpx !important; + padding: 6rpx 12rpx !important; + font-weight: 500 !important; + box-shadow: 0 2rpx 8rpx rgba(250, 177, 160, 0.3); +} + +.car-attrs .van-tag:nth-child(2n) { + background: linear-gradient(135deg, #a8e6cf, #88d8c0) !important; + box-shadow: 0 2rpx 8rpx rgba(136, 216, 192, 0.3); +} + +.car-attrs .van-tag:nth-child(3n) { + background: linear-gradient(135deg, #ffd3a5, #fd9853) !important; + box-shadow: 0 2rpx 8rpx rgba(253, 152, 83, 0.3); +} + +/* 下拉菜单优化 */ +.van-dropdown-menu { + border-radius: 24rpx 24rpx 0 0; + overflow: hidden; +} + +.van-dropdown-menu__item { + font-weight: 500; + color: #2c3e50; +} + +/* 树形选择器优化 */ +.van-tree-select { + border-radius: 0 0 24rpx 24rpx; + overflow: hidden; +} + +/* 响应式优化 */ +@media (max-width: 750rpx) { + .company-actions { + flex-direction: column; + gap: 8rpx; + } + + .company-actions .van-button { + max-width: 100%; + min-height: 64rpx; + } + + .filter-tags { + justify-content: center; + } + + .car-price { + flex-direction: column; + align-items: flex-start; + gap: 8rpx; + } +} + +/* 更小屏幕的额外优化 */ +@media (max-width: 600rpx) { + .company-actions .van-button { + font-size: 24rpx !important; + padding: 10rpx 6rpx !important; + } + + .company-actions .van-button .van-icon { + font-size: 24rpx !important; + margin-right: 4rpx !important; + } +} + +/* 动画效果 */ +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(30rpx); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.car-item { + animation: fadeInUp 0.5s ease-out; +} + +.car-item:nth-child(n+2) { + animation-delay: 0.1s; +} + +.car-item:nth-child(n+3) { + animation-delay: 0.2s; +} + +/* 滚动条样式 */ +::-webkit-scrollbar { + width: 8rpx; +} + +::-webkit-scrollbar-track { + background: #f1f1f1; + border-radius: 4rpx; +} + +::-webkit-scrollbar-thumb { + background: linear-gradient(135deg, #667eea, #764ba2); + border-radius: 4rpx; +} + +::-webkit-scrollbar-thumb:hover { + background: linear-gradient(135deg, #5a6fd8, #6a4190); +} +.car-type-badge { + position: absolute; + top: 20rpx; + right: 20rpx; + z-index: 10; +} +.badge-new { + background: linear-gradient(135deg, #1989fa, #40a9ff); + color: white; + padding: 8rpx 16rpx; + border-radius: 20rpx; + font-size: 22rpx; + font-weight: 600; +} + +.badge-rent { + background: linear-gradient(135deg, #07c160, #52c41a); + color: white; + padding: 8rpx 16rpx; + border-radius: 20rpx; + font-size: 22rpx; + font-weight: 600; +} + +.badge-used { + background: linear-gradient(135deg, #ff976a, #ffa940); + color: white; + padding: 8rpx 16rpx; + border-radius: 20rpx; + font-size: 22rpx; + font-weight: 600; +} +/* 租车价格 */ +.car-type-2 .price-rent { + color: #07c160; + font-size: 36rpx; + font-weight: 700; + margin-right: 16rpx; +} + +.car-type-2 .price-monthly { + color: #666; + font-size: 24rpx; +} + +/* 二手车价格 */ +.car-type-3 .price-used { + color: #ff976a; + font-size: 36rpx; + font-weight: 700; + margin-right: 16rpx; +} + +.car-type-3 .price-original { + color: #999; + font-size: 24rpx; +} + + diff --git a/pages/index/index.js b/pages/index/index.js index 53b8db1..32f89f5 100644 --- a/pages/index/index.js +++ b/pages/index/index.js @@ -12,185 +12,26 @@ Page({ latitude: 31.2304, // 地图坐标 longitude: 121.4737, phone: '021-88888888' + } + }, + // 跳转到新车页面 + goToNewCar: function() { + wx.navigateTo({ + url: '/pages/car_new/car_new' + }); }, - carList: [], - selectedSort: 'default', - selectedBrand: '', - selectedPrice: '', - filterParams: {}, - mainActiveIndex: 0, - selectedSeriesId: null, - selectedBrandLabel:"品牌", - brandTree: [], - sortOptions: [ - { text: '默认排序', value: 'default' }, - { text: '价格升序', value: 'priceAsc' }, - { text: '价格降序', value: 'priceDesc' } - ], - priceOptions: [ - { text: '全部价格', value: '' }, - { text: '5万以下', value: '<5' }, - { text: '5-10万', value: '5-10' }, - { text: '10万以上', value: '>10' } - ], - extendFields: [] // 筛选配置 - }, - onBrandClick(e) { - this.setData({ - mainActiveIndex: e.detail.index - }); - }, - - onSeriesSelect(e) { - const selectedId = e.detail.id; - const selectedText = e.detail.text; - this.setData({ - selectedSeriesId: selectedId, - selectedBrandLabel: selectedText // ✅ 更新 dropdown 显示的值 - }); - - this.reloadList(); - this.selectComponent('#dropdownItemBrand').toggle(false); // 关闭 - // TODO: 发起请求,用 selectedId 作为筛选条件 - }, - onSortChange(e) { - this.setData({ selectedSort: e.detail }); - this.reloadList(); - }, - onPriceChange(e) { - this.setData({ selectedPrice: e.detail }); - this.reloadList(); - }, - onParamChange(e) { - const value = e.detail.value; - this.setData({ selectedParam: value }); - this.reloadList(); - }, - - async reloadList() { - // TODO: 根据筛选值重新加载列表 - const data = { - sort:this.data.selectedSort, - brand:this.data.selectedSeriesId, - price:this.data.selectedPrice, - attr:this.data.filterParams, - } - try { - const raw = await request({ - url: '/admin/wechat/api/car', - method: 'POST', - data: data + // 跳转到租车页面 + goToRental: function() { + wx.navigateTo({ + url: '/pages/rental/rental' }); - this.setData({carList:raw.items}) - } catch (err) { - console.error('加载品牌失败', err); - } - }, - openMap() { - const { latitude, longitude, address, name } = this.data.company - wx.openLocation({ - latitude, - longitude, - scale: 18, - name, - address - }) - }, - onLoad(){ - this.loadBrandData(); - }, - async loadBrandData() { - try { - const raw = await request({ - url: '/admin/wechat/api/select' + }, + + // 跳转到二手车页面 + goToUsedCar: function() { + wx.navigateTo({ + url: '/pages/usedcar/usedcar' }); - - const brandTree = raw.brands.map(brand => ({ - text: brand.label, - children: (brand.children || []).map(series => ({ - id: series.value, - text: series.label - })) - })); - - const fields = raw.extend.map(f => { - // 为 range 类型添加 start/end 临时字段 - if (f.type === 'range') { - f._rangeStart = ''; - f._rangeEnd = ''; - } else if (f.type === 'checkbox') { - f.value = []; // 默认空数组 - } - return f; - }); - this.setData({ extendFields:fields }); - this.setData({ brandTree }); - this.reloadList(); - } catch (err) { - console.error('加载品牌失败', err); - } - }, - - onTagToggle(e) { - const name = e.currentTarget.dataset.name; - const value = String(e.currentTarget.dataset.value); - - const fields = this.data.extendFields.map(field => { - if (field.name === name) { - let list = (field.value || []).map(String); - const index = list.indexOf(value); - if (index > -1) { - list.splice(index, 1); - } else { - list.push(value); - } - field.value = list; - - // ✅ 同步 checked 状态 - field.options.forEach(opt => { - opt._checked = list.includes(String(opt.value)); - }); - } - return field; - }); - - this.setData({ extendFields: fields }); - }, - onSliderChange(e) { - const name = e.currentTarget.dataset.name; - const [start, end] = e.detail; - - const fields = this.data.extendFields.map(field => { - if (field.name === name) { - field._rangeStart = start; - field._rangeEnd = end; - } - return field; - }); - - this.setData({ extendFields: fields }); - }, - - onExtendConfirm() { - const filterParams = {}; - - this.data.extendFields.forEach(field => { - if (field.type === 'checkbox') { - if (field.value?.length > 0) { - filterParams[field.name] = field.value; - } - } else if (field.type === 'range') { - if (field._rangeStart || field._rangeEnd) { - filterParams[field.name] = { - start: field._rangeStart, - end: field._rangeEnd - }; - } - } - }); - this.selectComponent('#dropdownItemParam').toggle(false); // 关闭 - this.setData({filterParams:filterParams}); - this.reloadList(); - } + }, }) diff --git a/pages/index/index.wxml b/pages/index/index.wxml index a7e8db9..d04bfeb 100644 --- a/pages/index/index.wxml +++ b/pages/index/index.wxml @@ -1,3 +1,4 @@ +