获取设备和套餐
This commit is contained in:
parent
879190c956
commit
77e116b7fa
116
api/README.md
Normal file
116
api/README.md
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
# API 模块使用说明
|
||||
|
||||
## 概述
|
||||
|
||||
本项目使用统一的API请求工具 `@/utils/request.js`,所有API请求都通过该工具进行,无需重复配置基地址和请求头。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
api/
|
||||
├── index.js # API模块统一导出
|
||||
├── lease/ # 租赁相关API
|
||||
│ └── lease.js
|
||||
├── device/ # 设备相关API
|
||||
│ └── device.js
|
||||
├── banner/ # 轮播图相关API
|
||||
│ └── banner.js
|
||||
├── article/ # 文章相关API
|
||||
│ └── article.js
|
||||
└── auth/ # 认证相关API
|
||||
└── auth.js
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 1. 导入API方法
|
||||
|
||||
```javascript
|
||||
// 方式1:从具体模块导入
|
||||
import { getDeviceTypes, getPeriodPackages } from '@/api/lease/lease.js'
|
||||
|
||||
// 方式2:从统一入口导入
|
||||
import { getDeviceTypes, getPeriodPackages } from '@/api/index.js'
|
||||
```
|
||||
|
||||
### 2. 在组件中使用
|
||||
|
||||
```javascript
|
||||
export default {
|
||||
methods: {
|
||||
async fetchData() {
|
||||
try {
|
||||
const response = await getDeviceTypes()
|
||||
|
||||
if (response.code === 200) {
|
||||
this.deviceTypes = response.data
|
||||
} else {
|
||||
throw new Error(response.message || '请求失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取数据失败:', error)
|
||||
uni.showToast({
|
||||
title: error.message || '获取数据失败',
|
||||
icon: 'error',
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API方法命名规范
|
||||
|
||||
- 获取列表:`getXxxList`
|
||||
- 获取详情:`getXxxDetail`
|
||||
- 创建:`createXxx`
|
||||
- 更新:`updateXxx`
|
||||
- 删除:`deleteXxx`
|
||||
|
||||
## 请求工具特性
|
||||
|
||||
### 自动处理
|
||||
- ✅ 基地址配置
|
||||
- ✅ 请求头设置
|
||||
- ✅ Token管理
|
||||
- ✅ Loading状态
|
||||
- ✅ 错误处理
|
||||
- ✅ 超时处理
|
||||
|
||||
### 配置选项
|
||||
```javascript
|
||||
request({
|
||||
url: '/api/endpoint',
|
||||
method: 'GET',
|
||||
params: { id: 1 },
|
||||
loadingText: '加载中...', // 自定义loading文本
|
||||
showLoading: true, // 是否显示loading
|
||||
timeout: 60000, // 超时时间
|
||||
noToken: false, // 是否需要token
|
||||
})
|
||||
```
|
||||
|
||||
## 环境配置
|
||||
|
||||
请求工具会根据当前环境自动选择对应的配置:
|
||||
|
||||
- **开发环境**:`http://192.168.2.114:4601`
|
||||
- **体验版**:`http://192.168.2.114:4601`
|
||||
- **正式版**:`http://192.168.2.114:4601`
|
||||
|
||||
## 错误处理
|
||||
|
||||
所有API请求都会自动处理以下错误:
|
||||
|
||||
- 401:登录过期,自动跳转登录页
|
||||
- 403:权限不足
|
||||
- 404:资源不存在
|
||||
- 500:服务器错误
|
||||
- 网络错误:超时、连接失败等
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **方法名冲突**:避免页面方法名与API方法名相同,建议使用别名导入
|
||||
2. **Loading管理**:请求工具已内置loading管理,无需手动处理
|
||||
3. **错误提示**:统一使用 `uni.showToast` 显示错误信息
|
||||
4. **Token处理**:开发环境支持临时token,生产环境使用真实token
|
||||
6
api/index.js
Normal file
6
api/index.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
// API模块统一导出
|
||||
export * from './lease/lease.js'
|
||||
export * from './device/device.js'
|
||||
export * from './banner/banner.js'
|
||||
export * from './article/article.js'
|
||||
export * from './auth/auth.js'
|
||||
29
api/lease/lease.js
Normal file
29
api/lease/lease.js
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 获取设备类型列表
|
||||
* @returns {Promise} 返回设备类型列表数据
|
||||
*/
|
||||
export function getDeviceTypes() {
|
||||
return request({
|
||||
url: '/app/type/list',
|
||||
method: 'GET',
|
||||
loadingText: '加载设备类型中...',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据设备类型获取租赁套餐列表
|
||||
* @param {string} typeId - 设备类型ID
|
||||
* @returns {Promise} 返回租赁套餐列表数据
|
||||
*/
|
||||
export function getPeriodPackages(typeId) {
|
||||
return request({
|
||||
url: '/app/suit/list',
|
||||
method: 'GET',
|
||||
params: {
|
||||
typeId: typeId
|
||||
},
|
||||
loadingText: '加载套餐中...',
|
||||
})
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
/>
|
||||
|
||||
<!-- 底部导航已由系统tabBar处理 -->
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -43,14 +43,14 @@ import { getNewAnnouncement } from '../../api/article/article.js'
|
|||
import { getBannerList } from '../../api/banner/banner.js'
|
||||
import { getDeviceList } from '../../api/device/device.js'
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
AnnouncementBar,
|
||||
BannerSwiper,
|
||||
EquipmentList,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
data() {
|
||||
return {
|
||||
// 基础配置
|
||||
indicatorDots: true,
|
||||
autoplay: true,
|
||||
|
|
@ -72,11 +72,11 @@ export default {
|
|||
|
||||
// 设备列表数据
|
||||
equipmentList: [],
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
// 生命周期钩子
|
||||
onLoad() {
|
||||
onLoad() {
|
||||
this.fetchAnnouncement()
|
||||
this.fetchBannerList()
|
||||
this.fetchDeviceList()
|
||||
|
|
@ -270,7 +270,7 @@ export default {
|
|||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
@ -280,5 +280,5 @@ export default {
|
|||
max-width: 750rpx;
|
||||
margin: 0 auto;
|
||||
z-index: -2;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -58,7 +58,9 @@
|
|||
<view class="form-item">
|
||||
<text class="field-label">租赁设备</text>
|
||||
<view class="selector" @click="selectEquipment">
|
||||
<text class="selector-text">{{ formData.equipment || '选择设备类型' }}</text>
|
||||
<text :class="['selector-text', { placeholder: !formData.equipment }]">
|
||||
{{ formData.equipment || '选择设备类型' }}
|
||||
</text>
|
||||
<text class="arrow-icon">></text>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -67,7 +69,9 @@
|
|||
<view class="form-item">
|
||||
<text class="field-label">租赁周期</text>
|
||||
<view class="selector" @click="selectPeriod">
|
||||
<text class="selector-text">{{ formData.period || '1年' }}</text>
|
||||
<text :class="['selector-text', { placeholder: !formData.period }]">
|
||||
{{ formData.period || '请先选择设备类型' }}
|
||||
</text>
|
||||
<text class="arrow-icon">></text>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -76,7 +80,13 @@
|
|||
|
||||
<!-- 支付区域 -->
|
||||
<view class="payment-section">
|
||||
<button class="pay-button" @click="handlePayment">立即支付 ¥{{ totalAmount }}</button>
|
||||
<button
|
||||
:class="['pay-button', { disabled: !canPay }]"
|
||||
@click="handlePayment"
|
||||
:disabled="!canPay"
|
||||
>
|
||||
{{ canPay ? `立即支付 ¥${totalAmount}` : '请完善信息' }}
|
||||
</button>
|
||||
|
||||
<view class="payment-details">
|
||||
<view class="details-header" @click="toggleDetails">
|
||||
|
|
@ -87,6 +97,18 @@
|
|||
</view>
|
||||
|
||||
<view v-if="showDetails" class="details-content">
|
||||
<view v-if="selectedDevice" class="detail-item">
|
||||
<text class="detail-label">设备类型</text>
|
||||
<text class="detail-value">{{ selectedDevice.name }}</text>
|
||||
</view>
|
||||
<view v-if="selectedPackage" class="detail-item">
|
||||
<text class="detail-label">租赁周期</text>
|
||||
<text class="detail-value">{{ selectedPackage.name }}</text>
|
||||
</view>
|
||||
<view v-if="selectedPackage" class="detail-item">
|
||||
<text class="detail-label">租赁天数</text>
|
||||
<text class="detail-value">{{ selectedPackage.day }}天</text>
|
||||
</view>
|
||||
<view class="detail-item">
|
||||
<text class="detail-label">租金</text>
|
||||
<text class="detail-value">¥{{ totalAmount }}</text>
|
||||
|
|
@ -103,6 +125,7 @@
|
|||
<script>
|
||||
import commonEnum from '../../enum/commonEnum'
|
||||
import MapLocation from '@/components/map-location/map-location.vue'
|
||||
import { getDeviceTypes as fetchDeviceTypes, getPeriodPackages as fetchPeriodPackages } from '@/api/lease/lease.js'
|
||||
|
||||
export default {
|
||||
name: 'LeasePage',
|
||||
|
|
@ -113,10 +136,19 @@ export default {
|
|||
commonEnum() {
|
||||
return commonEnum
|
||||
},
|
||||
// 检查是否可以支付
|
||||
canPay() {
|
||||
return this.formData.name.trim() &&
|
||||
this.formData.phone.trim() &&
|
||||
this.formData.address.trim() &&
|
||||
this.formData.equipmentId &&
|
||||
this.formData.periodId &&
|
||||
parseFloat(this.totalAmount) > 0
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
// 页面加载时获取当前位置
|
||||
//this.getCurrentLocation()
|
||||
// 页面加载时获取设备类型列表
|
||||
this.getDeviceTypes()
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
@ -126,10 +158,16 @@ export default {
|
|||
address: '',
|
||||
detailAddress: '',
|
||||
equipment: '',
|
||||
period: '1年',
|
||||
equipmentId: '', // 设备类型ID
|
||||
period: '',
|
||||
periodId: '', // 租赁周期ID
|
||||
},
|
||||
showDetails: false,
|
||||
totalAmount: '100.10',
|
||||
totalAmount: '0.00',
|
||||
deviceTypes: [], // 设备类型列表
|
||||
periodPackages: [], // 租赁周期套餐列表
|
||||
selectedDevice: null, // 选中的设备
|
||||
selectedPackage: null, // 选中的套餐
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -153,23 +191,112 @@ export default {
|
|||
console.log('地图已打开')
|
||||
// 可以在这里处理地图打开后的逻辑
|
||||
},
|
||||
|
||||
// 获取设备类型列表
|
||||
async getDeviceTypes() {
|
||||
try {
|
||||
const response = await fetchDeviceTypes()
|
||||
|
||||
if (response.code === 200) {
|
||||
this.deviceTypes = response.data
|
||||
console.log('设备类型列表:', this.deviceTypes)
|
||||
} else {
|
||||
throw new Error(response.message || '获取设备类型失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取设备类型失败:', error)
|
||||
uni.showToast({
|
||||
title: error.message || '获取设备类型失败',
|
||||
icon: 'error',
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
// 根据设备类型获取租赁套餐
|
||||
async getPeriodPackages(typeId) {
|
||||
try {
|
||||
const response = await fetchPeriodPackages(typeId)
|
||||
|
||||
if (response.code === 200) {
|
||||
this.periodPackages = response.data
|
||||
console.log('租赁套餐列表:', this.periodPackages)
|
||||
} else {
|
||||
throw new Error(response.message || '获取租赁套餐失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取租赁套餐失败:', error)
|
||||
uni.showToast({
|
||||
title: error.message || '获取租赁套餐失败',
|
||||
icon: 'error',
|
||||
})
|
||||
}
|
||||
},
|
||||
selectEquipment() {
|
||||
// 选择设备逻辑
|
||||
// 检查是否有设备类型数据
|
||||
if (this.deviceTypes.length === 0) {
|
||||
uni.showToast({
|
||||
title: '设备类型加载中,请稍后重试',
|
||||
icon: 'none',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 构建设备类型选项列表
|
||||
const itemList = this.deviceTypes.map(item => item.name)
|
||||
|
||||
uni.showActionSheet({
|
||||
itemList: ['节能灶', '燃烧器', '燃气灶', '电磁炉'],
|
||||
itemList: itemList,
|
||||
success: res => {
|
||||
const equipmentList = ['节能灶', '燃烧器', '燃气灶', '电磁炉']
|
||||
this.formData.equipment = equipmentList[res.tapIndex]
|
||||
const selectedDevice = this.deviceTypes[res.tapIndex]
|
||||
this.selectedDevice = selectedDevice
|
||||
this.formData.equipment = selectedDevice.name
|
||||
this.formData.equipmentId = selectedDevice.id
|
||||
|
||||
// 清空之前选择的套餐
|
||||
this.formData.period = ''
|
||||
this.formData.periodId = ''
|
||||
this.selectedPackage = null
|
||||
this.totalAmount = '0.00'
|
||||
|
||||
// 根据选中的设备类型获取租赁套餐
|
||||
this.getPeriodPackages(selectedDevice.id)
|
||||
|
||||
console.log('选中设备:', selectedDevice)
|
||||
},
|
||||
})
|
||||
},
|
||||
selectPeriod() {
|
||||
// 选择租赁周期逻辑
|
||||
// 检查是否已选择设备
|
||||
if (!this.formData.equipmentId) {
|
||||
uni.showToast({
|
||||
title: '请先选择设备类型',
|
||||
icon: 'none',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否有套餐数据
|
||||
if (this.periodPackages.length === 0) {
|
||||
uni.showToast({
|
||||
title: '套餐加载中,请稍后重试',
|
||||
icon: 'none',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 构建套餐选项列表
|
||||
const itemList = this.periodPackages.map(item => `${item.name} ¥${item.amount}`)
|
||||
|
||||
uni.showActionSheet({
|
||||
itemList: ['1个月', '3个月', '6个月', '1年', '2年'],
|
||||
itemList: itemList,
|
||||
success: res => {
|
||||
const periodList = ['1个月', '3个月', '6个月', '1年', '2年']
|
||||
this.formData.period = periodList[res.tapIndex]
|
||||
const selectedPackage = this.periodPackages[res.tapIndex]
|
||||
this.selectedPackage = selectedPackage
|
||||
this.formData.period = selectedPackage.name
|
||||
this.formData.periodId = selectedPackage.id
|
||||
this.totalAmount = selectedPackage.amount.toFixed(2)
|
||||
|
||||
console.log('选中套餐:', selectedPackage)
|
||||
},
|
||||
})
|
||||
},
|
||||
|
|
@ -177,12 +304,69 @@ export default {
|
|||
this.showDetails = !this.showDetails
|
||||
},
|
||||
handlePayment() {
|
||||
// 表单验证
|
||||
if (!this.formData.name.trim()) {
|
||||
uni.showToast({
|
||||
title: '请输入姓名',
|
||||
icon: 'none',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.formData.phone.trim()) {
|
||||
uni.showToast({
|
||||
title: '请输入手机号',
|
||||
icon: 'none',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.formData.address.trim()) {
|
||||
uni.showToast({
|
||||
title: '请选择地址',
|
||||
icon: 'none',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.formData.equipmentId) {
|
||||
uni.showToast({
|
||||
title: '请选择设备类型',
|
||||
icon: 'none',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.formData.periodId) {
|
||||
uni.showToast({
|
||||
title: '请选择租赁周期',
|
||||
icon: 'none',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (parseFloat(this.totalAmount) <= 0) {
|
||||
uni.showToast({
|
||||
title: '金额无效',
|
||||
icon: 'none',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 支付逻辑
|
||||
uni.showModal({
|
||||
title: '确认支付',
|
||||
content: `确认支付 ¥${this.totalAmount} 吗?`,
|
||||
content: `确认支付 ¥${this.totalAmount} 吗?\n\n设备:${this.formData.equipment}\n周期:${this.formData.period}`,
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
// 这里可以调用支付API
|
||||
console.log('支付信息:', {
|
||||
...this.formData,
|
||||
amount: this.totalAmount,
|
||||
selectedDevice: this.selectedDevice,
|
||||
selectedPackage: this.selectedPackage
|
||||
})
|
||||
|
||||
uni.showToast({
|
||||
title: '支付成功',
|
||||
icon: 'success',
|
||||
|
|
@ -307,10 +491,8 @@ export default {
|
|||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 80rpx;
|
||||
|
||||
border-radius: 12rpx;
|
||||
padding: 0 20rpx;
|
||||
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
|
|
@ -321,6 +503,10 @@ export default {
|
|||
.selector-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
|
||||
&.placeholder {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.arrow-icon {
|
||||
|
|
@ -350,6 +536,18 @@ export default {
|
|||
font-weight: bold;
|
||||
margin-bottom: 40rpx;
|
||||
box-shadow: 0 10rpx 30rpx rgba(255, 154, 158, 0.3);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&.disabled {
|
||||
background: #ccc;
|
||||
color: #999;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&:not(.disabled):active {
|
||||
transform: translateY(2rpx);
|
||||
box-shadow: 0 8rpx 20rpx rgba(255, 154, 158, 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
.payment-details {
|
||||
|
|
@ -425,3 +623,4 @@ export default {
|
|||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
<!-- 登录按钮 -->
|
||||
<button :disabled="loginLoading" class="login-btn" @click="getPhoneNumber">
|
||||
<text class="btn-text">{{ loginLoading ? '登录中...' : '微信用户一键登录' }}</text>
|
||||
</button>
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<!-- 底部协议 -->
|
||||
|
|
@ -246,38 +246,38 @@ export default {
|
|||
|
||||
wxLogin(data)
|
||||
.then(res => {
|
||||
if (that.pageLoading) {
|
||||
that.pageLoading.hide()
|
||||
}
|
||||
if (that.pageLoading) {
|
||||
that.pageLoading.hide()
|
||||
}
|
||||
forceHideLoading()
|
||||
|
||||
if (res.code == 200) {
|
||||
if (res.code == 200) {
|
||||
console.log(res, 'resres')
|
||||
uni.setStorageSync('token', res.token)
|
||||
uni.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'success',
|
||||
uni.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'success',
|
||||
duration: 1500,
|
||||
})
|
||||
setTimeout(() => {
|
||||
that.ceshi()
|
||||
setTimeout(() => {
|
||||
that.ceshi()
|
||||
}, 1500)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.msg || '登录失败',
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.msg || '登录失败',
|
||||
icon: 'none',
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if (that.pageLoading) {
|
||||
that.pageLoading.hide()
|
||||
}
|
||||
if (that.pageLoading) {
|
||||
that.pageLoading.hide()
|
||||
}
|
||||
forceHideLoading()
|
||||
|
||||
console.error('登录失败:', error)
|
||||
uni.showToast({
|
||||
title: '登录失败',
|
||||
uni.showToast({
|
||||
title: '登录失败',
|
||||
icon: 'none',
|
||||
})
|
||||
})
|
||||
|
|
@ -329,7 +329,7 @@ page {
|
|||
.logo-image {
|
||||
width: 276rpx;
|
||||
height: 276rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.main-content {
|
||||
padding: 0 53rpx;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user