Files
jurong_circle_black/routes/regions.js

436 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const express = require('express')
const router = express.Router()
const {getDB} = require('../database')
/**
* @swagger
* tags:
* name: Regions
* description: 地区数据API
*/
/**
* @swagger
* components:
* schemas:
* Region:
* type: object
* properties:
* code:
* type: string
* description: 地区编码
* name:
* type: string
* description: 地区名称
* ZhejiangRegion:
* type: object
* properties:
* id:
* type: integer
* description: 地区ID
* city_name:
* type: string
* description: 城市名称
* district_name:
* type: string
* description: 区县名称
* region_code:
* type: string
* description: 地区编码
* is_available:
* type: integer
* description: 是否可用(1:可用 0:不可用)
*/
/**
* @swagger
* /regions/zhejiang:
* get:
* summary: 获取浙江省所有地区数据
* tags: [Regions]
* responses:
* 200:
* description: 成功获取浙江省地区数据
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* data:
* type: array
* items:
* $ref: '#/components/schemas/ZhejiangRegion'
* message:
* type: string
* example: 获取地区数据成功
* 500:
* description: 服务器错误
*/
router.get('/zhejiang', async (req, res) => {
try {
const query = `
SELECT id, city_name, district_name, region_code, is_available
FROM zhejiang_regions
WHERE is_available = 1
ORDER BY city_name, district_name
`
const [rows] = await getDB().execute(query)
res.json({
success: true,
data: rows,
message: '获取地区数据成功'
})
} catch (error) {
console.error('获取浙江省地区数据失败:', error)
res.status(500).json({
success: false,
message: '获取地区数据失败'
})
}
})
/**
* @swagger
* /regions/provinces:
* get:
* summary: 获取所有省份
* tags: [Regions]
* responses:
* 200:
* description: 成功获取省份列表
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* data:
* type: array
* items:
* $ref: '#/components/schemas/Region'
* 500:
* description: 服务器错误
*/
router.get('/provinces', async (req, res) => {
try {
// 按level分组数据
const regionsByLevel = {
1: [], // 省份
2: [], // 城市
3: [] // 区县
};
if (!global.provinces) {
// 一次性获取所有区域数据(省、市、区县)
const [allRegions] = await getDB().execute(
`SELECT code, name as label, level, parent_code
FROM china_regions
WHERE level <= 3
ORDER BY level, code`
);
// 创建code到region的映射便于快速查找
const regionMap = {};
// 分组并建立映射
allRegions.forEach(region => {
region.children = []; // 初始化children数组
regionsByLevel[region.level].push(region);
regionMap[region.code] = region;
});
// 构建层级关系:先处理区县到城市的关系
regionsByLevel[3].forEach(district => {
const parentCity = regionMap[district.parent_code];
if (parentCity) {
parentCity.children.push(district);
}
});
// 再处理城市到省份的关系
regionsByLevel[2].forEach(city => {
const parentProvince = regionMap[city.parent_code];
if (parentProvince) {
parentProvince.children.push(city);
}
});
global.provinces = regionsByLevel[1];
}else {
// console.log('1111')
regionsByLevel[1] = global.provinces;
}
// 返回省份数据(已包含完整的层级结构)
res.json({
success: true,
data: regionsByLevel[1]
});
} catch (error) {
console.error('获取省份列表错误:', error);
res.status(500).json({message: '获取省份列表失败'});
}
});
/**
* @swagger
* /regions/cities/{provinceCode}:
* get:
* summary: 根据省份代码获取城市列表
* tags: [Regions]
* parameters:
* - in: path
* name: provinceCode
* required: true
* schema:
* type: string
* description: 省份代码
* responses:
* 200:
* description: 成功获取城市列表
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* data:
* type: array
* items:
* $ref: '#/components/schemas/Region'
* 500:
* description: 服务器错误
*/
router.get('/cities/:provinceCode', async (req, res) => {
try {
const provinceCode = req.params.provinceCode;
const [cities] = await getDB().execute(
`SELECT code, name
FROM china_regions
WHERE level = 2
AND parent_code = ?
ORDER BY code`,
[provinceCode]
);
res.json({
success: true,
data: cities
});
} catch (error) {
console.error('获取城市列表错误:', error);
res.status(500).json({message: '获取城市列表失败'});
}
});
/**
* @swagger
* /regions/districts/{cityCode}:
* get:
* summary: 根据城市代码获取区县列表
* tags: [Regions]
* parameters:
* - in: path
* name: cityCode
* required: true
* schema:
* type: string
* description: 城市代码
* responses:
* 200:
* description: 成功获取区县列表
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* data:
* type: array
* items:
* $ref: '#/components/schemas/Region'
* 500:
* description: 服务器错误
*/
router.get('/districts/:cityCode', async (req, res) => {
try {
const cityCode = req.params.cityCode;
const [districts] = await getDB().execute(
`SELECT code, name
FROM china_regions
WHERE level = 3
AND parent_code = ?
ORDER BY code`,
[cityCode]
);
res.json({
success: true,
data: districts
});
} catch (error) {
console.error('获取区县列表错误:', error);
res.status(500).json({message: '获取区县列表失败'});
}
});
/**
* @swagger
* /regions/path/{regionCode}:
* get:
* summary: 根据区域代码获取完整路径(省-市-区)
* tags: [Regions]
* parameters:
* - in: path
* name: regionCode
* required: true
* schema:
* type: string
* description: 区域代码
* responses:
* 200:
* description: 成功获取区域完整路径
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* data:
* type: object
* properties:
* province:
* $ref: '#/components/schemas/Region'
* city:
* $ref: '#/components/schemas/Region'
* district:
* $ref: '#/components/schemas/Region'
* 404:
* description: 区域不存在
* 500:
* description: 服务器错误
*/
router.get('/path/:regionCode', async (req, res) => {
try {
const regionCode = req.params.regionCode;
// 获取当前区域信息
const [currentRegion] = await getDB().execute(
'SELECT code, name, level, parent_code FROM china_regions WHERE code = ?',
[regionCode]
);
if (currentRegion.length === 0) {
return res.status(404).json({message: '区域不存在'});
}
const region = currentRegion[0];
const path = [region];
// 递归获取父级区域
let parentCode = region.parent_code;
while (parentCode) {
const [parentRegion] = await getDB().execute(
'SELECT code, name, level, parent_code FROM china_regions WHERE code = ? AND status = "active"',
[parentCode]
);
if (parentRegion.length > 0) {
path.unshift(parentRegion[0]);
parentCode = parentRegion[0].parent_code;
} else {
break;
}
}
res.json({
success: true,
data: {
path,
province: path.find(r => r.level === 1) || null,
city: path.find(r => r.level === 2) || null,
district: path.find(r => r.level === 3) || null
}
});
} catch (error) {
console.error('获取区域路径错误:', error);
res.status(500).json({message: '获取区域路径失败'});
}
});
// 搜索区域(支持模糊搜索)
router.get('/search', async (req, res) => {
try {
const {keyword, level} = req.query;
if (!keyword || keyword.trim() === '') {
return res.status(400).json({message: '搜索关键词不能为空'});
}
let sql = `SELECT code, name, level, parent_code
FROM china_regions
WHERE name LIKE ?`;
const params = [`%${keyword.trim()}%`];
if (level) {
sql += ' AND level = ?';
params.push(parseInt(level));
}
sql += ' ORDER BY level, code LIMIT 50';
const [regions] = await getDB().execute(sql, params);
// 为每个搜索结果获取完整路径
const results = [];
for (const region of regions) {
const path = [region];
let parentCode = region.parent_code;
while (parentCode) {
const [parentRegion] = await getDB().execute(
'SELECT code, name, level, parent_code FROM china_regions WHERE code = ? AND status = "active"',
[parentCode]
);
if (parentRegion.length > 0) {
path.unshift(parentRegion[0]);
parentCode = parentRegion[0].parent_code;
} else {
break;
}
}
results.push({
...region,
path,
fullName: path.map(r => r.name).join(' - ')
});
}
res.json({
success: true,
data: results
});
} catch (error) {
console.error('搜索区域错误:', error);
res.status(500).json({message: '搜索区域失败'});
}
});
module.exports = router