docs: 更新项目文档,完善需求和技术细节
This commit is contained in:
@@ -37,33 +37,33 @@
|
||||
<!-- 订单列表 -->
|
||||
<el-table :data="orderList" border style="width: 100%" v-loading="loading">
|
||||
<el-table-column prop="id" label="ID" width="80" />
|
||||
<el-table-column prop="orderNo" label="订单号" width="180" />
|
||||
<el-table-column prop="order_number" label="订单号" width="180" />
|
||||
<el-table-column prop="username" label="用户" />
|
||||
<el-table-column prop="phone" label="手机号" width="120" />
|
||||
<el-table-column prop="amount" label="订单金额" width="100">
|
||||
<el-table-column prop="total_amount" label="订单金额" width="100">
|
||||
<template #default="scope">
|
||||
¥{{ scope.row.amount }}
|
||||
¥{{ scope.row.total_amount }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="支付状态" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.paymentStatus === 'pending'">待支付</el-tag>
|
||||
<el-tag v-else-if="scope.row.paymentStatus === 'paid'" type="success">已支付</el-tag>
|
||||
<el-tag v-else-if="scope.row.paymentStatus === 'cancelled'" type="danger">已取消</el-tag>
|
||||
<el-tag v-else>{{ scope.row.paymentStatus }}</el-tag>
|
||||
<el-tag v-if="scope.row.payment_status === 'pending'">待支付</el-tag>
|
||||
<el-tag v-else-if="scope.row.payment_status === 'paid'" type="success">已支付</el-tag>
|
||||
<el-tag v-else-if="scope.row.payment_status === 'cancelled'" type="danger">已取消</el-tag>
|
||||
<el-tag v-else>{{ scope.row.payment_status }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="发货状态" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.shippingStatus === 'pending'">待发货</el-tag>
|
||||
<el-tag v-else-if="scope.row.shippingStatus === 'shipped'" type="success">已发货</el-tag>
|
||||
<el-tag v-else-if="scope.row.shippingStatus === 'completed'" type="primary">已完成</el-tag>
|
||||
<el-tag v-else>{{ scope.row.shippingStatus }}</el-tag>
|
||||
<el-tag v-if="scope.row.shipping_status === 'pending'">待发货</el-tag>
|
||||
<el-tag v-else-if="scope.row.shipping_status === 'shipped'" type="success">已发货</el-tag>
|
||||
<el-tag v-else-if="scope.row.shipping_status === 'completed'" type="primary">已完成</el-tag>
|
||||
<el-tag v-else>{{ scope.row.shipping_status }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="下单时间" width="180">
|
||||
<el-table-column prop="created_at" label="下单时间" width="180">
|
||||
<template #default="scope">
|
||||
{{ formatDate(scope.row.createTime) }}
|
||||
{{ formatDate(scope.row.created_at) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="150">
|
||||
@@ -73,7 +73,7 @@
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleUpdateStatus(scope.row)"
|
||||
:disabled="scope.row.paymentStatus === 'cancelled'"
|
||||
:disabled="scope.row.payment_status === 'cancelled'"
|
||||
>
|
||||
状态
|
||||
</el-button>
|
||||
@@ -96,37 +96,37 @@
|
||||
<!-- 订单详情对话框 -->
|
||||
<el-dialog v-model="detailDialogVisible" title="订单详情" width="700px">
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="订单号">{{ currentOrder.orderNo }}</el-descriptions-item>
|
||||
<el-descriptions-item label="订单号">{{ currentOrder.order_number }}</el-descriptions-item>
|
||||
<el-descriptions-item label="用户">{{ currentOrder.username }}</el-descriptions-item>
|
||||
<el-descriptions-item label="手机号">{{ currentOrder.phone }}</el-descriptions-item>
|
||||
<el-descriptions-item label="订单金额">¥{{ currentOrder.amount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="订单金额">¥{{ currentOrder.total_amount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="支付状态">
|
||||
<el-tag v-if="currentOrder.paymentStatus === 'pending'">待支付</el-tag>
|
||||
<el-tag v-else-if="currentOrder.paymentStatus === 'paid'" type="success">已支付</el-tag>
|
||||
<el-tag v-else-if="currentOrder.paymentStatus === 'cancelled'" type="danger">已取消</el-tag>
|
||||
<el-tag v-else>{{ currentOrder.paymentStatus }}</el-tag>
|
||||
<el-tag v-if="currentOrder.payment_status === 'pending'">待支付</el-tag>
|
||||
<el-tag v-else-if="currentOrder.payment_status === 'paid'" type="success">已支付</el-tag>
|
||||
<el-tag v-else-if="currentOrder.payment_status === 'cancelled'" type="danger">已取消</el-tag>
|
||||
<el-tag v-else>{{ currentOrder.payment_status }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="发货状态">
|
||||
<el-tag v-if="currentOrder.shippingStatus === 'pending'">待发货</el-tag>
|
||||
<el-tag v-else-if="currentOrder.shippingStatus === 'shipped'" type="success">已发货</el-tag>
|
||||
<el-tag v-else-if="currentOrder.shippingStatus === 'completed'" type="primary">已完成</el-tag>
|
||||
<el-tag v-else>{{ currentOrder.shippingStatus }}</el-tag>
|
||||
<el-tag v-if="currentOrder.shipping_status === 'pending'">待发货</el-tag>
|
||||
<el-tag v-else-if="currentOrder.shipping_status === 'shipped'" type="success">已发货</el-tag>
|
||||
<el-tag v-else-if="currentOrder.shipping_status === 'completed'" type="primary">已完成</el-tag>
|
||||
<el-tag v-else>{{ currentOrder.shipping_status }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="收货地址">{{ currentOrder.shippingAddress }}</el-descriptions-item>
|
||||
<el-descriptions-item label="下单时间">{{ formatDate(currentOrder.createTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="收货地址">{{ currentOrder.shipping_address }}</el-descriptions-item>
|
||||
<el-descriptions-item label="下单时间">{{ formatDate(currentOrder.created_at) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-table :data="currentOrder.items" style="margin-top: 20px;" border>
|
||||
<el-table-column prop="productName" label="商品名称" />
|
||||
<el-table-column prop="product_name" label="商品名称" />
|
||||
<el-table-column prop="quantity" label="数量" width="80" />
|
||||
<el-table-column prop="unitPrice" label="单价" width="100">
|
||||
<el-table-column prop="unit_price" label="单价" width="100">
|
||||
<template #default="scope">
|
||||
¥{{ scope.row.unitPrice }}
|
||||
¥{{ scope.row.unit_price }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="小计" width="100">
|
||||
<template #default="scope">
|
||||
¥{{ (scope.row.unitPrice * scope.row.quantity).toFixed(2) }}
|
||||
¥{{ (scope.row.unit_price * scope.row.quantity).toFixed(2) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -142,14 +142,14 @@
|
||||
<el-dialog v-model="statusDialogVisible" title="更新订单状态" width="500px">
|
||||
<el-form :model="statusForm" label-width="100px">
|
||||
<el-form-item label="支付状态">
|
||||
<el-select v-model="statusForm.paymentStatus" placeholder="请选择">
|
||||
<el-select v-model="statusForm.payment_status" placeholder="请选择">
|
||||
<el-option label="待支付" value="pending" />
|
||||
<el-option label="已支付" value="paid" />
|
||||
<el-option label="已取消" value="cancelled" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="发货状态">
|
||||
<el-select v-model="statusForm.shippingStatus" placeholder="请选择">
|
||||
<el-select v-model="statusForm.shipping_status" placeholder="请选择">
|
||||
<el-option label="待发货" value="pending" />
|
||||
<el-option label="已发货" value="shipped" />
|
||||
<el-option label="已完成" value="completed" />
|
||||
@@ -169,7 +169,8 @@
|
||||
|
||||
<script>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { orderAPI } from '../utils/api'
|
||||
|
||||
export default {
|
||||
name: 'Orders',
|
||||
@@ -186,8 +187,8 @@ export default {
|
||||
|
||||
const statusForm = reactive({
|
||||
id: null,
|
||||
paymentStatus: '',
|
||||
shippingStatus: ''
|
||||
payment_status: '',
|
||||
shipping_status: ''
|
||||
})
|
||||
|
||||
const orderList = ref([])
|
||||
@@ -209,58 +210,23 @@ export default {
|
||||
const fetchOrders = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
// 模拟API调用
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
const params = {
|
||||
page: pagination.page,
|
||||
limit: pagination.limit,
|
||||
status: searchForm.status,
|
||||
start_date: dateRange.value && dateRange.value[0] ? dateRange.value[0] : undefined,
|
||||
end_date: dateRange.value && dateRange.value[1] ? dateRange.value[1] : undefined
|
||||
}
|
||||
|
||||
// 模拟数据
|
||||
orderList.value = [
|
||||
{
|
||||
id: 1,
|
||||
orderNo: 'ORD202401150001',
|
||||
username: 'user001',
|
||||
phone: '13800001111',
|
||||
amount: 199,
|
||||
paymentStatus: 'paid',
|
||||
shippingStatus: 'shipped',
|
||||
createTime: '2024-01-15 10:30:00',
|
||||
shippingAddress: '浙江省杭州市西湖区文三路159号',
|
||||
items: [
|
||||
{ productName: 'AI鉴花小程序', quantity: 1, unitPrice: 199 }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
orderNo: 'ORD202401160002',
|
||||
username: 'admin',
|
||||
phone: '13900002222',
|
||||
amount: 598,
|
||||
paymentStatus: 'paid',
|
||||
shippingStatus: 'pending',
|
||||
createTime: '2024-01-16 14:20:00',
|
||||
shippingAddress: '浙江省杭州市滨江区网商路699号',
|
||||
items: [
|
||||
{ productName: '花卉识别API', quantity: 2, unitPrice: 299 }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
orderNo: 'ORD202401170003',
|
||||
username: 'editor001',
|
||||
phone: '13700003333',
|
||||
amount: 999,
|
||||
paymentStatus: 'pending',
|
||||
shippingStatus: 'pending',
|
||||
createTime: '2024-01-17 09:15:00',
|
||||
shippingAddress: '浙江省杭州市余杭区五常大道1001号',
|
||||
items: [
|
||||
{ productName: '企业版解决方案', quantity: 1, unitPrice: 999 }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
pagination.total = orderList.value.length
|
||||
const response = await orderAPI.getOrders(params)
|
||||
if (response.code === 200) {
|
||||
orderList.value = response.data.orders
|
||||
pagination.total = response.data.pagination.total
|
||||
} else {
|
||||
ElMessage.error(response.message || '获取订单列表失败')
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('获取订单列表失败')
|
||||
ElMessage.error('获取订单列表失败: ' + error.message)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
@@ -282,35 +248,35 @@ export default {
|
||||
|
||||
// 查看订单详情
|
||||
const handleView = (row) => {
|
||||
currentOrder.value = { ...row }
|
||||
currentOrder.value = row
|
||||
detailDialogVisible.value = true
|
||||
}
|
||||
|
||||
// 更新订单状态
|
||||
const handleUpdateStatus = (row) => {
|
||||
statusForm.id = row.id
|
||||
statusForm.paymentStatus = row.paymentStatus
|
||||
statusForm.shippingStatus = row.shippingStatus
|
||||
statusForm.payment_status = row.payment_status
|
||||
statusForm.shipping_status = row.shipping_status
|
||||
statusDialogVisible.value = true
|
||||
}
|
||||
|
||||
// 提交状态更新
|
||||
const submitStatusUpdate = async () => {
|
||||
try {
|
||||
// 模拟API调用
|
||||
await new Promise(resolve => setTimeout(resolve, 300))
|
||||
const response = await orderAPI.updateOrderStatus(statusForm.id, {
|
||||
payment_status: statusForm.payment_status,
|
||||
shipping_status: statusForm.shipping_status
|
||||
})
|
||||
|
||||
// 更新订单状态
|
||||
const index = orderList.value.findIndex(item => item.id === statusForm.id)
|
||||
if (index !== -1) {
|
||||
orderList.value[index].paymentStatus = statusForm.paymentStatus
|
||||
orderList.value[index].shippingStatus = statusForm.shippingStatus
|
||||
if (response.code === 200) {
|
||||
ElMessage.success('状态更新成功')
|
||||
statusDialogVisible.value = false
|
||||
fetchOrders()
|
||||
} else {
|
||||
ElMessage.error(response.message || '状态更新失败')
|
||||
}
|
||||
|
||||
ElMessage.success('状态更新成功')
|
||||
statusDialogVisible.value = false
|
||||
} catch (error) {
|
||||
ElMessage.error('状态更新失败')
|
||||
ElMessage.error('状态更新失败: ' + error.message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import * as echarts from 'echarts'
|
||||
import { statisticsAPI } from '../utils/api'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
export default {
|
||||
name: 'Statistics',
|
||||
@@ -137,60 +138,62 @@ export default {
|
||||
// 获取统计数据
|
||||
const fetchStatsData = async () => {
|
||||
try {
|
||||
// 模拟数据
|
||||
statsData.userCount = 1234
|
||||
statsData.productCount = 567
|
||||
statsData.orderCount = 890
|
||||
statsData.totalRevenue = 123456.78
|
||||
const response = await statisticsAPI.getUserStats()
|
||||
if (response.code === 200) {
|
||||
statsData.userCount = response.data.user_count
|
||||
statsData.productCount = response.data.product_count
|
||||
statsData.orderCount = response.data.order_count
|
||||
statsData.totalRevenue = response.data.total_revenue
|
||||
} else {
|
||||
ElMessage.error(response.message || '获取统计数据失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取统计数据失败:', error)
|
||||
ElMessage.error('获取统计数据失败: ' + error.message)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户图表数据
|
||||
const fetchUserChartData = async () => {
|
||||
try {
|
||||
// 模拟数据
|
||||
chartData.userGrowth = {
|
||||
dates: ['1月1日', '1月2日', '1月3日', '1月4日', '1月5日', '1月6日', '1月7日'],
|
||||
counts: [10, 25, 15, 30, 20, 35, 40]
|
||||
const response = await statisticsAPI.getUserStats()
|
||||
if (response.code === 200) {
|
||||
chartData.userGrowth = response.data.user_growth
|
||||
renderUserChart()
|
||||
} else {
|
||||
ElMessage.error(response.message || '获取用户图表数据失败')
|
||||
}
|
||||
renderUserChart()
|
||||
} catch (error) {
|
||||
console.error('获取用户图表数据失败:', error)
|
||||
ElMessage.error('获取用户图表数据失败: ' + error.message)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取分类图表数据
|
||||
const fetchCategoryChartData = async () => {
|
||||
try {
|
||||
// 模拟数据
|
||||
chartData.categoryDistribution = [
|
||||
{ name: '鲜花', value: 45 },
|
||||
{ name: '盆栽', value: 30 },
|
||||
{ name: '种子', value: 15 },
|
||||
{ name: '工具', value: 10 }
|
||||
]
|
||||
renderCategoryChart()
|
||||
const response = await statisticsAPI.getProductStats()
|
||||
if (response.code === 200) {
|
||||
chartData.categoryDistribution = response.data.category_distribution
|
||||
renderCategoryChart()
|
||||
} else {
|
||||
ElMessage.error(response.message || '获取分类图表数据失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取分类图表数据失败:', error)
|
||||
ElMessage.error('获取分类图表数据失败: ' + error.message)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取订单状态图表数据
|
||||
const fetchOrderStatusChartData = async () => {
|
||||
try {
|
||||
// 模拟数据
|
||||
chartData.orderStatusDistribution = [
|
||||
{ name: '待支付', value: 20 },
|
||||
{ name: '已支付', value: 50 },
|
||||
{ name: '已发货', value: 15 },
|
||||
{ name: '已完成', value: 10 },
|
||||
{ name: '已取消', value: 5 }
|
||||
]
|
||||
renderOrderStatusChart()
|
||||
const response = await statisticsAPI.getOrderStats()
|
||||
if (response.code === 200) {
|
||||
chartData.orderStatusDistribution = response.data.status_distribution
|
||||
renderOrderStatusChart()
|
||||
} else {
|
||||
ElMessage.error(response.message || '获取订单状态图表数据失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取订单状态图表数据失败:', error)
|
||||
ElMessage.error('获取订单状态图表数据失败: ' + error.message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,18 +6,15 @@
|
||||
|
||||
## 基础信息
|
||||
|
||||
- **基础URL**: `http://localhost:3200/api/v1`
|
||||
- **Base URL**: `http://localhost:3200/api/v1`
|
||||
- **认证方式**: Bearer Token (JWT)
|
||||
- **数据格式**: JSON
|
||||
- **字符编码**: UTF-8
|
||||
- **响应格式**: JSON
|
||||
|
||||
## 认证接口
|
||||
|
||||
### 用户注册
|
||||
|
||||
```http
|
||||
POST /auth/register
|
||||
```
|
||||
**POST** `/auth/register`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
@@ -30,6 +27,7 @@ POST /auth/register
|
||||
| user_type | string | 否 | 用户类型(farmer/buyer/admin) |
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 201,
|
||||
@@ -47,9 +45,7 @@ POST /auth/register
|
||||
|
||||
### 用户登录
|
||||
|
||||
```http
|
||||
POST /auth/login
|
||||
```
|
||||
**POST** `/auth/login`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
@@ -59,6 +55,7 @@ POST /auth/login
|
||||
| password | string | 是 | 密码 |
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
@@ -79,9 +76,7 @@ POST /auth/login
|
||||
|
||||
### 获取用户信息
|
||||
|
||||
```http
|
||||
GET /users/me
|
||||
```
|
||||
**GET** `/users/me`
|
||||
|
||||
**请求头**:
|
||||
```
|
||||
@@ -89,6 +84,7 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
@@ -108,9 +104,7 @@ Authorization: Bearer <token>
|
||||
|
||||
### 更新用户信息
|
||||
|
||||
```http
|
||||
PUT /users/{id}
|
||||
```
|
||||
**PUT** `/users/{id}`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
@@ -124,9 +118,7 @@ PUT /users/{id}
|
||||
|
||||
### 获取商品列表
|
||||
|
||||
```http
|
||||
GET /products
|
||||
```
|
||||
**GET** `/products`
|
||||
|
||||
**查询参数**:
|
||||
|
||||
@@ -142,6 +134,7 @@ GET /products
|
||||
| sort_order | string | 排序方向(asc/desc) |
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
@@ -171,17 +164,13 @@ GET /products
|
||||
|
||||
### 获取商品详情
|
||||
|
||||
```http
|
||||
GET /products/{id}
|
||||
```
|
||||
**GET** `/products/{id}`
|
||||
|
||||
## 订单接口
|
||||
|
||||
### 创建订单
|
||||
|
||||
```http
|
||||
POST /orders
|
||||
```
|
||||
**POST** `/orders`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
@@ -204,9 +193,7 @@ POST /orders
|
||||
|
||||
### 花卉识别
|
||||
|
||||
```http
|
||||
POST /identifications/identify
|
||||
```
|
||||
**POST** `/identifications/identify`
|
||||
|
||||
**请求格式**: `multipart/form-data`
|
||||
|
||||
@@ -217,6 +204,7 @@ POST /identifications/identify
|
||||
| image | file | 是 | 花卉图片文件 |
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
@@ -244,9 +232,7 @@ POST /identifications/identify
|
||||
|
||||
### 获取识别历史
|
||||
|
||||
```http
|
||||
GET /identifications
|
||||
```
|
||||
**GET** `/identifications`
|
||||
|
||||
## 错误码说明
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## 基础信息
|
||||
|
||||
- **Base URL**: `http://localhost:3200/api`
|
||||
- **Base URL**: `http://localhost:3200/api/v1`
|
||||
- **认证方式**: Bearer Token (JWT)
|
||||
- **响应格式**: JSON
|
||||
|
||||
@@ -258,9 +258,10 @@
|
||||
| 错误码 | 说明 |
|
||||
|--------|------|
|
||||
| 200 | 成功 |
|
||||
| 400 | 请求参数错误 |
|
||||
| 201 | 创建成功 |
|
||||
| 400 | 参数错误 |
|
||||
| 401 | 未授权 |
|
||||
| 403 | 权限不足 |
|
||||
| 403 | 禁止访问 |
|
||||
| 404 | 资源不存在 |
|
||||
| 409 | 资源冲突 |
|
||||
| 500 | 服务器内部错误 |
|
||||
|
||||
Reference in New Issue
Block a user