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 FROM user_addresses ua LEFT JOIN address_labels al ON ua.label_id = al.id WHERE ua.user_id = ? AND ua.deleted_at IS NULL 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, province_name, city_code, city_name, district_code, district_name, detailed_address, postal_code, label_id, 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 = ? AND deleted_at IS NULL', [userId] ); } const [result] = await getDB().execute( `INSERT INTO user_addresses ( user_id, recipient_name, phone, province_code, province_name, city_code, city_name, district_code, district_name, detailed_address, postal_code, label_id, is_default, created_at, updated_at ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())`, [ userId, recipient_name, phone, province_code, province_name, city_code, city_name, district_code, district_name, detailed_address, postal_code, label_id, 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, province_name, city_code, city_name, district_code, district_name, detailed_address, postal_code, label_id, is_default } = req.body; // 检查地址是否存在且属于当前用户 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: '收货地址不存在' }); } // 如果设置为默认地址,先取消其他默认地址 if (is_default) { await getDB().execute( 'UPDATE user_addresses SET is_default = false WHERE user_id = ? AND id != ? AND deleted_at IS NULL', [userId, addressId] ); } const [result] = await getDB().execute( `UPDATE user_addresses SET recipient_name = ?, phone = ?, province_code = ?, province_name = ?, city_code = ?, city_name = ?, district_code = ?, district_name = ?, detailed_address = ?, postal_code = ?, label_id = ?, is_default = ?, updated_at = NOW() WHERE id = ? AND user_id = ?`, [ recipient_name, phone, province_code, province_name, city_code, city_name, district_code, district_name, detailed_address, postal_code, label_id, 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( 'UPDATE user_addresses SET deleted_at = NOW() WHERE id = ? AND user_id = ? AND deleted_at IS NULL', [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;