feat(authorization): 新增行政区划代码↔中文名映射表,修复省市公司查询不到的问题

authorization_roles表的regionCode存储格式不一致(有中文名"北京"、"广东省"也有数字代码"110100"),
但查询时统一传入6位数字代码,导致findProvinceCompanyByRegion/findCityCompanyByRegion永远返回null。

新增 RegionCodeResolver 静态映射表(34个省+333个地级市),
将精确匹配 regionCode = provinceCode 改为多形式匹配 regionCode IN (所有可能形式)。
此修复同时影响正常认种和预种的省区域/市区域/省团队/市团队权益分配。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-03-01 01:41:48 -08:00
parent b9ddda2532
commit 530aeb2a6f
2 changed files with 508 additions and 6 deletions

View File

@ -0,0 +1,491 @@
/**
* +
*
* [2026-03-01]
* authorization_roles.regionCode
* - "北京""广东省""广州市"
* - / 6 "110000""440100"
*
*
* RegionCodeResolver.resolveProvince("440000") ["440000", "广东", "广东省"]
* RegionCodeResolver.resolveProvince("广东") ["440000", "广东", "广东省"]
* RegionCodeResolver.resolveCity("440100") ["440100", "广州", "广州市"]
* RegionCodeResolver.resolveCity("广州市") ["440100", "广州", "广州市"]
*
* repository 使 `WHERE regionCode IN (...)`
*
* GB/T 2260
*/
interface RegionEntry {
code: string;
aliases: string[];
}
// ==================== 省级34个 ====================
const PROVINCES: RegionEntry[] = [
{ code: '110000', aliases: ['北京', '北京市'] },
{ code: '120000', aliases: ['天津', '天津市'] },
{ code: '130000', aliases: ['河北', '河北省'] },
{ code: '140000', aliases: ['山西', '山西省'] },
{ code: '150000', aliases: ['内蒙古', '内蒙古自治区'] },
{ code: '210000', aliases: ['辽宁', '辽宁省'] },
{ code: '220000', aliases: ['吉林', '吉林省'] },
{ code: '230000', aliases: ['黑龙江', '黑龙江省'] },
{ code: '310000', aliases: ['上海', '上海市'] },
{ code: '320000', aliases: ['江苏', '江苏省'] },
{ code: '330000', aliases: ['浙江', '浙江省'] },
{ code: '340000', aliases: ['安徽', '安徽省'] },
{ code: '350000', aliases: ['福建', '福建省'] },
{ code: '360000', aliases: ['江西', '江西省'] },
{ code: '370000', aliases: ['山东', '山东省'] },
{ code: '410000', aliases: ['河南', '河南省'] },
{ code: '420000', aliases: ['湖北', '湖北省'] },
{ code: '430000', aliases: ['湖南', '湖南省'] },
{ code: '440000', aliases: ['广东', '广东省'] },
{ code: '450000', aliases: ['广西', '广西壮族自治区', '广西省'] },
{ code: '460000', aliases: ['海南', '海南省'] },
{ code: '500000', aliases: ['重庆', '重庆市'] },
{ code: '510000', aliases: ['四川', '四川省'] },
{ code: '520000', aliases: ['贵州', '贵州省'] },
{ code: '530000', aliases: ['云南', '云南省'] },
{ code: '540000', aliases: ['西藏', '西藏自治区'] },
{ code: '610000', aliases: ['陕西', '陕西省'] },
{ code: '620000', aliases: ['甘肃', '甘肃省'] },
{ code: '630000', aliases: ['青海', '青海省'] },
{ code: '640000', aliases: ['宁夏', '宁夏回族自治区'] },
{ code: '650000', aliases: ['新疆', '新疆维吾尔自治区'] },
{ code: '710000', aliases: ['台湾', '台湾省'] },
{ code: '810000', aliases: ['香港', '香港特别行政区'] },
{ code: '820000', aliases: ['澳门', '澳门特别行政区'] },
];
// ==================== 地级市(含自治州、地区、盟) ====================
const CITIES: RegionEntry[] = [
// === 北京 ===
{ code: '110100', aliases: ['北京', '北京市', '北京城区'] },
// === 天津 ===
{ code: '120100', aliases: ['天津', '天津市', '天津城区'] },
// === 河北 ===
{ code: '130100', aliases: ['石家庄', '石家庄市'] },
{ code: '130200', aliases: ['唐山', '唐山市'] },
{ code: '130300', aliases: ['秦皇岛', '秦皇岛市'] },
{ code: '130400', aliases: ['邯郸', '邯郸市'] },
{ code: '130500', aliases: ['邢台', '邢台市'] },
{ code: '130600', aliases: ['保定', '保定市'] },
{ code: '130700', aliases: ['张家口', '张家口市'] },
{ code: '130800', aliases: ['承德', '承德市'] },
{ code: '130900', aliases: ['沧州', '沧州市'] },
{ code: '131000', aliases: ['廊坊', '廊坊市'] },
{ code: '131100', aliases: ['衡水', '衡水市'] },
// === 山西 ===
{ code: '140100', aliases: ['太原', '太原市'] },
{ code: '140200', aliases: ['大同', '大同市'] },
{ code: '140300', aliases: ['阳泉', '阳泉市'] },
{ code: '140400', aliases: ['长治', '长治市'] },
{ code: '140500', aliases: ['晋城', '晋城市'] },
{ code: '140600', aliases: ['朔州', '朔州市'] },
{ code: '140700', aliases: ['晋中', '晋中市'] },
{ code: '140800', aliases: ['运城', '运城市'] },
{ code: '140900', aliases: ['忻州', '忻州市'] },
{ code: '141000', aliases: ['临汾', '临汾市'] },
{ code: '141100', aliases: ['吕梁', '吕梁市'] },
// === 内蒙古 ===
{ code: '150100', aliases: ['呼和浩特', '呼和浩特市'] },
{ code: '150200', aliases: ['包头', '包头市'] },
{ code: '150300', aliases: ['乌海', '乌海市'] },
{ code: '150400', aliases: ['赤峰', '赤峰市'] },
{ code: '150500', aliases: ['通辽', '通辽市'] },
{ code: '150600', aliases: ['鄂尔多斯', '鄂尔多斯市'] },
{ code: '150700', aliases: ['呼伦贝尔', '呼伦贝尔市'] },
{ code: '150800', aliases: ['巴彦淖尔', '巴彦淖尔市'] },
{ code: '150900', aliases: ['乌兰察布', '乌兰察布市'] },
{ code: '152200', aliases: ['兴安', '兴安盟'] },
{ code: '152500', aliases: ['锡林郭勒', '锡林郭勒盟'] },
{ code: '152900', aliases: ['阿拉善', '阿拉善盟'] },
// === 辽宁 ===
{ code: '210100', aliases: ['沈阳', '沈阳市'] },
{ code: '210200', aliases: ['大连', '大连市'] },
{ code: '210300', aliases: ['鞍山', '鞍山市'] },
{ code: '210400', aliases: ['抚顺', '抚顺市'] },
{ code: '210500', aliases: ['本溪', '本溪市'] },
{ code: '210600', aliases: ['丹东', '丹东市'] },
{ code: '210700', aliases: ['锦州', '锦州市'] },
{ code: '210800', aliases: ['营口', '营口市'] },
{ code: '210900', aliases: ['阜新', '阜新市'] },
{ code: '211000', aliases: ['辽阳', '辽阳市'] },
{ code: '211100', aliases: ['盘锦', '盘锦市'] },
{ code: '211200', aliases: ['铁岭', '铁岭市'] },
{ code: '211300', aliases: ['朝阳', '朝阳市'] },
{ code: '211400', aliases: ['葫芦岛', '葫芦岛市'] },
// === 吉林 ===
{ code: '220100', aliases: ['长春', '长春市'] },
{ code: '220200', aliases: ['吉林', '吉林市'] },
{ code: '220300', aliases: ['四平', '四平市'] },
{ code: '220400', aliases: ['辽源', '辽源市'] },
{ code: '220500', aliases: ['通化', '通化市'] },
{ code: '220600', aliases: ['白山', '白山市'] },
{ code: '220700', aliases: ['松原', '松原市'] },
{ code: '220800', aliases: ['白城', '白城市'] },
{ code: '222400', aliases: ['延边', '延边朝鲜族自治州', '延边州'] },
// === 黑龙江 ===
{ code: '230100', aliases: ['哈尔滨', '哈尔滨市'] },
{ code: '230200', aliases: ['齐齐哈尔', '齐齐哈尔市'] },
{ code: '230300', aliases: ['鸡西', '鸡西市'] },
{ code: '230400', aliases: ['鹤岗', '鹤岗市'] },
{ code: '230500', aliases: ['双鸭山', '双鸭山市'] },
{ code: '230600', aliases: ['大庆', '大庆市'] },
{ code: '230700', aliases: ['伊春', '伊春市'] },
{ code: '230800', aliases: ['佳木斯', '佳木斯市'] },
{ code: '230900', aliases: ['七台河', '七台河市'] },
{ code: '231000', aliases: ['牡丹江', '牡丹江市'] },
{ code: '231100', aliases: ['黑河', '黑河市'] },
{ code: '231200', aliases: ['绥化', '绥化市'] },
{ code: '232700', aliases: ['大兴安岭', '大兴安岭地区'] },
// === 上海 ===
{ code: '310100', aliases: ['上海', '上海市', '上海城区'] },
// === 江苏 ===
{ code: '320100', aliases: ['南京', '南京市'] },
{ code: '320200', aliases: ['无锡', '无锡市'] },
{ code: '320300', aliases: ['徐州', '徐州市'] },
{ code: '320400', aliases: ['常州', '常州市'] },
{ code: '320500', aliases: ['苏州', '苏州市'] },
{ code: '320600', aliases: ['南通', '南通市'] },
{ code: '320700', aliases: ['连云港', '连云港市'] },
{ code: '320800', aliases: ['淮安', '淮安市'] },
{ code: '320900', aliases: ['盐城', '盐城市'] },
{ code: '321000', aliases: ['扬州', '扬州市'] },
{ code: '321100', aliases: ['镇江', '镇江市'] },
{ code: '321200', aliases: ['泰州', '泰州市'] },
{ code: '321300', aliases: ['宿迁', '宿迁市'] },
// === 浙江 ===
{ code: '330100', aliases: ['杭州', '杭州市'] },
{ code: '330200', aliases: ['宁波', '宁波市'] },
{ code: '330300', aliases: ['温州', '温州市'] },
{ code: '330400', aliases: ['嘉兴', '嘉兴市'] },
{ code: '330500', aliases: ['湖州', '湖州市'] },
{ code: '330600', aliases: ['绍兴', '绍兴市'] },
{ code: '330700', aliases: ['金华', '金华市'] },
{ code: '330800', aliases: ['衢州', '衢州市'] },
{ code: '330900', aliases: ['舟山', '舟山市'] },
{ code: '331000', aliases: ['台州', '台州市'] },
{ code: '331100', aliases: ['丽水', '丽水市'] },
// === 安徽 ===
{ code: '340100', aliases: ['合肥', '合肥市'] },
{ code: '340200', aliases: ['芜湖', '芜湖市'] },
{ code: '340300', aliases: ['蚌埠', '蚌埠市'] },
{ code: '340400', aliases: ['淮南', '淮南市'] },
{ code: '340500', aliases: ['马鞍山', '马鞍山市'] },
{ code: '340600', aliases: ['淮北', '淮北市'] },
{ code: '340700', aliases: ['铜陵', '铜陵市'] },
{ code: '340800', aliases: ['安庆', '安庆市'] },
{ code: '341000', aliases: ['黄山', '黄山市'] },
{ code: '341100', aliases: ['滁州', '滁州市'] },
{ code: '341200', aliases: ['阜阳', '阜阳市'] },
{ code: '341300', aliases: ['宿州', '宿州市'] },
{ code: '341500', aliases: ['六安', '六安市'] },
{ code: '341600', aliases: ['亳州', '亳州市'] },
{ code: '341700', aliases: ['池州', '池州市'] },
{ code: '341800', aliases: ['宣城', '宣城市'] },
// === 福建 ===
{ code: '350100', aliases: ['福州', '福州市'] },
{ code: '350200', aliases: ['厦门', '厦门市'] },
{ code: '350300', aliases: ['莆田', '莆田市'] },
{ code: '350400', aliases: ['三明', '三明市'] },
{ code: '350500', aliases: ['泉州', '泉州市'] },
{ code: '350600', aliases: ['漳州', '漳州市'] },
{ code: '350700', aliases: ['南平', '南平市'] },
{ code: '350800', aliases: ['龙岩', '龙岩市'] },
{ code: '350900', aliases: ['宁德', '宁德市'] },
// === 江西 ===
{ code: '360100', aliases: ['南昌', '南昌市'] },
{ code: '360200', aliases: ['景德镇', '景德镇市'] },
{ code: '360300', aliases: ['萍乡', '萍乡市'] },
{ code: '360400', aliases: ['九江', '九江市'] },
{ code: '360500', aliases: ['新余', '新余市'] },
{ code: '360600', aliases: ['鹰潭', '鹰潭市'] },
{ code: '360700', aliases: ['赣州', '赣州市'] },
{ code: '360800', aliases: ['吉安', '吉安市'] },
{ code: '360900', aliases: ['宜春', '宜春市'] },
{ code: '361000', aliases: ['抚州', '抚州市'] },
{ code: '361100', aliases: ['上饶', '上饶市'] },
// === 山东 ===
{ code: '370100', aliases: ['济南', '济南市'] },
{ code: '370200', aliases: ['青岛', '青岛市'] },
{ code: '370300', aliases: ['淄博', '淄博市'] },
{ code: '370400', aliases: ['枣庄', '枣庄市'] },
{ code: '370500', aliases: ['东营', '东营市'] },
{ code: '370600', aliases: ['烟台', '烟台市'] },
{ code: '370700', aliases: ['潍坊', '潍坊市'] },
{ code: '370800', aliases: ['济宁', '济宁市'] },
{ code: '370900', aliases: ['泰安', '泰安市'] },
{ code: '371000', aliases: ['威海', '威海市'] },
{ code: '371100', aliases: ['日照', '日照市'] },
{ code: '371300', aliases: ['临沂', '临沂市'] },
{ code: '371400', aliases: ['德州', '德州市'] },
{ code: '371500', aliases: ['聊城', '聊城市'] },
{ code: '371600', aliases: ['滨州', '滨州市'] },
{ code: '371700', aliases: ['菏泽', '菏泽市'] },
// === 河南 ===
{ code: '410100', aliases: ['郑州', '郑州市'] },
{ code: '410200', aliases: ['开封', '开封市'] },
{ code: '410300', aliases: ['洛阳', '洛阳市'] },
{ code: '410400', aliases: ['平顶山', '平顶山市'] },
{ code: '410500', aliases: ['安阳', '安阳市'] },
{ code: '410600', aliases: ['鹤壁', '鹤壁市'] },
{ code: '410700', aliases: ['新乡', '新乡市'] },
{ code: '410800', aliases: ['焦作', '焦作市'] },
{ code: '410900', aliases: ['濮阳', '濮阳市'] },
{ code: '411000', aliases: ['许昌', '许昌市'] },
{ code: '411100', aliases: ['漯河', '漯河市'] },
{ code: '411200', aliases: ['三门峡', '三门峡市'] },
{ code: '411300', aliases: ['南阳', '南阳市'] },
{ code: '411400', aliases: ['商丘', '商丘市'] },
{ code: '411500', aliases: ['信阳', '信阳市'] },
{ code: '411600', aliases: ['周口', '周口市'] },
{ code: '411700', aliases: ['驻马店', '驻马店市'] },
{ code: '419001', aliases: ['济源', '济源市'] },
// === 湖北 ===
{ code: '420100', aliases: ['武汉', '武汉市'] },
{ code: '420200', aliases: ['黄石', '黄石市'] },
{ code: '420300', aliases: ['十堰', '十堰市'] },
{ code: '420500', aliases: ['宜昌', '宜昌市'] },
{ code: '420600', aliases: ['襄阳', '襄阳市'] },
{ code: '420700', aliases: ['鄂州', '鄂州市'] },
{ code: '420800', aliases: ['荆门', '荆门市'] },
{ code: '420900', aliases: ['孝感', '孝感市'] },
{ code: '421000', aliases: ['荆州', '荆州市'] },
{ code: '421100', aliases: ['黄冈', '黄冈市'] },
{ code: '421200', aliases: ['咸宁', '咸宁市'] },
{ code: '421300', aliases: ['随州', '随州市'] },
{ code: '422800', aliases: ['恩施', '恩施土家族苗族自治州', '恩施州'] },
{ code: '429004', aliases: ['仙桃', '仙桃市'] },
{ code: '429005', aliases: ['潜江', '潜江市'] },
{ code: '429006', aliases: ['天门', '天门市'] },
{ code: '429021', aliases: ['神农架', '神农架林区'] },
// === 湖南 ===
{ code: '430100', aliases: ['长沙', '长沙市'] },
{ code: '430200', aliases: ['株洲', '株洲市'] },
{ code: '430300', aliases: ['湘潭', '湘潭市'] },
{ code: '430400', aliases: ['衡阳', '衡阳市'] },
{ code: '430500', aliases: ['邵阳', '邵阳市'] },
{ code: '430600', aliases: ['岳阳', '岳阳市'] },
{ code: '430700', aliases: ['常德', '常德市'] },
{ code: '430800', aliases: ['张家界', '张家界市'] },
{ code: '430900', aliases: ['益阳', '益阳市'] },
{ code: '431000', aliases: ['郴州', '郴州市'] },
{ code: '431100', aliases: ['永州', '永州市'] },
{ code: '431200', aliases: ['怀化', '怀化市'] },
{ code: '431300', aliases: ['娄底', '娄底市'] },
{ code: '433100', aliases: ['湘西', '湘西土家族苗族自治州', '湘西州'] },
// === 广东 ===
{ code: '440100', aliases: ['广州', '广州市'] },
{ code: '440200', aliases: ['韶关', '韶关市'] },
{ code: '440300', aliases: ['深圳', '深圳市'] },
{ code: '440400', aliases: ['珠海', '珠海市'] },
{ code: '440500', aliases: ['汕头', '汕头市'] },
{ code: '440600', aliases: ['佛山', '佛山市'] },
{ code: '440700', aliases: ['江门', '江门市'] },
{ code: '440800', aliases: ['湛江', '湛江市'] },
{ code: '440900', aliases: ['茂名', '茂名市'] },
{ code: '441200', aliases: ['肇庆', '肇庆市'] },
{ code: '441300', aliases: ['惠州', '惠州市'] },
{ code: '441400', aliases: ['梅州', '梅州市'] },
{ code: '441500', aliases: ['汕尾', '汕尾市'] },
{ code: '441600', aliases: ['河源', '河源市'] },
{ code: '441700', aliases: ['阳江', '阳江市'] },
{ code: '441800', aliases: ['清远', '清远市'] },
{ code: '441900', aliases: ['东莞', '东莞市'] },
{ code: '442000', aliases: ['中山', '中山市'] },
{ code: '445100', aliases: ['潮州', '潮州市'] },
{ code: '445200', aliases: ['揭阳', '揭阳市'] },
{ code: '445300', aliases: ['云浮', '云浮市'] },
// === 广西 ===
{ code: '450100', aliases: ['南宁', '南宁市'] },
{ code: '450200', aliases: ['柳州', '柳州市'] },
{ code: '450300', aliases: ['桂林', '桂林市'] },
{ code: '450400', aliases: ['梧州', '梧州市'] },
{ code: '450500', aliases: ['北海', '北海市'] },
{ code: '450600', aliases: ['防城港', '防城港市'] },
{ code: '450700', aliases: ['钦州', '钦州市'] },
{ code: '450800', aliases: ['贵港', '贵港市'] },
{ code: '450900', aliases: ['玉林', '玉林市'] },
{ code: '451000', aliases: ['百色', '百色市'] },
{ code: '451100', aliases: ['贺州', '贺州市'] },
{ code: '451200', aliases: ['河池', '河池市'] },
{ code: '451300', aliases: ['来宾', '来宾市'] },
{ code: '451400', aliases: ['崇左', '崇左市'] },
// === 海南 ===
{ code: '460100', aliases: ['海口', '海口市'] },
{ code: '460200', aliases: ['三亚', '三亚市'] },
{ code: '460300', aliases: ['三沙', '三沙市'] },
{ code: '460400', aliases: ['儋州', '儋州市'] },
// === 重庆 ===
{ code: '500100', aliases: ['重庆', '重庆市', '重庆城区'] },
// === 四川 ===
{ code: '510100', aliases: ['成都', '成都市'] },
{ code: '510300', aliases: ['自贡', '自贡市'] },
{ code: '510400', aliases: ['攀枝花', '攀枝花市'] },
{ code: '510500', aliases: ['泸州', '泸州市'] },
{ code: '510600', aliases: ['德阳', '德阳市'] },
{ code: '510700', aliases: ['绵阳', '绵阳市'] },
{ code: '510800', aliases: ['广元', '广元市'] },
{ code: '510900', aliases: ['遂宁', '遂宁市'] },
{ code: '511000', aliases: ['内江', '内江市'] },
{ code: '511100', aliases: ['乐山', '乐山市'] },
{ code: '511300', aliases: ['南充', '南充市'] },
{ code: '511400', aliases: ['眉山', '眉山市'] },
{ code: '511500', aliases: ['宜宾', '宜宾市'] },
{ code: '511600', aliases: ['广安', '广安市'] },
{ code: '511700', aliases: ['达州', '达州市'] },
{ code: '511800', aliases: ['雅安', '雅安市'] },
{ code: '511900', aliases: ['巴中', '巴中市'] },
{ code: '512000', aliases: ['资阳', '资阳市'] },
{ code: '513200', aliases: ['阿坝', '阿坝藏族羌族自治州', '阿坝州'] },
{ code: '513300', aliases: ['甘孜', '甘孜藏族自治州', '甘孜州'] },
{ code: '513400', aliases: ['凉山', '凉山彝族自治州', '凉山州'] },
// === 贵州 ===
{ code: '520100', aliases: ['贵阳', '贵阳市'] },
{ code: '520200', aliases: ['六盘水', '六盘水市'] },
{ code: '520300', aliases: ['遵义', '遵义市'] },
{ code: '520400', aliases: ['安顺', '安顺市'] },
{ code: '520500', aliases: ['毕节', '毕节市'] },
{ code: '520600', aliases: ['铜仁', '铜仁市'] },
{ code: '522300', aliases: ['黔西南', '黔西南布依族苗族自治州', '黔西南州'] },
{ code: '522600', aliases: ['黔东南', '黔东南苗族侗族自治州', '黔东南州'] },
{ code: '522700', aliases: ['黔南', '黔南布依族苗族自治州', '黔南州'] },
// === 云南 ===
{ code: '530100', aliases: ['昆明', '昆明市'] },
{ code: '530300', aliases: ['曲靖', '曲靖市'] },
{ code: '530400', aliases: ['玉溪', '玉溪市'] },
{ code: '530500', aliases: ['保山', '保山市'] },
{ code: '530600', aliases: ['昭通', '昭通市'] },
{ code: '530700', aliases: ['丽江', '丽江市'] },
{ code: '530800', aliases: ['普洱', '普洱市'] },
{ code: '530900', aliases: ['临沧', '临沧市'] },
{ code: '532300', aliases: ['楚雄', '楚雄彝族自治州', '楚雄州'] },
{ code: '532500', aliases: ['红河', '红河哈尼族彝族自治州', '红河州'] },
{ code: '532600', aliases: ['文山', '文山壮族苗族自治州', '文山州'] },
{ code: '532800', aliases: ['西双版纳', '西双版纳傣族自治州', '西双版纳州'] },
{ code: '532900', aliases: ['大理', '大理白族自治州', '大理州'] },
{ code: '533100', aliases: ['德宏', '德宏傣族景颇族自治州', '德宏州'] },
{ code: '533300', aliases: ['怒江', '怒江傈僳族自治州', '怒江州'] },
{ code: '533400', aliases: ['迪庆', '迪庆藏族自治州', '迪庆州'] },
// === 西藏 ===
{ code: '540100', aliases: ['拉萨', '拉萨市'] },
{ code: '540200', aliases: ['日喀则', '日喀则市'] },
{ code: '540300', aliases: ['昌都', '昌都市'] },
{ code: '540400', aliases: ['林芝', '林芝市'] },
{ code: '540500', aliases: ['山南', '山南市'] },
{ code: '540600', aliases: ['那曲', '那曲市'] },
{ code: '542500', aliases: ['阿里', '阿里地区'] },
// === 陕西 ===
{ code: '610100', aliases: ['西安', '西安市'] },
{ code: '610200', aliases: ['铜川', '铜川市'] },
{ code: '610300', aliases: ['宝鸡', '宝鸡市'] },
{ code: '610400', aliases: ['咸阳', '咸阳市'] },
{ code: '610500', aliases: ['渭南', '渭南市'] },
{ code: '610600', aliases: ['延安', '延安市'] },
{ code: '610700', aliases: ['汉中', '汉中市'] },
{ code: '610800', aliases: ['榆林', '榆林市'] },
{ code: '610900', aliases: ['安康', '安康市'] },
{ code: '611000', aliases: ['商洛', '商洛市'] },
// === 甘肃 ===
{ code: '620100', aliases: ['兰州', '兰州市'] },
{ code: '620200', aliases: ['嘉峪关', '嘉峪关市'] },
{ code: '620300', aliases: ['金昌', '金昌市'] },
{ code: '620400', aliases: ['白银', '白银市'] },
{ code: '620500', aliases: ['天水', '天水市'] },
{ code: '620600', aliases: ['武威', '武威市'] },
{ code: '620700', aliases: ['张掖', '张掖市'] },
{ code: '620800', aliases: ['平凉', '平凉市'] },
{ code: '620900', aliases: ['酒泉', '酒泉市'] },
{ code: '621000', aliases: ['庆阳', '庆阳市'] },
{ code: '621100', aliases: ['定西', '定西市'] },
{ code: '621200', aliases: ['陇南', '陇南市'] },
{ code: '622900', aliases: ['临夏', '临夏回族自治州', '临夏州'] },
{ code: '623000', aliases: ['甘南', '甘南藏族自治州', '甘南州'] },
// === 青海 ===
{ code: '630100', aliases: ['西宁', '西宁市'] },
{ code: '630200', aliases: ['海东', '海东市'] },
{ code: '632200', aliases: ['海北', '海北藏族自治州', '海北州'] },
{ code: '632300', aliases: ['黄南', '黄南藏族自治州', '黄南州'] },
{ code: '632500', aliases: ['海南藏族自治州', '海南州'] },
{ code: '632600', aliases: ['果洛', '果洛藏族自治州', '果洛州'] },
{ code: '632700', aliases: ['玉树', '玉树藏族自治州', '玉树州'] },
{ code: '632800', aliases: ['海西', '海西蒙古族藏族自治州', '海西州'] },
// === 宁夏 ===
{ code: '640100', aliases: ['银川', '银川市'] },
{ code: '640200', aliases: ['石嘴山', '石嘴山市'] },
{ code: '640300', aliases: ['吴忠', '吴忠市'] },
{ code: '640400', aliases: ['固原', '固原市'] },
{ code: '640500', aliases: ['中卫', '中卫市'] },
// === 新疆 ===
{ code: '650100', aliases: ['乌鲁木齐', '乌鲁木齐市'] },
{ code: '650200', aliases: ['克拉玛依', '克拉玛依市'] },
{ code: '650400', aliases: ['吐鲁番', '吐鲁番市'] },
{ code: '650500', aliases: ['哈密', '哈密市'] },
{ code: '652300', aliases: ['昌吉', '昌吉回族自治州', '昌吉州'] },
{ code: '652700', aliases: ['博尔塔拉', '博尔塔拉蒙古自治州', '博州'] },
{ code: '652800', aliases: ['巴音郭楞', '巴音郭楞蒙古自治州', '巴州'] },
{ code: '652900', aliases: ['阿克苏', '阿克苏地区'] },
{ code: '653000', aliases: ['克孜勒苏', '克孜勒苏柯尔克孜自治州', '克州'] },
{ code: '653100', aliases: ['喀什', '喀什地区'] },
{ code: '653200', aliases: ['和田', '和田地区'] },
{ code: '654000', aliases: ['伊犁', '伊犁哈萨克自治州', '伊犁州'] },
{ code: '654200', aliases: ['塔城', '塔城地区'] },
{ code: '654300', aliases: ['阿勒泰', '阿勒泰地区'] },
// === 香港 ===
{ code: '810100', aliases: ['香港', '香港特别行政区'] },
// === 澳门 ===
{ code: '820100', aliases: ['澳门', '澳门特别行政区'] },
];
/**
*
* / /
*/
export class RegionCodeResolver {
// 省级:任意形式 → 所有形式(含代码)
private static provinceMap: Map<string, string[]>;
// 市级:任意形式 → 所有形式(含代码)
private static cityMap: Map<string, string[]>;
private static buildMap(entries: RegionEntry[]): Map<string, string[]> {
const map = new Map<string, string[]>();
for (const entry of entries) {
const allForms = [entry.code, ...entry.aliases];
for (const form of allForms) {
map.set(form, allForms);
}
}
return map;
}
private static ensureInit(): void {
if (!this.provinceMap) {
this.provinceMap = this.buildMap(PROVINCES);
this.cityMap = this.buildMap(CITIES);
}
}
/**
*
* @param input "440000" / "广东" / "广东省"
* @returns ["440000", "广东", "广东省"] [input]
*/
static resolveProvince(input: string): string[] {
this.ensureInit();
return this.provinceMap.get(input) || [input];
}
/**
*
* @param input "440100" / "广州" / "广州市"
* @returns ["440100", "广州", "广州市"] [input]
*/
static resolveCity(input: string): string[] {
this.ensureInit();
return this.cityMap.get(input) || [input];
}
}

View File

@ -13,6 +13,7 @@ import {
AssessmentConfig, AssessmentConfig,
} from '@/domain/value-objects' } from '@/domain/value-objects'
import { RoleType, AuthorizationStatus, MonthlyTargetType } from '@/domain/enums' import { RoleType, AuthorizationStatus, MonthlyTargetType } from '@/domain/enums'
import { RegionCodeResolver } from '@/domain/region-code-resolver'
@Injectable() @Injectable()
export class AuthorizationRoleRepositoryImpl implements IAuthorizationRoleRepository { export class AuthorizationRoleRepositoryImpl implements IAuthorizationRoleRepository {
@ -228,11 +229,12 @@ export class AuthorizationRoleRepositoryImpl implements IAuthorizationRoleReposi
return [] return []
} }
const allProvinceForms = RegionCodeResolver.resolveProvince(provinceCode)
const records = await this.prisma.authorizationRole.findMany({ const records = await this.prisma.authorizationRole.findMany({
where: { where: {
accountSequence: { in: accountSequences }, accountSequence: { in: accountSequences },
roleType: RoleType.PROVINCE_COMPANY, roleType: RoleType.PROVINCE_COMPANY,
regionCode: provinceCode, regionCode: { in: allProvinceForms },
status: AuthorizationStatus.AUTHORIZED, status: AuthorizationStatus.AUTHORIZED,
benefitActive: true, benefitActive: true,
...this.notDeleted, ...this.notDeleted,
@ -250,11 +252,12 @@ export class AuthorizationRoleRepositoryImpl implements IAuthorizationRoleReposi
return [] return []
} }
const allCityForms = RegionCodeResolver.resolveCity(cityCode)
const records = await this.prisma.authorizationRole.findMany({ const records = await this.prisma.authorizationRole.findMany({
where: { where: {
accountSequence: { in: accountSequences }, accountSequence: { in: accountSequences },
roleType: RoleType.CITY_COMPANY, roleType: RoleType.CITY_COMPANY,
regionCode: cityCode, regionCode: { in: allCityForms },
status: AuthorizationStatus.AUTHORIZED, status: AuthorizationStatus.AUTHORIZED,
benefitActive: true, benefitActive: true,
...this.notDeleted, ...this.notDeleted,
@ -292,11 +295,12 @@ export class AuthorizationRoleRepositoryImpl implements IAuthorizationRoleReposi
return [] return []
} }
const allProvinceForms = RegionCodeResolver.resolveProvince(provinceCode)
const records = await this.prisma.authorizationRole.findMany({ const records = await this.prisma.authorizationRole.findMany({
where: { where: {
accountSequence: { in: accountSequences }, accountSequence: { in: accountSequences },
roleType: RoleType.AUTH_PROVINCE_COMPANY, roleType: RoleType.AUTH_PROVINCE_COMPANY,
regionCode: provinceCode, regionCode: { in: allProvinceForms },
status: AuthorizationStatus.AUTHORIZED, status: AuthorizationStatus.AUTHORIZED,
...this.notDeleted, ...this.notDeleted,
// 注意:不过滤 benefitActive用于计算省团队权益分配 // 注意:不过滤 benefitActive用于计算省团队权益分配
@ -314,11 +318,12 @@ export class AuthorizationRoleRepositoryImpl implements IAuthorizationRoleReposi
return [] return []
} }
const allCityForms = RegionCodeResolver.resolveCity(cityCode)
const records = await this.prisma.authorizationRole.findMany({ const records = await this.prisma.authorizationRole.findMany({
where: { where: {
accountSequence: { in: accountSequences }, accountSequence: { in: accountSequences },
roleType: RoleType.AUTH_CITY_COMPANY, roleType: RoleType.AUTH_CITY_COMPANY,
regionCode: cityCode, regionCode: { in: allCityForms },
status: AuthorizationStatus.AUTHORIZED, status: AuthorizationStatus.AUTHORIZED,
...this.notDeleted, ...this.notDeleted,
// 注意:不过滤 benefitActive用于计算市团队权益分配 // 注意:不过滤 benefitActive用于计算市团队权益分配
@ -371,10 +376,14 @@ export class AuthorizationRoleRepositoryImpl implements IAuthorizationRoleReposi
} }
async findProvinceCompanyByRegion(provinceCode: string): Promise<AuthorizationRole | null> { async findProvinceCompanyByRegion(provinceCode: string): Promise<AuthorizationRole | null> {
// [2026-03-01] 使用 RegionCodeResolver 多形式匹配
// 传入的可能是数字代码("440000")或中文名("广东"/"广东省")
// 数据库 regionCode 存储格式不统一,需要同时匹配所有可能形式。
const allForms = RegionCodeResolver.resolveProvince(provinceCode)
const record = await this.prisma.authorizationRole.findFirst({ const record = await this.prisma.authorizationRole.findFirst({
where: { where: {
roleType: RoleType.PROVINCE_COMPANY, roleType: RoleType.PROVINCE_COMPANY,
regionCode: provinceCode, regionCode: { in: allForms },
status: AuthorizationStatus.AUTHORIZED, status: AuthorizationStatus.AUTHORIZED,
...this.notDeleted, ...this.notDeleted,
}, },
@ -383,10 +392,12 @@ export class AuthorizationRoleRepositoryImpl implements IAuthorizationRoleReposi
} }
async findCityCompanyByRegion(cityCode: string): Promise<AuthorizationRole | null> { async findCityCompanyByRegion(cityCode: string): Promise<AuthorizationRole | null> {
// [2026-03-01] 使用 RegionCodeResolver 多形式匹配(与省级同理)
const allForms = RegionCodeResolver.resolveCity(cityCode)
const record = await this.prisma.authorizationRole.findFirst({ const record = await this.prisma.authorizationRole.findFirst({
where: { where: {
roleType: RoleType.CITY_COMPANY, roleType: RoleType.CITY_COMPANY,
regionCode: cityCode, regionCode: { in: allForms },
status: AuthorizationStatus.AUTHORIZED, status: AuthorizationStatus.AUTHORIZED,
...this.notDeleted, ...this.notDeleted,
}, },