详情
This commit is contained in:
parent
a241484705
commit
90ece932c9
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
|
|
@ -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
|
||||||
8
.idea/car_front.iml
Normal file
8
.idea/car_front.iml
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/car_front.iml" filepath="$PROJECT_DIR$/.idea/car_front.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
19
.idea/php.xml
Normal file
19
.idea/php.xml
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="MessDetectorOptionsConfiguration">
|
||||||
|
<option name="transferred" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PHPCSFixerOptionsConfiguration">
|
||||||
|
<option name="transferred" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PHPCodeSnifferOptionsConfiguration">
|
||||||
|
<option name="highlightLevel" value="WARNING" />
|
||||||
|
<option name="transferred" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PhpStanOptionsConfiguration">
|
||||||
|
<option name="transferred" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PsalmOptionsConfiguration">
|
||||||
|
<option name="transferred" value="true" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
3
app.json
3
app.json
|
|
@ -1,7 +1,8 @@
|
||||||
{
|
{
|
||||||
"pages": [
|
"pages": [
|
||||||
"pages/index/index",
|
"pages/index/index",
|
||||||
"pages/logs/logs"
|
"pages/info/info",
|
||||||
|
"pages/car_new/car_new"
|
||||||
],
|
],
|
||||||
"window": {
|
"window": {
|
||||||
"navigationBarTextStyle": "black",
|
"navigationBarTextStyle": "black",
|
||||||
|
|
|
||||||
203
pages/car_new/car_new.js
Normal file
203
pages/car_new/car_new.js
Normal file
|
|
@ -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();
|
||||||
|
}
|
||||||
|
})
|
||||||
11
pages/car_new/car_new.json
Normal file
11
pages/car_new/car_new.json
Normal file
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
156
pages/car_new/car_new.wxml
Normal file
156
pages/car_new/car_new.wxml
Normal file
|
|
@ -0,0 +1,156 @@
|
||||||
|
<!--pages/car_new/car_new.wxml-->
|
||||||
|
<view class="sticky-filter">
|
||||||
|
<van-dropdown-menu>
|
||||||
|
<van-dropdown-item
|
||||||
|
value="{{selectedSort}}"
|
||||||
|
options="{{sortOptions}}"
|
||||||
|
bind:change="onSortChange"
|
||||||
|
/>
|
||||||
|
<van-dropdown-item id="dropdownItemBrand" title="{{selectedBrandLabel}}" use-slot>
|
||||||
|
<van-tree-select
|
||||||
|
height="400"
|
||||||
|
items="{{brandTree}}"
|
||||||
|
main-active-index="{{mainActiveIndex}}"
|
||||||
|
active-id="{{selectedSeriesId}}"
|
||||||
|
bind:click-nav="onBrandClick"
|
||||||
|
bind:click-item="onSeriesSelect"
|
||||||
|
/>
|
||||||
|
</van-dropdown-item>
|
||||||
|
<van-dropdown-item
|
||||||
|
value="{{selectedPrice}}"
|
||||||
|
options="{{priceOptions}}"
|
||||||
|
bind:change="onPriceChange"
|
||||||
|
/>
|
||||||
|
<van-dropdown-item title="参数"
|
||||||
|
use-slot
|
||||||
|
id="dropdownItemParam"
|
||||||
|
>
|
||||||
|
<view class="filter-extend">
|
||||||
|
<view wx:for="{{extendFields}}" wx:key="id" class="filter-group">
|
||||||
|
<view class="filter-label">{{item.label}}</view>
|
||||||
|
|
||||||
|
<!-- 多选项字段 -->
|
||||||
|
<view wx:if="{{item.type === 'checkbox'}}" class="filter-tags">
|
||||||
|
<view
|
||||||
|
wx:for="{{item.options}}"
|
||||||
|
wx:for-item="opt"
|
||||||
|
wx:key="index"
|
||||||
|
class="filter-tag-item"
|
||||||
|
data-name="{{item.name}}"
|
||||||
|
data-value="{{opt.value}}"
|
||||||
|
bind:tap="onTagToggle"
|
||||||
|
>
|
||||||
|
<van-tag
|
||||||
|
size="medium"
|
||||||
|
plain="{{!opt._checked}}"
|
||||||
|
>
|
||||||
|
{{opt.key}}
|
||||||
|
</van-tag>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<view wx:if="{{item.type === 'range'}}" class="filter-slider-group">
|
||||||
|
<view class="slider-label">
|
||||||
|
{{item.label}}:{{item._rangeStart || item.options.start}}{{item.options.unit}} - {{item._rangeEnd || item.options.end}}{{item.options.unit}}
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<van-slider
|
||||||
|
range
|
||||||
|
value="{{[item._rangeStart ? item._rangeStart : item.options.start, item._rangeEnd ? item._rangeEnd : item.options.end]}}"
|
||||||
|
min="{{item.options.start}}"
|
||||||
|
max="{{item.options.end}}"
|
||||||
|
data-name="{{item.name}}"
|
||||||
|
bind:change="onSliderChange"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<van-button type="primary" block size="small" bind:tap="onExtendConfirm">确认</van-button>
|
||||||
|
</view>
|
||||||
|
</van-dropdown-item>
|
||||||
|
</van-dropdown-menu>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 汽车列表 -->
|
||||||
|
<view class="car-list">
|
||||||
|
<view wx:for="{{carList}}" wx:key="id" class="car-item car-type-{{item.car_type}}" bindtap="goToCarDetail" data-id="{{item.id}}">
|
||||||
|
<!-- 车辆类型标签 -->
|
||||||
|
<view class="car-type-badge">
|
||||||
|
<text wx:if="{{item.car_type == 1}}" class="badge-new">新车</text>
|
||||||
|
<text wx:elif="{{item.car_type == 2}}" class="badge-rent">租车</text>
|
||||||
|
<text wx:elif="{{item.car_type == 3}}" class="badge-used">二手车</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<image class="car-image" src="{{item.cover_image[0]}}" mode="aspectFill" />
|
||||||
|
|
||||||
|
<view class="car-info">
|
||||||
|
<view class="car-title">{{item.title}}</view>
|
||||||
|
|
||||||
|
<!-- 新车价格显示 -->
|
||||||
|
<view wx:if="{{item.car_type == 1}}" class="car-price">
|
||||||
|
<text class="price-new">¥{{item.price}}万起</text>
|
||||||
|
<text wx:if="{{item.re_price}}" class="price-old">指导价 ¥{{item.re_price}}万</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 租车价格显示 -->
|
||||||
|
<view wx:elif="{{item.car_type == 2}}" class="car-price">
|
||||||
|
<text class="price-rent">¥{{item.price}}/天</text>
|
||||||
|
<text wx:if="{{item.re_price}}" class="price-monthly">月租 ¥{{item.re_price}}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 二手车价格显示 -->
|
||||||
|
<view wx:elif="{{item.car_type == 3}}" class="car-price">
|
||||||
|
<text class="price-used">¥{{item.price}}万</text>
|
||||||
|
<text wx:if="{{item.re_price}}" class="price-original">新车价 ¥{{item.re_price}}万</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 车辆特性标签 -->
|
||||||
|
<view class="car-attrs">
|
||||||
|
<!-- 新车特性 -->
|
||||||
|
<block wx:if="{{item.car_type == 1}}">
|
||||||
|
<van-tag wx:for="{{item.attr}}" wx:key="index" wx:for-item="opt" type="primary" size="mini">
|
||||||
|
{{opt}}
|
||||||
|
</van-tag>
|
||||||
|
<van-tag wx:if="{{item.is_new_model}}" type="success" size="mini">全新上市</van-tag>
|
||||||
|
<van-tag wx:if="{{item.has_discount}}" type="warning" size="mini">限时优惠</van-tag>
|
||||||
|
</block>
|
||||||
|
|
||||||
|
<!-- 租车特性 -->
|
||||||
|
<block wx:elif="{{item.car_type == 2}}">
|
||||||
|
<van-tag wx:for="{{item.attr}}" wx:key="index" wx:for-item="opt" type="success" size="mini">
|
||||||
|
{{opt}}
|
||||||
|
</van-tag>
|
||||||
|
<van-tag wx:if="{{item.available_now}}" type="primary" size="mini">现车可租</van-tag>
|
||||||
|
<van-tag wx:if="{{item.insurance_included}}" type="default" size="mini">含保险</van-tag>
|
||||||
|
</block>
|
||||||
|
|
||||||
|
<!-- 二手车特性 -->
|
||||||
|
<block wx:elif="{{item.car_type == 3}}">
|
||||||
|
<van-tag wx:for="{{item.attr}}" wx:key="index" wx:for-item="opt" type="warning" size="mini">
|
||||||
|
{{opt}}
|
||||||
|
</van-tag>
|
||||||
|
<van-tag wx:if="{{item.mileage}}" type="default" size="mini">{{item.mileage}}万公里</van-tag>
|
||||||
|
<van-tag wx:if="{{item.car_age}}" type="default" size="mini">{{item.car_age}}年车龄</van-tag>
|
||||||
|
<van-tag wx:if="{{item.certified}}" type="success" size="mini">官方认证</van-tag>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 额外信息 -->
|
||||||
|
<view class="car-extra">
|
||||||
|
<!-- 新车额外信息 -->
|
||||||
|
<text wx:if="{{item.car_type == 1 && item.dealer_name}}" class="dealer-info">{{item.dealer_name}}</text>
|
||||||
|
|
||||||
|
<!-- 租车额外信息 -->
|
||||||
|
<text wx:elif="{{item.car_type == 2 && item.pickup_location}}" class="pickup-info">取车点:{{item.pickup_location}}</text>
|
||||||
|
|
||||||
|
<!-- 二手车额外信息 -->
|
||||||
|
<view wx:elif="{{item.car_type == 3}}" class="used-car-info">
|
||||||
|
<text wx:if="{{item.first_license_date}}" class="license-date">首次上牌:{{item.first_license_date}}</text>
|
||||||
|
<text wx:if="{{item.warranty_remain}}" class="warranty-info">质保剩余:{{item.warranty_remain}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
380
pages/car_new/car_new.wxss
Normal file
380
pages/car_new/car_new.wxss
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -12,185 +12,26 @@ Page({
|
||||||
latitude: 31.2304, // 地图坐标
|
latitude: 31.2304, // 地图坐标
|
||||||
longitude: 121.4737,
|
longitude: 121.4737,
|
||||||
phone: '021-88888888'
|
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;
|
goToRental: function() {
|
||||||
const selectedText = e.detail.text;
|
wx.navigateTo({
|
||||||
|
url: '/pages/rental/rental'
|
||||||
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);
|
// 跳转到二手车页面
|
||||||
}
|
goToUsedCar: function() {
|
||||||
},
|
wx.navigateTo({
|
||||||
openMap() {
|
url: '/pages/usedcar/usedcar'
|
||||||
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 });
|
|
||||||
},
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
<!-- 顶部轮播图 -->
|
<!-- 顶部轮播图 -->
|
||||||
<swiper autoplay="3000" circular indicator-dots class="banner">
|
<swiper autoplay="3000" circular indicator-dots class="banner">
|
||||||
<block wx:for="{{bannerList}}" wx:key="index">
|
<block wx:for="{{bannerList}}" wx:key="index">
|
||||||
|
|
@ -20,97 +21,52 @@
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 车辆列表 -->
|
<!-- 业务模块 -->
|
||||||
<!-- 筛选栏 -->
|
<view class="business-modules">
|
||||||
<view class="sticky-filter">
|
<view class="module-title">车辆服务</view>
|
||||||
<van-dropdown-menu>
|
<view class="module-grid">
|
||||||
<van-dropdown-item
|
<view class="module-item" bindtap="goToNewCar">
|
||||||
value="{{selectedSort}}"
|
<view class="module-icon">
|
||||||
options="{{sortOptions}}"
|
<van-icon name="new-o" size="24px" color="#ff6b35" />
|
||||||
bind:change="onSortChange"
|
|
||||||
/>
|
|
||||||
<van-dropdown-item id="dropdownItemBrand" title="{{selectedBrandLabel}}" use-slot>
|
|
||||||
<van-tree-select
|
|
||||||
height="400"
|
|
||||||
items="{{brandTree}}"
|
|
||||||
main-active-index="{{mainActiveIndex}}"
|
|
||||||
active-id="{{selectedSeriesId}}"
|
|
||||||
bind:click-nav="onBrandClick"
|
|
||||||
bind:click-item="onSeriesSelect"
|
|
||||||
/>
|
|
||||||
</van-dropdown-item>
|
|
||||||
<van-dropdown-item
|
|
||||||
value="{{selectedPrice}}"
|
|
||||||
options="{{priceOptions}}"
|
|
||||||
bind:change="onPriceChange"
|
|
||||||
/>
|
|
||||||
<van-dropdown-item title="参数"
|
|
||||||
use-slot
|
|
||||||
id="dropdownItemParam"
|
|
||||||
>
|
|
||||||
<view class="filter-extend">
|
|
||||||
<view wx:for="{{extendFields}}" wx:key="id" class="filter-group">
|
|
||||||
<view class="filter-label">{{item.label}}</view>
|
|
||||||
|
|
||||||
<!-- 多选项字段 -->
|
|
||||||
<view wx:if="{{item.type === 'checkbox'}}" class="filter-tags">
|
|
||||||
<view
|
|
||||||
wx:for="{{item.options}}"
|
|
||||||
wx:for-item="opt"
|
|
||||||
wx:key="index"
|
|
||||||
class="filter-tag-item"
|
|
||||||
data-name="{{item.name}}"
|
|
||||||
data-value="{{opt.value}}"
|
|
||||||
bind:tap="onTagToggle"
|
|
||||||
>
|
|
||||||
<van-tag
|
|
||||||
class="mytag"
|
|
||||||
plain="{{!opt._checked}}"
|
|
||||||
>
|
|
||||||
{{opt.key}}
|
|
||||||
</van-tag>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<view wx:if="{{item.type === 'range'}}" class="filter-slider-group">
|
|
||||||
<view class="slider-label">
|
|
||||||
{{item.label}}:{{item._rangeStart || item.options.start}}{{item.options.unit}} - {{item._rangeEnd || item.options.end}}{{item.options.unit}}
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<van-slider
|
|
||||||
range
|
|
||||||
value="{{[item._rangeStart ? item._rangeStart : item.options.start, item._rangeEnd ? item._rangeEnd : item.options.end]}}"
|
|
||||||
min="{{item.options.start}}"
|
|
||||||
max="{{item.options.end}}"
|
|
||||||
data-name="{{item.name}}"
|
|
||||||
bind:change="onSliderChange"
|
|
||||||
/>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
|
<view class="module-text">新车</view>
|
||||||
<van-button type="primary" block size="small" bind:tap="onExtendConfirm">确认</van-button>
|
<view class="module-desc">全新车辆销售</view>
|
||||||
</view>
|
</view>
|
||||||
</van-dropdown-item>
|
|
||||||
</van-dropdown-menu>
|
<view class="module-item" bindtap="goToRental">
|
||||||
|
<view class="module-icon">
|
||||||
|
<van-icon name="coupon-o" size="24px" color="#4CAF50" />
|
||||||
|
</view>
|
||||||
|
<view class="module-text">租车</view>
|
||||||
|
<view class="module-desc">短期长期租赁</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="module-item" bindtap="goToUsedCar">
|
||||||
|
<view class="module-icon">
|
||||||
|
<van-icon name="shopping-cart-o" size="24px" color="#2196F3" />
|
||||||
|
</view>
|
||||||
|
<view class="module-text">二手车</view>
|
||||||
|
<view class="module-desc">优质二手车源</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 汽车列表 -->
|
<!-- 热门推荐 -->
|
||||||
<view class="car-list">
|
<view class="hot-recommend">
|
||||||
<view wx:for="{{carList}}" wx:key="id" class="car-item">
|
<view class="section-title">
|
||||||
<image class="car-image" src="{{item.cover_image[0]}}" mode="aspectFill" />
|
<text>热门推荐</text>
|
||||||
|
<van-icon name="arrow" size="16px" />
|
||||||
<view class="car-info">
|
</view>
|
||||||
<view class="car-title">{{item.title}}</view>
|
<view class="recommend-list">
|
||||||
<view class="car-price">
|
<view class="recommend-item" wx:for="{{hotCarList}}" wx:key="id" bindtap="goToCarDetail" data-id="{{item.id}}">
|
||||||
<text class="price-new">¥{{item.price}}万</text>
|
<image src="{{item.image}}" class="car-image" mode="aspectFill" />
|
||||||
<text class="price-old">¥{{item.re_price}}万</text>
|
<view class="car-info">
|
||||||
</view>
|
<view class="car-name">{{item.name}}</view>
|
||||||
<view class="car-attrs">
|
<view class="car-price">¥{{item.price}}</view>
|
||||||
<van-tag wx:for="{{item.attr}}" wx:key="index" wx:for-item="opt">
|
<view class="car-tags">
|
||||||
{{opt}}
|
<text class="tag">{{item.year}}年</text>
|
||||||
</van-tag>
|
<text class="tag">{{item.mileage}}万公里</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
|
||||||
|
|
@ -65,13 +65,14 @@ page {
|
||||||
gap: 12rpx;
|
gap: 12rpx;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
justify-content: space-around;
|
||||||
}
|
}
|
||||||
|
|
||||||
.company-actions .van-button {
|
.company-actions .van-button {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0; /* 允许按钮缩小 */
|
min-width: 0; /* 允许按钮缩小 */
|
||||||
|
|
||||||
max-width: calc(50% - 6rpx); /* 确保不超过一半宽度 */
|
width: auto; /* 确保不超过一半宽度 */
|
||||||
background: rgba(255, 255, 255, 0.15) !important;
|
background: rgba(255, 255, 255, 0.15) !important;
|
||||||
border: 2rpx solid rgba(255, 255, 255, 0.3) !important;
|
border: 2rpx solid rgba(255, 255, 255, 0.3) !important;
|
||||||
color: #ffffff !important;
|
color: #ffffff !important;
|
||||||
|
|
@ -79,7 +80,7 @@ page {
|
||||||
border-radius: 16rpx !important;
|
border-radius: 16rpx !important;
|
||||||
font-weight: 500 !important;
|
font-weight: 500 !important;
|
||||||
font-size: 26rpx !important;
|
font-size: 26rpx !important;
|
||||||
padding: 12rpx 8rpx !important;
|
padding: 12rpx 20rpx !important;
|
||||||
height: auto !important;
|
height: auto !important;
|
||||||
line-height: 1.2 !important;
|
line-height: 1.2 !important;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
@ -89,7 +90,7 @@ page {
|
||||||
}
|
}
|
||||||
|
|
||||||
.company-actions .van-button:hover {
|
.company-actions .van-button:hover {
|
||||||
background: rgba(255, 255, 255, 0.25) !important;
|
background: rgba(27, 24, 24, 0.25) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 按钮内容样式调整 */
|
/* 按钮内容样式调整 */
|
||||||
|
|
@ -103,322 +104,129 @@ page {
|
||||||
margin-right: 6rpx !important;
|
margin-right: 6rpx !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 筛选栏样式 */
|
/* 业务模块样式 */
|
||||||
.sticky-filter {
|
.business-modules {
|
||||||
background: #ffffff;
|
padding: 20px;
|
||||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
|
background: #fff;
|
||||||
overflow: hidden;
|
margin-bottom: 20px;
|
||||||
position: sticky;
|
border-radius: 10px;
|
||||||
top: 0;
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||||
z-index: 100;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 筛选扩展面板 */
|
.module-title {
|
||||||
.filter-extend {
|
font-size: 18px;
|
||||||
padding: 32rpx 24rpx;
|
font-weight: bold;
|
||||||
background: #ffffff;
|
color: #333;
|
||||||
max-height: 80vh;
|
margin-bottom: 15px;
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-group {
|
.module-grid {
|
||||||
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;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
justify-content: space-between;
|
||||||
gap: 12rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-tag-item {
|
.module-item {
|
||||||
transition: all 0.3s ease;
|
flex: 1;
|
||||||
}
|
|
||||||
|
|
||||||
.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;
|
text-align: center;
|
||||||
}
|
padding: 20px 10px;
|
||||||
|
border-radius: 10px;
|
||||||
/* 确认按钮样式 */
|
background: #f8f9fa;
|
||||||
.filter-extend .van-button {
|
margin: 0 5px;
|
||||||
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;
|
transition: all 0.3s ease;
|
||||||
position: relative;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.car-item::before {
|
.module-item:active {
|
||||||
content: '';
|
transform: scale(0.95);
|
||||||
position: absolute;
|
background: #e9ecef;
|
||||||
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 {
|
.module-icon {
|
||||||
transform: translateY(-4rpx);
|
margin-bottom: 10px;
|
||||||
box-shadow: 0 16rpx 48rpx rgba(0, 0, 0, 0.12);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.car-item:active::before {
|
.module-text {
|
||||||
opacity: 1;
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-desc {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 热门推荐样式 */
|
||||||
|
.hot-recommend {
|
||||||
|
padding: 20px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recommend-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recommend-item {
|
||||||
|
display: flex;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recommend-item:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
background: #e9ecef;
|
||||||
}
|
}
|
||||||
|
|
||||||
.car-image {
|
.car-image {
|
||||||
width: 100%;
|
width: 80px;
|
||||||
height: 300rpx;
|
height: 60px;
|
||||||
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
border-radius: 5px;
|
||||||
position: relative;
|
margin-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.car-info {
|
.car-info {
|
||||||
padding: 24rpx;
|
flex: 1;
|
||||||
position: relative;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.car-title {
|
.car-name {
|
||||||
font-size: 32rpx;
|
font-size: 16px;
|
||||||
font-weight: 700;
|
font-weight: bold;
|
||||||
color: #2c3e50;
|
color: #333;
|
||||||
margin-bottom: 16rpx;
|
margin-bottom: 5px;
|
||||||
line-height: 1.4;
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.car-price {
|
.car-price {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #ff6b35;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-tags {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: baseline;
|
gap: 5px;
|
||||||
gap: 12rpx;
|
|
||||||
margin-bottom: 20rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-new {
|
.tag {
|
||||||
font-size: 36rpx;
|
font-size: 12px;
|
||||||
font-weight: 800;
|
color: #666;
|
||||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
background: #e9ecef;
|
||||||
background-clip: text;
|
padding: 2px 6px;
|
||||||
-webkit-background-clip: text;
|
border-radius: 3px;
|
||||||
-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);
|
|
||||||
}
|
}
|
||||||
339
pages/info/info.js
Normal file
339
pages/info/info.js
Normal file
|
|
@ -0,0 +1,339 @@
|
||||||
|
const request = require('../../utils/request');
|
||||||
|
Page({
|
||||||
|
data: null,
|
||||||
|
onLoad(options) {
|
||||||
|
// 获取车辆ID
|
||||||
|
if (options.id) {
|
||||||
|
this.setData({
|
||||||
|
carId: options.id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 加载车辆详情
|
||||||
|
this.loadCarDetail();
|
||||||
|
},
|
||||||
|
|
||||||
|
onShow() {
|
||||||
|
// 页面显示时刷新数据
|
||||||
|
this.refreshData();
|
||||||
|
},
|
||||||
|
|
||||||
|
onShareAppMessage() {
|
||||||
|
// 分享配置
|
||||||
|
return {
|
||||||
|
title: this.data.carDetail.title,
|
||||||
|
desc: `${this.data.carDetail.desc} - 仅售${this.data.carDetail.price}万`,
|
||||||
|
path: `/pages/car-detail/car-detail?id=${this.data.carId}`,
|
||||||
|
imageUrl: this.data.carDetail.cover_image[0]
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
onShareTimeline() {
|
||||||
|
// 分享到朋友圈
|
||||||
|
return {
|
||||||
|
title: `${this.data.carDetail.title} - 仅售${this.data.carDetail.price}万`,
|
||||||
|
imageUrl: this.data.carDetail.cover_image[0]
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
// 初始化数据
|
||||||
|
initializeData() {
|
||||||
|
const { carDetail } = this.data;
|
||||||
|
|
||||||
|
// 计算优惠金额
|
||||||
|
const discountAmount = (carDetail.re_price - carDetail.price).toFixed(1);
|
||||||
|
|
||||||
|
// 转换属性为数组格式
|
||||||
|
const attributesList = Object.entries(carDetail.attributes).map(([key, value]) => ({
|
||||||
|
key,
|
||||||
|
value
|
||||||
|
}));
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
discountAmount,
|
||||||
|
attributesList
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 加载车辆详情
|
||||||
|
async loadCarDetail() {
|
||||||
|
if (!this.data.carId) return;
|
||||||
|
|
||||||
|
this.setData({ loading: true });
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
// 模拟API调用
|
||||||
|
const carDetail = await this.fetchCarDetail(this.data.carId);
|
||||||
|
console.log(carDetail)
|
||||||
|
if (carDetail) {
|
||||||
|
// 计算优惠金额
|
||||||
|
const discountAmount = (carDetail.re_price - carDetail.price).toFixed(1);
|
||||||
|
|
||||||
|
// 转换属性为数组格式
|
||||||
|
const attributesList = Object.entries(carDetail.attr).map(([key, value]) => ({
|
||||||
|
key,
|
||||||
|
value
|
||||||
|
}));
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
carDetail,
|
||||||
|
discountAmount,
|
||||||
|
attributesList
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载车辆详情失败:', error);
|
||||||
|
wx.showToast({
|
||||||
|
title: '加载失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
this.setData({ loading: false });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
async fetchCarDetail(id) {
|
||||||
|
try {
|
||||||
|
const raw = await request({
|
||||||
|
url: '/admin/wechat/api/carInfo?id=' + id,
|
||||||
|
method: 'GET'
|
||||||
|
});
|
||||||
|
return raw;
|
||||||
|
} catch (err) {
|
||||||
|
console.error('加载品牌失败', err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 刷新数据
|
||||||
|
refreshData() {
|
||||||
|
// 可以在这里添加数据刷新逻辑
|
||||||
|
console.log('页面数据刷新');
|
||||||
|
},
|
||||||
|
|
||||||
|
// 返回上一页
|
||||||
|
goBack() {
|
||||||
|
// 检查是否有上一页
|
||||||
|
const pages = getCurrentPages();
|
||||||
|
if (pages.length > 1) {
|
||||||
|
wx.navigateBack({
|
||||||
|
delta: 1
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 如果没有上一页,跳转到首页
|
||||||
|
wx.redirectTo({
|
||||||
|
url: '/pages/index/index'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 分享车辆
|
||||||
|
shareVehicle() {
|
||||||
|
const { carDetail } = this.data;
|
||||||
|
|
||||||
|
// 显示分享菜单
|
||||||
|
wx.showActionSheet({
|
||||||
|
itemList: ['分享给朋友', '分享到朋友圈', '复制链接'],
|
||||||
|
success: (res) => {
|
||||||
|
switch(res.tapIndex) {
|
||||||
|
case 0:
|
||||||
|
// 分享给朋友 - 由微信原生分享处理
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// 分享到朋友圈
|
||||||
|
this.shareToTimeline();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
// 复制链接
|
||||||
|
this.copyLink();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 分享到朋友圈
|
||||||
|
shareToTimeline() {
|
||||||
|
// 由于小程序限制,这里只能提示用户
|
||||||
|
wx.showModal({
|
||||||
|
title: '分享提示',
|
||||||
|
content: '请点击右上角菜单选择"分享到朋友圈"',
|
||||||
|
showCancel: false
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 复制链接
|
||||||
|
copyLink() {
|
||||||
|
const shareUrl = `https://yourapp.com/car-detail?id=${this.data.carId}`;
|
||||||
|
|
||||||
|
wx.setClipboardData({
|
||||||
|
data: shareUrl,
|
||||||
|
success: () => {
|
||||||
|
wx.showToast({
|
||||||
|
title: '链接已复制',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
wx.showToast({
|
||||||
|
title: '复制失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 拨打电话
|
||||||
|
makePhoneCall(e) {
|
||||||
|
const phone = e.currentTarget.dataset.phone || this.data.contactPhone;
|
||||||
|
|
||||||
|
wx.makePhoneCall({
|
||||||
|
phoneNumber: phone,
|
||||||
|
success: () => {
|
||||||
|
console.log('拨打电话成功');
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('拨打电话失败:', err);
|
||||||
|
wx.showToast({
|
||||||
|
title: '拨打失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 打开微信咨询
|
||||||
|
openWechat() {
|
||||||
|
// 方案1: 复制微信号
|
||||||
|
const wechatId = 'car_consultant_001';
|
||||||
|
|
||||||
|
wx.showModal({
|
||||||
|
title: '微信咨询',
|
||||||
|
content: `客服微信号:${wechatId}\n点击确定复制微信号`,
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
wx.setClipboardData({
|
||||||
|
data: wechatId,
|
||||||
|
success: () => {
|
||||||
|
wx.showToast({
|
||||||
|
title: '微信号已复制',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 图片预览
|
||||||
|
previewImage(e) {
|
||||||
|
const current = e.currentTarget.dataset.src;
|
||||||
|
const urls = this.data.carDetail.cover_image;
|
||||||
|
|
||||||
|
wx.previewImage({
|
||||||
|
current,
|
||||||
|
urls
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 收藏车辆
|
||||||
|
toggleFavorite() {
|
||||||
|
// 这里应该调用收藏API
|
||||||
|
wx.showToast({
|
||||||
|
title: '收藏成功',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查看更多图片
|
||||||
|
viewMoreImages() {
|
||||||
|
wx.navigateTo({
|
||||||
|
url: `/pages/car-images/car-images?id=${this.data.carId}`
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查看检测报告
|
||||||
|
viewInspectionReport() {
|
||||||
|
const { carDetail } = this.data;
|
||||||
|
|
||||||
|
if (carDetail.attributes['检测状态'] === '已检测') {
|
||||||
|
wx.navigateTo({
|
||||||
|
url: `/pages/inspection-report/inspection-report?id=${this.data.carId}`
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
wx.showToast({
|
||||||
|
title: '暂无检测报告',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 计算器
|
||||||
|
openCalculator() {
|
||||||
|
wx.navigateTo({
|
||||||
|
url: `/pages/loan-calculator/loan-calculator?price=${this.data.carDetail.price}`
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 预约看车
|
||||||
|
bookViewing() {
|
||||||
|
wx.navigateTo({
|
||||||
|
url: `/pages/book-viewing/book-viewing?id=${this.data.carId}`
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 举报车辆
|
||||||
|
reportVehicle() {
|
||||||
|
wx.showActionSheet({
|
||||||
|
itemList: ['价格有误', '车况描述不符', '联系方式错误', '其他问题'],
|
||||||
|
success: (res) => {
|
||||||
|
const reasons = ['价格有误', '车况描述不符', '联系方式错误', '其他问题'];
|
||||||
|
const reason = reasons[res.tapIndex];
|
||||||
|
|
||||||
|
wx.showModal({
|
||||||
|
title: '举报确认',
|
||||||
|
content: `您要举报的原因:${reason}`,
|
||||||
|
success: (modalRes) => {
|
||||||
|
if (modalRes.confirm) {
|
||||||
|
// 提交举报
|
||||||
|
this.submitReport(reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 提交举报
|
||||||
|
submitReport(reason) {
|
||||||
|
// 这里应该调用举报API
|
||||||
|
wx.showToast({
|
||||||
|
title: '举报成功',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 页面下拉刷新
|
||||||
|
onPullDownRefresh() {
|
||||||
|
this.loadCarDetail().then(() => {
|
||||||
|
wx.stopPullDownRefresh();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 页面触底加载
|
||||||
|
onReachBottom() {
|
||||||
|
// 如果有相关推荐车辆,可以在这里加载
|
||||||
|
console.log('触底加载更多');
|
||||||
|
},
|
||||||
|
|
||||||
|
// 用户点击右上角分享
|
||||||
|
onShareAppMessage() {
|
||||||
|
return {
|
||||||
|
title: this.data.carDetail.title,
|
||||||
|
desc: `${this.data.carDetail.desc} - 仅售${this.data.carDetail.price}万`,
|
||||||
|
path: `/pages/car-detail/car-detail?id=${this.data.carId}`,
|
||||||
|
imageUrl: this.data.carDetail.cover_image[0]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
10
pages/info/info.json
Normal file
10
pages/info/info.json
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"navigationBarTitleText": "车辆详情",
|
||||||
|
"usingComponents": {
|
||||||
|
"van-button": "@vant/weapp/button/index",
|
||||||
|
"van-icon": "@vant/weapp/icon/index",
|
||||||
|
"van-loading": "@vant/weapp/loading/index",
|
||||||
|
"van-overlay": "@vant/weapp/overlay/index"
|
||||||
|
},
|
||||||
|
"disableScroll": false
|
||||||
|
}
|
||||||
151
pages/info/info.wxml
Normal file
151
pages/info/info.wxml
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
<!-- car-detail.wxml -->
|
||||||
|
<view class="my_container">
|
||||||
|
<!-- 加载状态 -->
|
||||||
|
<van-overlay show="{{loading}}" z-index="100">
|
||||||
|
<view class="loading-container">
|
||||||
|
<van-loading size="24px" color="#667eea">加载中...</van-loading>
|
||||||
|
</view>
|
||||||
|
</van-overlay>
|
||||||
|
|
||||||
|
<!-- 头部图片区域 -->
|
||||||
|
<view class="hero-section">
|
||||||
|
<image
|
||||||
|
src="{{carDetail.cover_image[0]}}"
|
||||||
|
class="car-image"
|
||||||
|
mode="aspectFill"
|
||||||
|
bindtap="previewImage"
|
||||||
|
data-src="{{carDetail.cover_image[0]}}"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<view class="car-desc">{{carDetail.desc}}</view>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 图片指示器 -->
|
||||||
|
<view class="image-indicator" wx:if="{{carDetail.cover_image.length > 1}}">
|
||||||
|
<text>1/{{carDetail.cover_image.length}}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 更多图片按钮 -->
|
||||||
|
<view class="more-images-btn" bindtap="viewMoreImages" wx:if="{{carDetail.cover_image.length > 1}}">
|
||||||
|
<van-icon name="photo" size="16px" />
|
||||||
|
<text>查看更多</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="car-info-card car-type-{{carDetail.car_type}}">
|
||||||
|
<view class="car-header">
|
||||||
|
<view class="car-title">{{carDetail.title}}</view>
|
||||||
|
<view class="car-type-tag">
|
||||||
|
<text wx:if="{{carDetail.car_type == 1}}" class="tag-new">新车</text>
|
||||||
|
<text wx:elif="{{carDetail.car_type == 2}}" class="tag-rent">租车</text>
|
||||||
|
<text wx:elif="{{carDetail.car_type == 3}}" class="tag-used">二手车</text>
|
||||||
|
</view>
|
||||||
|
<!-- <view class="favorite-btn" bindtap="toggleFavorite">
|
||||||
|
<van-icon name="{{carDetail.is_favorite ? 'star' : 'star-o'}}" size="20px" color="{{carDetail.is_favorite ? '#ff6b6b' : '#999'}}" />
|
||||||
|
</view> -->
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="car-desc">{{carDetail.desc}}</view>
|
||||||
|
|
||||||
|
<!-- 新车价格展示 -->
|
||||||
|
<view wx:if="{{carDetail.car_type == 1}}" class="price-section price-new">
|
||||||
|
<view class="price-main">
|
||||||
|
<text class="current-price">¥{{carDetail.price}}万起</text>
|
||||||
|
</view>
|
||||||
|
<text wx:if="{{carDetail.re_price}}" class="original-price">指导价 ¥{{carDetail.re_price}}万</text>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 租车价格展示 -->
|
||||||
|
<view wx:elif="{{carDetail.car_type == 2}}" class="price-section price-rent">
|
||||||
|
<view class="price-main">
|
||||||
|
<text class="current-price">¥{{carDetail.price}}/天</text>
|
||||||
|
</view>
|
||||||
|
<text wx:if="{{carDetail.re_price}}" class="monthly-price">月租 ¥{{carDetail.re_price}}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 二手车价格展示 -->
|
||||||
|
<view wx:elif="{{carDetail.car_type == 3}}" class="price-section price-used">
|
||||||
|
<view class="price-main">
|
||||||
|
<text class="current-price">¥{{carDetail.price}}万</text>
|
||||||
|
</view>
|
||||||
|
<text wx:if="{{carDetail.re_price}}" class="original-price">新车价 ¥{{carDetail.re_price}}万</text>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="brand-info">
|
||||||
|
<image src="{{carDetail.brand.logo}}" class="brand-logo" mode="aspectFill" />
|
||||||
|
<view class="brand-text">
|
||||||
|
<view class="brand-name">{{carDetail.brand.name}}</view>
|
||||||
|
<view class="series-name">{{carDetail.series.name}}</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 不同车型的操作按钮 -->
|
||||||
|
<view class="action-buttons">
|
||||||
|
<!-- 新车操作按钮 -->
|
||||||
|
<view wx:if="{{carDetail.car_type == 1}}" class="calculator-btn" bindtap="openCalculator">
|
||||||
|
<van-icon name="calculator" size="16px" />
|
||||||
|
<text>贷款计算</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 租车操作按钮 -->
|
||||||
|
<view wx:elif="{{carDetail.car_type == 2}}" class="rent-btn" bindtap="openRentCalculator">
|
||||||
|
<van-icon name="calendar" size="16px" />
|
||||||
|
<text>租期计算</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 车辆属性 -->
|
||||||
|
<view class="attributes-card">
|
||||||
|
<view class="card-title">车辆详情</view>
|
||||||
|
<view class="attributes-grid">
|
||||||
|
<view
|
||||||
|
wx:for="{{attributesList}}"
|
||||||
|
wx:key="key"
|
||||||
|
class="attribute-item {{item.key === '检测状态' ? 'status-checked' : ''}}"
|
||||||
|
bindtap="{{item.key === '检测状态' ? 'viewInspectionReport' : ''}}"
|
||||||
|
>
|
||||||
|
<view class="attribute-label">{{item.key}}</view>
|
||||||
|
<view class="attribute-value">
|
||||||
|
{{item.value}}
|
||||||
|
<van-icon wx:if="{{item.key === '检测状态' && item.value === '已检测'}}" name="arrow" size="12px" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 联系我们 -->
|
||||||
|
<view class="contact-section">
|
||||||
|
<view class="contact-buttons">
|
||||||
|
<!-- 电话咨询 -->
|
||||||
|
<button
|
||||||
|
class="contact-btn primary"
|
||||||
|
open-type="makePhoneCall"
|
||||||
|
data-phone="{{contactPhone}}"
|
||||||
|
bindtap="makePhoneCall"
|
||||||
|
>
|
||||||
|
<van-icon name="phone" size="20px" class="btn-icon" />
|
||||||
|
<text>电话咨询</text>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- 微信咨询 -->
|
||||||
|
<button
|
||||||
|
class="contact-btn secondary"
|
||||||
|
bindtap="openWechat"
|
||||||
|
>
|
||||||
|
<van-icon name="chat" size="20px" class="btn-icon" />
|
||||||
|
<text>微信咨询</text>
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 底部安全区域 -->
|
||||||
|
<view class="safe-area-bottom"></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- Toast 组件 -->
|
||||||
|
<van-toast id="van-toast" />
|
||||||
828
pages/info/info.wxss
Normal file
828
pages/info/info.wxss
Normal file
|
|
@ -0,0 +1,828 @@
|
||||||
|
/* car-detail.wxss */
|
||||||
|
|
||||||
|
/* 全局容器 */
|
||||||
|
.my_container {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: linear-gradient(135deg, #e8e9ec80 0%, #bfbcc248 100%);
|
||||||
|
position: relative;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 加载状态 */
|
||||||
|
.loading-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 32px;
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 头部图片区域 */
|
||||||
|
.hero-section {
|
||||||
|
position: relative;
|
||||||
|
height: 260px;
|
||||||
|
margin: 0 16px 16px 16px;
|
||||||
|
border-radius: 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-image:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
left: 20px;
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
border-radius: 22px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-button:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
}
|
||||||
|
.van-button {
|
||||||
|
width: auto !important;
|
||||||
|
}
|
||||||
|
.share-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
border-radius: 22px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-button:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-indicator {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
right: 80px;
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
color: white;
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-radius: 16px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.more-images-btn {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 20px;
|
||||||
|
right: 20px;
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.more-images-btn text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.more-images-btn:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 车辆信息卡片 */
|
||||||
|
.car-info-card {
|
||||||
|
background: white;
|
||||||
|
margin: 0 16px 16px 16px;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 24px;
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-info-card::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 4px;
|
||||||
|
background: linear-gradient(90deg, #667eea, #764ba2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-title {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1a1a1a;
|
||||||
|
line-height: 1.3;
|
||||||
|
flex: 1;
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.favorite-btn {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.favorite-btn:active {
|
||||||
|
transform: scale(0.9);
|
||||||
|
background: #667eea;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-desc {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.5;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-section {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-price {
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #e74c3c;
|
||||||
|
background: linear-gradient(45deg, #e74c3c, #c0392b);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.original-price {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #999;
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discount-badge {
|
||||||
|
background: linear-gradient(45deg, #2ecc71, #27ae60);
|
||||||
|
color: white;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 16px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
box-shadow: 0 2px 8px rgba(46, 204, 113, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 16px;
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 1px solid #e9ecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-logo {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: white;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-text {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1a1a1a;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.series-name {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calculator-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
background: linear-gradient(45deg, #667eea, #764ba2);
|
||||||
|
color: white;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calculator-btn:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 车辆属性卡片 */
|
||||||
|
.attributes-card {
|
||||||
|
background: white;
|
||||||
|
margin: 0 16px 16px 16px;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 24px;
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1a1a1a;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
border-bottom: 2px solid #f1f3f4;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: -2px;
|
||||||
|
left: 0;
|
||||||
|
width: 40px;
|
||||||
|
height: 2px;
|
||||||
|
background: linear-gradient(90deg, #667eea, #764ba2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.attributes-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attribute-item {
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 16px;
|
||||||
|
border-radius: 12px;
|
||||||
|
border-left: 4px solid #e9ecef;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attribute-item:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-checked {
|
||||||
|
background: linear-gradient(135deg, #e8f5e8, #f0f8f0);
|
||||||
|
border-left-color: #2ecc71;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attribute-label {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attribute-value {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #1a1a1a;
|
||||||
|
font-weight: 600;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 快捷操作 */
|
||||||
|
.quick-actions {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 12px;
|
||||||
|
margin: 0 16px 16px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-item {
|
||||||
|
background: white;
|
||||||
|
padding: 20px 12px;
|
||||||
|
border-radius: 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-item:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-item:nth-child(1) {
|
||||||
|
background: linear-gradient(135deg, #fff5f5, #ffeaea);
|
||||||
|
color: #e74c3c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-item:nth-child(2) {
|
||||||
|
background: linear-gradient(135deg, #f0f8ff, #e6f3ff);
|
||||||
|
color: #3498db;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-item:nth-child(3) {
|
||||||
|
background: linear-gradient(135deg, #fff8e1, #ffecb3);
|
||||||
|
color: #f39c12;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-item:nth-child(4) {
|
||||||
|
background: linear-gradient(135deg, #f3e5f5, #e8d5ee);
|
||||||
|
color: #9b59b6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-item text {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 联系我们 */
|
||||||
|
.contact-section {
|
||||||
|
background: white;
|
||||||
|
margin: 0 16px 16px 16px;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 24px;
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-info {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 12px 0;
|
||||||
|
border-bottom: 1px solid #f1f3f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-item text {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-btn {
|
||||||
|
flex: 1;
|
||||||
|
border-radius: 24px !important;
|
||||||
|
font-weight: 600 !important;
|
||||||
|
font-size: 16px !important;
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-btn.primary {
|
||||||
|
background: linear-gradient(45deg, #667eea, #764ba2) !important;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-btn.secondary {
|
||||||
|
background: linear-gradient(45deg, #2ecc71, #27ae60) !important;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-btn:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 底部安全区域 */
|
||||||
|
.safe-area-bottom {
|
||||||
|
height: 34px;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 响应式优化 */
|
||||||
|
@media (max-width: 375px) {
|
||||||
|
.attributes-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-actions {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-title {
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-price {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 动画效果 */
|
||||||
|
@keyframes fadeInUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-info-card,
|
||||||
|
.attributes-card,
|
||||||
|
.contact-section {
|
||||||
|
animation: fadeInUp 0.6s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-info-card {
|
||||||
|
animation-delay: 0.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attributes-card {
|
||||||
|
animation-delay: 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-actions {
|
||||||
|
animation: fadeInUp 0.6s ease-out;
|
||||||
|
animation-delay: 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-section {
|
||||||
|
animation-delay: 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 毛玻璃效果增强 */
|
||||||
|
.back-button,
|
||||||
|
.share-button,
|
||||||
|
.more-images-btn {
|
||||||
|
backdrop-filter: blur(15px);
|
||||||
|
-webkit-backdrop-filter: blur(15px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 悬浮效果 */
|
||||||
|
.car-info-card,
|
||||||
|
.attributes-card,
|
||||||
|
.contact-section {
|
||||||
|
transform: translateY(0);
|
||||||
|
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-info-card:hover,
|
||||||
|
.attributes-card:hover,
|
||||||
|
.contact-section:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 渐变文字效果 */
|
||||||
|
.brand-name {
|
||||||
|
background: linear-gradient(45deg, #667eea, #764ba2);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 自定义滚动条 */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: linear-gradient(45deg, #667eea, #764ba2);
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: linear-gradient(45deg, #764ba2, #667eea);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 车辆信息卡片 */
|
||||||
|
.car-info-card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
padding: 30rpx;
|
||||||
|
margin: 20rpx;
|
||||||
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 不同车型的顶部装饰条 */
|
||||||
|
.car-type-1::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 8rpx;
|
||||||
|
background: linear-gradient(90deg, #1989fa, #40a9ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-type-2::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 8rpx;
|
||||||
|
background: linear-gradient(90deg, #07c160, #52c41a);
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-type-3::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 8rpx;
|
||||||
|
background: linear-gradient(90deg, #ff976a, #ffa940);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 车辆头部信息 */
|
||||||
|
.car-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-title {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #333;
|
||||||
|
flex: 1;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-type-tag {
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-new {
|
||||||
|
background: linear-gradient(135deg, #1989fa, #40a9ff);
|
||||||
|
color: white;
|
||||||
|
padding: 8rpx 16rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-rent {
|
||||||
|
background: linear-gradient(135deg, #07c160, #52c41a);
|
||||||
|
color: white;
|
||||||
|
padding: 8rpx 16rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-used {
|
||||||
|
background: linear-gradient(135deg, #ff976a, #ffa940);
|
||||||
|
color: white;
|
||||||
|
padding: 8rpx 16rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.favorite-btn {
|
||||||
|
padding: 8rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.car-desc {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 价格区域 */
|
||||||
|
.price-section {
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
padding: 30rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 新车价格样式 */
|
||||||
|
.price-new {
|
||||||
|
background: linear-gradient(135deg, rgba(25, 137, 250, 0.1), rgba(64, 169, 255, 0.05));
|
||||||
|
border: 2rpx solid rgba(25, 137, 250, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-new .current-price {
|
||||||
|
font-size: 48rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1989fa;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-new .original-price {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999;
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-new .discount-badge {
|
||||||
|
background: #ff4d4f;
|
||||||
|
color: white;
|
||||||
|
padding: 6rpx 12rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 租车价格样式 */
|
||||||
|
.price-rent {
|
||||||
|
background: linear-gradient(135deg, rgba(7, 193, 96, 0.1), rgba(82, 196, 26, 0.05));
|
||||||
|
border: 2rpx solid rgba(7, 193, 96, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-rent .current-price {
|
||||||
|
font-size: 48rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #07c160;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-rent .monthly-price {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rent-options {
|
||||||
|
display: flex;
|
||||||
|
gap: 20rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rent-option {
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
padding: 12rpx 20rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
text-align: center;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-label {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 4rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-price {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #07c160;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 二手车价格样式 */
|
||||||
|
.price-used {
|
||||||
|
background: linear-gradient(135deg, rgba(255, 151, 106, 0.1), rgba(255, 169, 64, 0.05));
|
||||||
|
border: 2rpx solid rgba(255, 151, 106, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-used .current-price {
|
||||||
|
font-size: 48rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #ff976a;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-used .original-price {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value-badge {
|
||||||
|
background: #52c41a;
|
||||||
|
color: white;
|
||||||
|
padding: 6rpx 12rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.depreciation-rate {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666;
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
padding: 6rpx 12rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.used-car-details {
|
||||||
|
display: flex;
|
||||||
|
gap: 20rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
padding: 16rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-label {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 4rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-value {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 价格提示 */
|
||||||
|
.price-tips {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tip-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
// logs.js
|
|
||||||
const util = require('../../utils/util.js')
|
|
||||||
|
|
||||||
Page({
|
|
||||||
data: {
|
|
||||||
logs: []
|
|
||||||
},
|
|
||||||
onLoad() {
|
|
||||||
this.setData({
|
|
||||||
logs: (wx.getStorageSync('logs') || []).map(log => {
|
|
||||||
return {
|
|
||||||
date: util.formatTime(new Date(log)),
|
|
||||||
timeStamp: log
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"usingComponents": {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
<!--logs.wxml-->
|
|
||||||
<scroll-view class="scrollarea" scroll-y type="list">
|
|
||||||
<block wx:for="{{logs}}" wx:key="timeStamp" wx:for-item="log">
|
|
||||||
<view class="log-item">{{index + 1}}. {{log.date}}</view>
|
|
||||||
</block>
|
|
||||||
</scroll-view>
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
page {
|
|
||||||
height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
.scrollarea {
|
|
||||||
flex: 1;
|
|
||||||
overflow-y: hidden;
|
|
||||||
}
|
|
||||||
.log-item {
|
|
||||||
margin-top: 20rpx;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.log-item:last-child {
|
|
||||||
padding-bottom: env(safe-area-inset-bottom);
|
|
||||||
}
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
"disablePlugins": [],
|
"disablePlugins": [],
|
||||||
"outputPath": ""
|
"outputPath": ""
|
||||||
},
|
},
|
||||||
"compileWorklet": false,
|
"compileWorklet": true,
|
||||||
"uglifyFileName": false,
|
"uglifyFileName": false,
|
||||||
"uploadWithSourceMap": true,
|
"uploadWithSourceMap": true,
|
||||||
"packNpmManually": false,
|
"packNpmManually": false,
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
"projectname": "car_front",
|
"projectname": "car_front",
|
||||||
"setting": {
|
"setting": {
|
||||||
"compileHotReLoad": true,
|
"compileHotReLoad": true,
|
||||||
"urlCheck": true,
|
"urlCheck": false,
|
||||||
"coverView": true,
|
"coverView": true,
|
||||||
"lazyloadPlaceholderEnable": false,
|
"lazyloadPlaceholderEnable": false,
|
||||||
"skylineRenderEnable": false,
|
"skylineRenderEnable": false,
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ const BASE_URL = 'https://car.cherrybless.com'; // 👈 换成你的后端地址
|
||||||
function request({ url, method = 'GET', data = {}, header = {} }) {
|
function request({ url, method = 'GET', data = {}, header = {} }) {
|
||||||
const token = '';
|
const token = '';
|
||||||
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
wx.request({
|
wx.request({
|
||||||
url: BASE_URL + url,
|
url: BASE_URL + url,
|
||||||
|
|
|
||||||
382
utils/util.js
382
utils/util.js
|
|
@ -14,6 +14,388 @@ const formatNumber = n => {
|
||||||
return n[1] ? n : `0${n}`
|
return n[1] ? n : `0${n}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化价格显示
|
||||||
|
* @param {number} price - 价格
|
||||||
|
* @returns {string} 格式化后的价格
|
||||||
|
*/
|
||||||
|
export function formatPrice(price) {
|
||||||
|
if (!price) return '0';
|
||||||
|
return price.toFixed(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算优惠金额
|
||||||
|
* @param {number} originalPrice - 原价
|
||||||
|
* @param {number} currentPrice - 现价
|
||||||
|
* @returns {number} 优惠金额
|
||||||
|
*/
|
||||||
|
export function calculateDiscount(originalPrice, currentPrice) {
|
||||||
|
if (!originalPrice || !currentPrice) return 0;
|
||||||
|
return Math.max(0, originalPrice - currentPrice);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车龄计算
|
||||||
|
* @param {string} year - 年份
|
||||||
|
* @returns {string} 车龄描述
|
||||||
|
*/
|
||||||
|
export function calculateCarAge(year) {
|
||||||
|
if (!year) return '未知';
|
||||||
|
const currentYear = new Date().getFullYear();
|
||||||
|
const age = currentYear - parseInt(year);
|
||||||
|
|
||||||
|
if (age <= 0) return '新车';
|
||||||
|
if (age === 1) return '1年';
|
||||||
|
return `${age}年`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 里程数格式化
|
||||||
|
* @param {number} mileage - 里程数(公里)
|
||||||
|
* @returns {string} 格式化后的里程数
|
||||||
|
*/
|
||||||
|
export function formatMileage(mileage) {
|
||||||
|
if (!mileage) return '0公里';
|
||||||
|
|
||||||
|
if (mileage < 1000) {
|
||||||
|
return `${mileage}公里`;
|
||||||
|
} else if (mileage < 10000) {
|
||||||
|
return `${(mileage / 1000).toFixed(1)}千公里`;
|
||||||
|
} else {
|
||||||
|
return `${(mileage / 10000).toFixed(1)}万公里`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证手机号
|
||||||
|
* @param {string} phone - 手机号
|
||||||
|
* @returns {boolean} 是否有效
|
||||||
|
*/
|
||||||
|
export function validatePhone(phone) {
|
||||||
|
const phoneReg = /^1[3-9]\d{9}$/;
|
||||||
|
return phoneReg.test(phone);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片加载错误处理
|
||||||
|
* @param {string} src - 图片源
|
||||||
|
* @param {string} fallback - 备用图片
|
||||||
|
* @returns {string} 处理后的图片源
|
||||||
|
*/
|
||||||
|
export function handleImageError(src, fallback = '/images/car-placeholder.png') {
|
||||||
|
return src || fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分享配置生成
|
||||||
|
* @param {Object} carDetail - 车辆详情
|
||||||
|
* @param {string} carId - 车辆ID
|
||||||
|
* @returns {Object} 分享配置
|
||||||
|
*/
|
||||||
|
export function generateShareConfig(carDetail, carId) {
|
||||||
|
return {
|
||||||
|
title: carDetail.title || '精品二手车',
|
||||||
|
desc: `${carDetail.desc || '车况优良'} - 仅售${formatPrice(carDetail.price)}万`,
|
||||||
|
path: `/pages/car-detail/car-detail?id=${carId}`,
|
||||||
|
imageUrl: carDetail.cover_image?.[0] || '/images/share-default.png'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本地存储操作
|
||||||
|
*/
|
||||||
|
export const storage = {
|
||||||
|
/**
|
||||||
|
* 保存浏览记录
|
||||||
|
* @param {Object} carInfo - 车辆信息
|
||||||
|
*/
|
||||||
|
saveBrowseHistory(carInfo) {
|
||||||
|
try {
|
||||||
|
const history = this.getBrowseHistory();
|
||||||
|
const existingIndex = history.findIndex(item => item.id === carInfo.id);
|
||||||
|
|
||||||
|
if (existingIndex !== -1) {
|
||||||
|
history.splice(existingIndex, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
history.unshift({
|
||||||
|
id: carInfo.id,
|
||||||
|
title: carInfo.title,
|
||||||
|
price: carInfo.price,
|
||||||
|
cover_image: carInfo.cover_image?.[0],
|
||||||
|
browse_time: Date.now()
|
||||||
|
});
|
||||||
|
|
||||||
|
// 只保留最近50条记录
|
||||||
|
if (history.length > 50) {
|
||||||
|
history.splice(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
wx.setStorageSync('browse_history', history);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存浏览记录失败:', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取浏览记录
|
||||||
|
* @returns {Array} 浏览记录列表
|
||||||
|
*/
|
||||||
|
getBrowseHistory() {
|
||||||
|
try {
|
||||||
|
return wx.getStorageSync('browse_history') || [];
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取浏览记录失败:', error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存收藏
|
||||||
|
* @param {Object} carInfo - 车辆信息
|
||||||
|
*/
|
||||||
|
saveFavorite(carInfo) {
|
||||||
|
try {
|
||||||
|
const favorites = this.getFavorites();
|
||||||
|
const existingIndex = favorites.findIndex(item => item.id === carInfo.id);
|
||||||
|
|
||||||
|
if (existingIndex === -1) {
|
||||||
|
favorites.unshift({
|
||||||
|
id: carInfo.id,
|
||||||
|
title: carInfo.title,
|
||||||
|
price: carInfo.price,
|
||||||
|
cover_image: carInfo.cover_image?.[0],
|
||||||
|
favorite_time: Date.now()
|
||||||
|
});
|
||||||
|
|
||||||
|
wx.setStorageSync('favorites', favorites);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存收藏失败:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消收藏
|
||||||
|
* @param {string} carId - 车辆ID
|
||||||
|
*/
|
||||||
|
removeFavorite(carId) {
|
||||||
|
try {
|
||||||
|
const favorites = this.getFavorites();
|
||||||
|
const filteredFavorites = favorites.filter(item => item.id !== carId);
|
||||||
|
wx.setStorageSync('favorites', filteredFavorites);
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('取消收藏失败:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取收藏列表
|
||||||
|
* @returns {Array} 收藏列表
|
||||||
|
*/
|
||||||
|
getFavorites() {
|
||||||
|
try {
|
||||||
|
return wx.getStorageSync('favorites') || [];
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取收藏列表失败:', error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否已收藏
|
||||||
|
* @param {string} carId - 车辆ID
|
||||||
|
* @returns {boolean} 是否已收藏
|
||||||
|
*/
|
||||||
|
isFavorite(carId) {
|
||||||
|
const favorites = this.getFavorites();
|
||||||
|
return favorites.some(item => item.id === carId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API 请求封装
|
||||||
|
*/
|
||||||
|
export const api = {
|
||||||
|
/**
|
||||||
|
* 获取车辆详情
|
||||||
|
* @param {string} carId - 车辆ID
|
||||||
|
* @returns {Promise} API响应
|
||||||
|
*/
|
||||||
|
getCarDetail(carId) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
wx.request({
|
||||||
|
url: `${getApp().globalData.apiUrl}/cars/${carId}`,
|
||||||
|
method: 'GET',
|
||||||
|
header: {
|
||||||
|
'Authorization': getApp().globalData.token
|
||||||
|
},
|
||||||
|
success: (res) => {
|
||||||
|
if (res.statusCode === 200) {
|
||||||
|
resolve(res.data);
|
||||||
|
} else {
|
||||||
|
reject(new Error(res.data.message || '获取车辆详情失败'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (error) => {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交举报
|
||||||
|
* @param {string} carId - 车辆ID
|
||||||
|
* @param {string} reason - 举报原因
|
||||||
|
* @returns {Promise} API响应
|
||||||
|
*/
|
||||||
|
submitReport(carId, reason) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
wx.request({
|
||||||
|
url: `${getApp().globalData.apiUrl}/reports`,
|
||||||
|
method: 'POST',
|
||||||
|
header: {
|
||||||
|
'Authorization': getApp().globalData.token,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
car_id: carId,
|
||||||
|
reason: reason,
|
||||||
|
report_time: Date.now()
|
||||||
|
},
|
||||||
|
success: (res) => {
|
||||||
|
if (res.statusCode === 200) {
|
||||||
|
resolve(res.data);
|
||||||
|
} else {
|
||||||
|
reject(new Error(res.data.message || '举报提交失败'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (error) => {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预约看车
|
||||||
|
* @param {Object} bookingData - 预约数据
|
||||||
|
* @returns {Promise} API响应
|
||||||
|
*/
|
||||||
|
bookViewing(bookingData) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
wx.request({
|
||||||
|
url: `${getApp().globalData.apiUrl}/bookings`,
|
||||||
|
method: 'POST',
|
||||||
|
header: {
|
||||||
|
'Authorization': getApp().globalData.token,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
data: bookingData,
|
||||||
|
success: (res) => {
|
||||||
|
if (res.statusCode === 200) {
|
||||||
|
resolve(res.data);
|
||||||
|
} else {
|
||||||
|
reject(new Error(res.data.message || '预约失败'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (error) => {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户行为追踪
|
||||||
|
*/
|
||||||
|
export const analytics = {
|
||||||
|
/**
|
||||||
|
* 记录页面访问
|
||||||
|
* @param {string} carId - 车辆ID
|
||||||
|
* @param {string} source - 访问来源
|
||||||
|
*/
|
||||||
|
trackPageView(carId, source = 'direct') {
|
||||||
|
try {
|
||||||
|
// 这里可以接入第三方统计服务
|
||||||
|
console.log('页面访问:', { carId, source, timestamp: Date.now() });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('统计记录失败:', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录用户操作
|
||||||
|
* @param {string} action - 操作类型
|
||||||
|
* @param {Object} params - 操作参数
|
||||||
|
*/
|
||||||
|
trackUserAction(action, params = {}) {
|
||||||
|
try {
|
||||||
|
console.log('用户操作:', { action, params, timestamp: Date.now() });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('操作记录失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误处理
|
||||||
|
*/
|
||||||
|
export const errorHandler = {
|
||||||
|
/**
|
||||||
|
* 显示错误提示
|
||||||
|
* @param {string} message - 错误信息
|
||||||
|
* @param {string} type - 错误类型
|
||||||
|
*/
|
||||||
|
showError(message, type = 'toast') {
|
||||||
|
switch (type) {
|
||||||
|
case 'toast':
|
||||||
|
wx.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'modal':
|
||||||
|
wx.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: message,
|
||||||
|
showCancel: false
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理网络错误
|
||||||
|
* @param {Error} error - 错误对象
|
||||||
|
*/
|
||||||
|
handleNetworkError(error) {
|
||||||
|
let message = '网络错误,请稍后重试';
|
||||||
|
|
||||||
|
if (error.errMsg) {
|
||||||
|
if (error.errMsg.includes('timeout')) {
|
||||||
|
message = '请求超时,请检查网络连接';
|
||||||
|
} else if (error.errMsg.includes('fail')) {
|
||||||
|
message = '网络连接失败,请检查网络设置';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.showError(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
formatTime
|
formatTime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user