567 lines
16 KiB
JavaScript
567 lines
16 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const { getDB } = require('../database');
|
|
const { auth } = require('../middleware/auth');
|
|
|
|
/**
|
|
* @swagger
|
|
* components:
|
|
* schemas:
|
|
* Address:
|
|
* type: object
|
|
* properties:
|
|
* id:
|
|
* type: integer
|
|
* description: 地址ID
|
|
* user_id:
|
|
* type: integer
|
|
* description: 用户ID
|
|
* recipient_name:
|
|
* type: string
|
|
* description: 收件人姓名
|
|
* phone:
|
|
* type: string
|
|
* description: 联系电话
|
|
* province_code:
|
|
* type: string
|
|
* description: 省份编码
|
|
* province_name:
|
|
* type: string
|
|
* description: 省份名称
|
|
* city_code:
|
|
* type: string
|
|
* description: 城市编码
|
|
* city_name:
|
|
* type: string
|
|
* description: 城市名称
|
|
* district_code:
|
|
* type: string
|
|
* description: 区县编码
|
|
* district_name:
|
|
* type: string
|
|
* description: 区县名称
|
|
* detailed_address:
|
|
* type: string
|
|
* description: 详细地址
|
|
* postal_code:
|
|
* type: string
|
|
* description: 邮政编码
|
|
* label_id:
|
|
* type: integer
|
|
* description: 地址标签ID
|
|
* is_default:
|
|
* type: boolean
|
|
* description: 是否为默认地址
|
|
* label_name:
|
|
* type: string
|
|
* description: 标签名称
|
|
* label_color:
|
|
* type: string
|
|
* description: 标签颜色
|
|
* required:
|
|
* - recipient_name
|
|
* - phone
|
|
* - province_code
|
|
* - province_name
|
|
* - city_code
|
|
* - city_name
|
|
* - district_code
|
|
* - district_name
|
|
* - detailed_address
|
|
*/
|
|
|
|
/**
|
|
* @swagger
|
|
* /addresses:
|
|
* get:
|
|
* summary: 获取用户收货地址列表
|
|
* tags: [Addresses]
|
|
* security:
|
|
* - bearerAuth: []
|
|
* responses:
|
|
* 200:
|
|
* description: 成功获取地址列表
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* success:
|
|
* type: boolean
|
|
* data:
|
|
* type: array
|
|
* items:
|
|
* $ref: '#/components/schemas/Address'
|
|
* 401:
|
|
* description: 未授权
|
|
* 500:
|
|
* description: 服务器错误
|
|
*/
|
|
router.get('/', auth, async (req, res) => {
|
|
try {
|
|
const userId = req.user.id;
|
|
|
|
const [addresses] = await getDB().execute(
|
|
`SELECT ua.*, al.name as label_name, al.color as label_color,
|
|
p.name as province_name, c.name as city_name, d.name as district_name
|
|
FROM user_addresses ua
|
|
LEFT JOIN address_labels al ON ua.label = al.id
|
|
LEFT JOIN china_regions p ON ua.province = p.code
|
|
LEFT JOIN china_regions c ON ua.city = c.code
|
|
LEFT JOIN china_regions d ON ua.district = d.code
|
|
WHERE ua.user_id = ?
|
|
ORDER BY ua.is_default DESC, ua.created_at DESC`,
|
|
[userId]
|
|
);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: addresses
|
|
});
|
|
} catch (error) {
|
|
console.error('获取收货地址列表错误:', error);
|
|
res.status(500).json({ message: '获取收货地址列表失败' });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /addresses/{id}:
|
|
* get:
|
|
* summary: 获取单个收货地址详情
|
|
* tags: [Addresses]
|
|
* security:
|
|
* - bearerAuth: []
|
|
* parameters:
|
|
* - in: path
|
|
* name: id
|
|
* required: true
|
|
* schema:
|
|
* type: integer
|
|
* description: 地址ID
|
|
* responses:
|
|
* 200:
|
|
* description: 成功获取地址详情
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* success:
|
|
* type: boolean
|
|
* data:
|
|
* $ref: '#/components/schemas/Address'
|
|
* 401:
|
|
* description: 未授权
|
|
* 404:
|
|
* description: 地址不存在
|
|
* 500:
|
|
* description: 服务器错误
|
|
*/
|
|
router.get('/:id', auth, async (req, res) => {
|
|
try {
|
|
const addressId = req.params.id;
|
|
const userId = req.user.id;
|
|
|
|
const [addresses] = await getDB().execute(
|
|
`SELECT ua.*, al.name as label_name, al.color as label_color
|
|
FROM user_addresses ua
|
|
LEFT JOIN address_labels al ON ua.label_id = al.id
|
|
WHERE ua.id = ? AND ua.user_id = ? AND ua.deleted_at IS NULL`,
|
|
[addressId, userId]
|
|
);
|
|
|
|
if (addresses.length === 0) {
|
|
return res.status(404).json({ message: '收货地址不存在' });
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
data: addresses[0]
|
|
});
|
|
} catch (error) {
|
|
console.error('获取收货地址详情错误:', error);
|
|
res.status(500).json({ message: '获取收货地址详情失败' });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /addresses:
|
|
* post:
|
|
* summary: 创建收货地址
|
|
* tags: [Addresses]
|
|
* security:
|
|
* - bearerAuth: []
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* recipient_name:
|
|
* type: string
|
|
* description: 收件人姓名
|
|
* phone:
|
|
* type: string
|
|
* description: 联系电话
|
|
* province_code:
|
|
* type: string
|
|
* description: 省份编码
|
|
* province_name:
|
|
* type: string
|
|
* description: 省份名称
|
|
* city_code:
|
|
* type: string
|
|
* description: 城市编码
|
|
* city_name:
|
|
* type: string
|
|
* description: 城市名称
|
|
* district_code:
|
|
* type: string
|
|
* description: 区县编码
|
|
* district_name:
|
|
* type: string
|
|
* description: 区县名称
|
|
* detailed_address:
|
|
* type: string
|
|
* description: 详细地址
|
|
* postal_code:
|
|
* type: string
|
|
* description: 邮政编码
|
|
* label_id:
|
|
* type: integer
|
|
* description: 地址标签ID
|
|
* is_default:
|
|
* type: boolean
|
|
* description: 是否为默认地址
|
|
* required:
|
|
* - recipient_name
|
|
* - phone
|
|
* - province_code
|
|
* - province_name
|
|
* - city_code
|
|
* - city_name
|
|
* - district_code
|
|
* - district_name
|
|
* - detailed_address
|
|
* responses:
|
|
* 201:
|
|
* description: 地址创建成功
|
|
* 400:
|
|
* description: 请求参数错误
|
|
* 401:
|
|
* description: 未授权
|
|
* 500:
|
|
* description: 服务器错误
|
|
*/
|
|
router.post('/', auth, async (req, res) => {
|
|
try {
|
|
const userId = req.user.id;
|
|
const {
|
|
recipient_name,
|
|
phone,
|
|
province_code,
|
|
city_code,
|
|
district_code,
|
|
detailed_address,
|
|
is_default = false
|
|
} = req.body;
|
|
|
|
// 验证必填字段
|
|
if (!recipient_name || !phone || !province_code || !city_code || !district_code || !detailed_address) {
|
|
return res.status(400).json({ message: '收件人姓名、电话、省市区和详细地址不能为空' });
|
|
}
|
|
|
|
// 如果设置为默认地址,先取消其他默认地址
|
|
if (is_default) {
|
|
await getDB().execute(
|
|
'UPDATE user_addresses SET is_default = false WHERE user_id = ? ',
|
|
[userId]
|
|
);
|
|
}
|
|
|
|
const [result] = await getDB().execute(
|
|
`INSERT INTO user_addresses (
|
|
user_id, receiver_name, receiver_phone, province, city,
|
|
district, detailed_address, is_default, created_at, updated_at
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())`,
|
|
[
|
|
userId, recipient_name, phone, province_code, city_code,
|
|
district_code, detailed_address, is_default
|
|
]
|
|
);
|
|
|
|
res.status(201).json({
|
|
success: true,
|
|
message: '收货地址创建成功',
|
|
data: { addressId: result.insertId }
|
|
});
|
|
} catch (error) {
|
|
console.error('创建收货地址错误:', error);
|
|
res.status(500).json({ message: '创建收货地址失败' });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /addresses/{id}:
|
|
* put:
|
|
* summary: 更新收货地址
|
|
* tags: [Addresses]
|
|
* security:
|
|
* - bearerAuth: []
|
|
* parameters:
|
|
* - in: path
|
|
* name: id
|
|
* required: true
|
|
* schema:
|
|
* type: integer
|
|
* description: 地址ID
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* recipient_name:
|
|
* type: string
|
|
* description: 收件人姓名
|
|
* phone:
|
|
* type: string
|
|
* description: 联系电话
|
|
* province_code:
|
|
* type: string
|
|
* description: 省份编码
|
|
* province_name:
|
|
* type: string
|
|
* description: 省份名称
|
|
* city_code:
|
|
* type: string
|
|
* description: 城市编码
|
|
* city_name:
|
|
* type: string
|
|
* description: 城市名称
|
|
* district_code:
|
|
* type: string
|
|
* description: 区县编码
|
|
* district_name:
|
|
* type: string
|
|
* description: 区县名称
|
|
* detailed_address:
|
|
* type: string
|
|
* description: 详细地址
|
|
* postal_code:
|
|
* type: string
|
|
* description: 邮政编码
|
|
* label_id:
|
|
* type: integer
|
|
* description: 地址标签ID
|
|
* is_default:
|
|
* type: boolean
|
|
* description: 是否为默认地址
|
|
* responses:
|
|
* 200:
|
|
* description: 地址更新成功
|
|
* 400:
|
|
* description: 请求参数错误
|
|
* 401:
|
|
* description: 未授权
|
|
* 404:
|
|
* description: 地址不存在
|
|
* 500:
|
|
* description: 服务器错误
|
|
*/
|
|
router.put('/:id', auth, async (req, res) => {
|
|
try {
|
|
const addressId = req.params.id;
|
|
const userId = req.user.id;
|
|
const {
|
|
recipient_name,
|
|
phone,
|
|
province_code,
|
|
city_code,
|
|
district_code,
|
|
detailed_address,
|
|
is_default
|
|
} = req.body;
|
|
if (!recipient_name || !phone || !province_code || !city_code || !district_code || !detailed_address) {
|
|
return res.status(400).json({ message: '收件人姓名、电话、省市区和详细地址不能为空' });
|
|
}
|
|
|
|
// 检查地址是否存在且属于当前用户
|
|
const [existing] = await getDB().execute(
|
|
'SELECT id FROM user_addresses WHERE id = ? AND user_id = ? ',
|
|
[addressId, userId]
|
|
);
|
|
|
|
if (existing.length === 0) {
|
|
return res.status(404).json({ message: '收货地址不存在' });
|
|
}
|
|
|
|
// 如果设置为默认地址,先取消其他默认地址
|
|
if (is_default) {
|
|
await getDB().execute(
|
|
'UPDATE user_addresses SET is_default = false WHERE user_id = ? AND id != ? ',
|
|
[userId, addressId]
|
|
);
|
|
}
|
|
|
|
const [result] = await getDB().execute(
|
|
`UPDATE user_addresses SET
|
|
receiver_name = ?, receiver_phone = ?, province = ?, city = ?,
|
|
district = ?, detailed_address = ?, is_default = ?, updated_at = NOW()
|
|
WHERE id = ? AND user_id = ?`,
|
|
[
|
|
recipient_name, phone, province_code, city_code,
|
|
district_code, detailed_address, is_default,
|
|
addressId, userId
|
|
]
|
|
);
|
|
|
|
res.json({
|
|
success: true,
|
|
message: '收货地址更新成功'
|
|
});
|
|
} catch (error) {
|
|
console.error('更新收货地址错误:', error);
|
|
res.status(500).json({ message: '更新收货地址失败' });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /addresses/{id}:
|
|
* delete:
|
|
* summary: 删除收货地址
|
|
* tags: [Addresses]
|
|
* security:
|
|
* - bearerAuth: []
|
|
* parameters:
|
|
* - in: path
|
|
* name: id
|
|
* required: true
|
|
* schema:
|
|
* type: integer
|
|
* description: 地址ID
|
|
* responses:
|
|
* 200:
|
|
* description: 地址删除成功
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* success:
|
|
* type: boolean
|
|
* example: true
|
|
* message:
|
|
* type: string
|
|
* example: 收货地址删除成功
|
|
* 401:
|
|
* description: 未授权
|
|
* 404:
|
|
* description: 地址不存在
|
|
* 500:
|
|
* description: 服务器错误
|
|
*/
|
|
router.delete('/:id', auth, async (req, res) => {
|
|
try {
|
|
const addressId = req.params.id;
|
|
const userId = req.user.id;
|
|
|
|
const [result] = await getDB().execute(
|
|
'DELETE FROM user_addresses WHERE id = ? AND user_id = ?',
|
|
[addressId, userId]
|
|
);
|
|
|
|
if (result.affectedRows === 0) {
|
|
return res.status(404).json({ message: '收货地址不存在' });
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
message: '收货地址删除成功'
|
|
});
|
|
} catch (error) {
|
|
console.error('删除收货地址错误:', error);
|
|
res.status(500).json({ message: '删除收货地址失败' });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /addresses/{id}/default:
|
|
* put:
|
|
* summary: 设置默认地址
|
|
* tags: [Addresses]
|
|
* security:
|
|
* - bearerAuth: []
|
|
* parameters:
|
|
* - in: path
|
|
* name: id
|
|
* required: true
|
|
* schema:
|
|
* type: integer
|
|
* description: 地址ID
|
|
* responses:
|
|
* 200:
|
|
* description: 默认地址设置成功
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* success:
|
|
* type: boolean
|
|
* example: true
|
|
* message:
|
|
* type: string
|
|
* example: 默认地址设置成功
|
|
* 401:
|
|
* description: 未授权
|
|
* 404:
|
|
* description: 地址不存在
|
|
* 500:
|
|
* description: 服务器错误
|
|
*/
|
|
router.put('/:id/default', auth, async (req, res) => {
|
|
try {
|
|
const addressId = req.params.id;
|
|
const userId = req.user.id;
|
|
|
|
// 检查地址是否存在且属于当前用户
|
|
const [existing] = await getDB().execute(
|
|
'SELECT id FROM user_addresses WHERE id = ? AND user_id = ? AND deleted_at IS NULL',
|
|
[addressId, userId]
|
|
);
|
|
|
|
if (existing.length === 0) {
|
|
return res.status(404).json({ message: '收货地址不存在' });
|
|
}
|
|
|
|
// 取消其他默认地址
|
|
await getDB().execute(
|
|
'UPDATE user_addresses SET is_default = false WHERE user_id = ? AND deleted_at IS NULL',
|
|
[userId]
|
|
);
|
|
|
|
// 设置当前地址为默认
|
|
await getDB().execute(
|
|
'UPDATE user_addresses SET is_default = true WHERE id = ? AND user_id = ?',
|
|
[addressId, userId]
|
|
);
|
|
|
|
res.json({
|
|
success: true,
|
|
message: '默认地址设置成功'
|
|
});
|
|
} catch (error) {
|
|
console.error('设置默认地址错误:', error);
|
|
res.status(500).json({ message: '设置默认地址失败' });
|
|
}
|
|
});
|
|
|
|
module.exports = router; |