Commit 7b98a3f3f390304c3c9e94e9c7e27c48994560fb

Authored by xingyu
2 parents 683b49a8 427d031b

Merge remote-tracking branch 'origin/master' into feature/springdoc

# Conflicts:
#	README.md
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageRespVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuRespVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/property/AppProductPropertyValueDetailRespVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderPageReqVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderItemRespVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderRespVO.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayNotifyOrderReqVO.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayRefundOrderReqVO.java
#	yudao-server/pom.xml
#	yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/app/AppShopOrderController.java
Showing 466 changed files with 17546 additions and 4307 deletions

Too many changes.

To preserve performance only 100 of 466 files are displayed.

README.md
1   -**严肃声明:现在、未来都不会有商业版本,所有功能全部开源!**
2   -
3   -**拒绝虚假开源,售卖商业版,程序员不骗程序员!!**
  1 +**严肃声明:现在、未来都不会有商业版本,所有代码全部开源!**
4 2  
5 3 **「我喜欢写代码,乐此不疲」**
6 4 **「我喜欢做开源,以此为乐」**
... ... @@ -27,7 +25,7 @@
27 25  
28 26 * 管理后台的 Vue3 版本采用 [vue-element-plus-admin](https://gitee.com/kailong110120130/vue-element-plus-admin) ,Vue2 版本采用 [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
29 27 * 管理后台的移动端采用 [uni-app](https://github.com/dcloudio/uni-app) 方案,一份代码多终端适配,同时支持 APP、小程序、H5!
30   -* 后端采用 Spring Boot、MySQL + MyBatis Plus、Redis + Redisson
  28 +* 后端采用 Spring Boot 多模块架构、MySQL + MyBatis Plus、Redis + Redisson
31 29 * 数据库可使用 MySQL、Oracle、PostgreSQL、SQL Server、MariaDB、国产达梦 DM、TiDB 等
32 30 * 权限认证使用 Spring Security & Token & Redis,支持多终端、多种用户的认证系统,支持 SSO 单点登录
33 31 * 支持加载动态权限菜单,按钮级别权限控制,本地缓存提升性能
... ... @@ -38,12 +36,12 @@
38 36 * 集成阿里云、腾讯云等短信渠道,集成 MinIO、阿里云、腾讯云、七牛云等云存储服务
39 37 * 集成报表设计器,支持数据报表、图形报表、打印设计等
40 38  
41   -| 项目名 | 说明 | 传送门 |
42   -|--------------------|------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
43   -| `ruoyi-vue-pro` | Spring Boot 多模块 | **[Gitee](https://gitee.com/zhijiantianya/ruoyi-vue-pro)**     [Github](https://github.com/YunaiV/ruoyi-vue-pro) |
44   -| `yudao-cloud` | Spring Cloud 微服务 | **[Gitee](https://gitee.com/zhijiantianya/yudao-cloud)**     [Github](https://github.com/YunaiV/yudao-cloud) |
45   -| `Spring-Boot-Labs` | Spring Boot & Cloud 入门 | **[Gitee](https://gitee.com/zhijiantianya/SpringBoot-Labs)**     [Github](https://github.com/YunaiV/SpringBoot-Labs) |
46   - | `ruoyi-vue-pro-mini` | 精简版 移除工作流 支付等模块| **[Gitee](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/mini)** |
  39 +| 项目名 | 说明 | 传送门 |
  40 +|----------------------|------------------------|-------------------------------------------------------------------------------------------------------------------------------------|
  41 +| `ruoyi-vue-pro` | Spring Boot 多模块 | **[Gitee](https://gitee.com/zhijiantianya/ruoyi-vue-pro)**     [Github](https://github.com/YunaiV/ruoyi-vue-pro) |
  42 +| `yudao-cloud` | Spring Cloud 微服务 | **[Gitee](https://gitee.com/zhijiantianya/yudao-cloud)**     [Github](https://github.com/YunaiV/yudao-cloud) |
  43 +| `Spring-Boot-Labs` | Spring Boot & Cloud 入门 | **[Gitee](https://gitee.com/zhijiantianya/SpringBoot-Labs)**     [Github](https://github.com/YunaiV/SpringBoot-Labs) |
  44 +| `ruoyi-vue-pro-mini` | 精简版:移除工作流、支付等模块 | **[Gitee](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/mini)** |
47 45  
48 46 ## 😎 开源协议
49 47  
... ... @@ -96,8 +94,9 @@
96 94 | ⭐️ | 登录日志 | 系统登录日志记录查询,包含登录异常 |
97 95 | 🚀 | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务 |
98 96 | | 通知公告 | 系统通知公告信息发布维护 |
99   -| 🚀 | 敏感词 | 配置系统敏感词,支持标签分组 |
  97 +| 🚀 | 敏感词 | 配置系统敏感词,支持标签分组 |
100 98 | 🚀 | 应用管理 | 管理 SSO 单点登录的应用,支持多种 OAuth2 授权方式 |
  99 +| 🚀 | 地区管理 | 展示省份、城市、区镇等城市信息,支持 IP 对应城市 |
101 100  
102 101 ### 工作流程
103 102  
... ... @@ -132,7 +131,7 @@ ps:核心功能已经实现,正在对接微信小程序中...
132 131 | | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 |
133 132 | 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 |
134 133 | ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 |
135   -| 🚀 | 文件服务 | 支持将文件存储到 S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等 |
  134 +| 🚀 | 文件服务 | 支持将文件存储到 S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等 |
136 135 | 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 |
137 136 | | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 |
138 137 | | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 |
... ... @@ -169,47 +168,47 @@ ps:核心功能已经实现,正在对接微信小程序中...
169 168  
170 169 ## 🐨 技术栈
171 170  
172   -| 项目 | 说明 |
173   -|-------------------------|-----------------------|
174   -| `yudao-dependencies` | Maven 依赖版本管理 |
175   -| `yudao-framework` | Java 框架拓展 |
176   -| `yudao-server` | 管理后台 + 用户 APP 的服务端 |
177   -| `yudao-ui-admin` | 管理后台的 Vue2 前端项目 |
178   -| `yudao-ui-admin-vue3` | 管理后台的 Vue3 前端项目 |
179   -| `yudao-ui-admin-uniapp` | 管理后台的 uni-app 多端项目 |
180   -| `yudao-ui-app` | 用户 APP 的 UI 界面 |
181   -| `yudao-module-system` | 系统功能的 Module 模块 |
182   -| `yudao-module-member` | 会员中心的 Module 模块 |
183   -| `yudao-module-infra` | 基础设施的 Module 模块 |
184   -| `yudao-module-tool` | 研发工具的 Module 模块 |
185   -| `yudao-module-bpm` | 工作流程的 Module 模块 |
186   -| `yudao-module-pay` | 支付系统的 Module 模块 |
  171 +| 项目 | 说明 |
  172 +|------------------------------|--------------------|
  173 +| `yudao-dependencies` | Maven 依赖版本管理 |
  174 +| `yudao-framework` | Java 框架拓展 |
  175 +| `yudao-server` | 管理后台 + 用户 APP 的服务端 |
  176 +| `yudao-ui-admin` | 管理后台的 Vue2 前端项目 |
  177 +| `yudao-ui-admin-vue3` | 管理后台的 Vue3 前端项目 |
  178 +| `yudao-ui-admin-uniapp` | 管理后台的 uni-app 多端项目 |
  179 +| `yudao-ui-app` | 用户 APP 的 UI 界面 |
  180 +| `yudao-module-system` | 系统功能的 Module 模块 |
  181 +| `yudao-module-member` | 会员中心的 Module 模块 |
  182 +| `yudao-module-infra` | 基础设施的 Module 模块 |
  183 +| `yudao-module-bpm` | 工作流程的 Module 模块 |
  184 +| `yudao-module-pay` | 支付系统的 Module 模块 |
  185 +| `yudao-module-visualization` | 大屏报表 Module 模块 |
187 186  
188 187 ### 后端
189 188  
190   -| 框架 | 说明 | 版本 | 学习指南 |
191   -|---------------------------------------------------------------------------------------------|-----------------------|-------------|----------------------------------------------------------------|
192   -| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.7.6 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |
193   -| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 / 8.0+ | |
194   -| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.15 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
195   -| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.5.2 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |
196   -| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.6.0 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
197   -| [Redis](https://redis.io/) | key-value 数据库 | 5.0 / 6.0 | |
198   -| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.18.0 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |
199   -| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.24 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
200   -| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.7.5 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |
201   -| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.5 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |
202   -| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 6.7.2 | [文档](https://doc.iocoder.cn/bpm/) |
203   -| [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) |
204   -| [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 4.0.0 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
205   -| [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.1 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) |
  189 +| 框架 | 说明 | 版本 | 学习指南 |
  190 +|---------------------------------------------------------------------------------------------|------------------|-------------|----------------------------------------------------------------|
  191 +| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.7.6 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |
  192 +| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 / 8.0+ | |
  193 +| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.15 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
  194 +| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.5.2 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |
  195 +| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.6.0 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
  196 +| [Redis](https://redis.io/) | key-value 数据库 | 5.0 / 6.0 | |
  197 +| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.18.0 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |
  198 +| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.24 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
  199 +| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.7.5 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |
  200 +| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.5 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |
  201 +| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 6.7.2 | [文档](https://doc.iocoder.cn/bpm/) |
  202 +| [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) |
  203 +| [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 4.0.0 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
  204 +| [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.1 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) |
206 205 | [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.12.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |
207   -| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.7.9 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
208   -| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.13.3 | |
209   -| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.5.3.Final | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |
210   -| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.18.24 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |
211   -| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.8.2 | - |
212   -| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 4.8.0 | - |
  206 +| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.7.9 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
  207 +| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.13.3 | |
  208 +| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.5.3.Final | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |
  209 +| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.18.24 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |
  210 +| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.8.2 | - |
  211 +| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 4.8.0 | - |
213 212  
214 213 ### [管理后台 Vue2 前端](./yudao-ui-admin)
215 214  
... ... @@ -220,22 +219,22 @@ ps:核心功能已经实现,正在对接微信小程序中...
220 219  
221 220 ### [管理后台 Vue3 前端](./yudao-ui-admin-vue3)
222 221  
223   -| 框架 | 说明 | 版本 |
  222 +| 框架 | 说明 | 版本 |
224 223 |----------------------------------------------------------------------|:------------:|:------:|
225   -| [Vue](https://staging-cn.vuejs.org/) | Vue 框架 | 3.2.45 |
226   -| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 4.0.2 |
227   -| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.27 |
  224 +| [Vue](https://staging-cn.vuejs.org/) | Vue 框架 | 3.2.45 |
  225 +| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 4.0.3 |
  226 +| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.28 |
228 227 | [TypeScript](https://www.typescriptlang.org/docs/) | TypeScript | 4.9.4 |
229 228 | [pinia](https://pinia.vuejs.org/) | vuex5 | 2.0.28 |
230   -| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.2.2 |
231   -| [vxe-table](https://vxetable.cn/) | vue最强表单 | 4.3.7 |
  229 +| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.2.2 |
  230 +| [vxe-table](https://vxetable.cn/) | vue最强表单 | 4.3.7 |
232 231  
233 232 ### [管理后台 uni-app 跨端](./yudao-ui-admin-uniapp)
234 233  
235   -| 框架 | 说明 | 版本 |
236   -|----------------------------------------------------------------------|------------------|--------|
237   -| [uni-app](hhttps://github.com/dcloudio/uni-app) | 跨平台框架 | 2.0.0 |
238   -| [uni-ui](https://github.com/dcloudio/uni-ui) | 基于 uni-app 的 UI 框架 | 1.4.20 |
  234 +| 框架 | 说明 | 版本 |
  235 +|-------------------------------------------------|--------------------|--------|
  236 +| [uni-app](hhttps://github.com/dcloudio/uni-app) | 跨平台框架 | 2.0.0 |
  237 +| [uni-ui](https://github.com/dcloudio/uni-ui) | 基于 uni-app 的 UI 框架 | 1.4.20 |
239 238  
240 239 ## 🐷 演示图
241 240  
... ...
http-client.env.json
... ... @@ -5,7 +5,7 @@
5 5 "adminTenentId": "1",
6 6  
7 7 "appApi": "http://127.0.0.1:48080/app-api",
8   - "appToken": "test1",
  8 + "appToken": "test247",
9 9 "appTenentId": "1"
10 10 },
11 11 "gateway": {
... ...
... ... @@ -14,12 +14,12 @@
14 14 <module>yudao-server</module>
15 15 <!-- 各种 module 拓展 -->
16 16 <module>yudao-module-member</module>
17   - <module>yudao-module-bpm</module>
18 17 <module>yudao-module-system</module>
19 18 <module>yudao-module-infra</module>
20 19 <module>yudao-module-pay</module>
21   - <module>yudao-module-mall</module>
  20 +<!-- <module>yudao-module-bpm</module>-->
22 21 <module>yudao-module-visualization</module>
  22 +<!-- <module>yudao-module-mall</module>-->
23 23 <!-- 示例项目 -->
24 24 <module>yudao-example</module>
25 25 </modules>
... ...
yudao-dependencies/pom.xml
... ... @@ -24,7 +24,7 @@
24 24 <!-- DB 相关 -->
25 25 <druid.version>1.2.15</druid.version>
26 26 <mybatis-plus.version>3.5.2</mybatis-plus.version>
27   - <mybatis-plus-generator.version>3.5.3</mybatis-plus-generator.version>
  27 + <mybatis-plus-generator.version>3.5.2</mybatis-plus-generator.version>
28 28 <dynamic-datasource.version>3.6.0</dynamic-datasource.version>
29 29 <redisson.version>3.18.0</redisson.version>
30 30 <!-- 服务保障相关 -->
... ... @@ -56,6 +56,7 @@
56 56 <tika-core.version>2.6.0</tika-core.version>
57 57 <aj-captcha.version>1.3.0</aj-captcha.version>
58 58 <netty-all.version>4.1.85.Final</netty-all.version>
  59 + <ip2region.version>2.6.6</ip2region.version>
59 60 <!-- 三方云服务相关 -->
60 61 <okio.version>3.0.0</okio.version>
61 62 <okhttp3.version>4.10.0</okhttp3.version>
... ... @@ -132,6 +133,11 @@
132 133 </dependency>
133 134 <dependency>
134 135 <groupId>cn.iocoder.boot</groupId>
  136 + <artifactId>yudao-spring-boot-starter-biz-ip</artifactId>
  137 + <version>${revision}</version>
  138 + </dependency>
  139 + <dependency>
  140 + <groupId>cn.iocoder.boot</groupId>
135 141 <artifactId>yudao-spring-boot-starter-captcha</artifactId>
136 142 <version>${revision}</version>
137 143 </dependency>
... ... @@ -503,6 +509,12 @@
503 509 <version>${netty-all.version}</version>
504 510 </dependency>
505 511  
  512 + <dependency>
  513 + <groupId>org.lionsoul</groupId>
  514 + <artifactId>ip2region</artifactId>
  515 + <version>${ip2region.version}</version>
  516 + </dependency>
  517 +
506 518 <!-- 三方云服务相关 -->
507 519 <dependency>
508 520 <groupId>com.squareup.okio</groupId>
... ...
yudao-framework/pom.xml
... ... @@ -36,6 +36,7 @@
36 36 <module>yudao-spring-boot-starter-biz-tenant</module>
37 37 <module>yudao-spring-boot-starter-biz-data-permission</module>
38 38 <module>yudao-spring-boot-starter-biz-error-code</module>
  39 + <module>yudao-spring-boot-starter-biz-ip</module>
39 40  
40 41 <module>yudao-spring-boot-starter-flowable</module>
41 42 <module>yudao-spring-boot-starter-captcha</module>
... ...
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/CommonStatusEnum.java
... ... @@ -20,7 +20,6 @@ public enum CommonStatusEnum implements IntArrayValuable {
20 20  
21 21 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CommonStatusEnum::getStatus).toArray();
22 22  
23   -
24 23 /**
25 24 * 状态值
26 25 */
... ...
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/TerminalEnum.java
... ... @@ -15,11 +15,12 @@ import java.util.Arrays;
15 15 @Getter
16 16 public enum TerminalEnum implements IntArrayValuable {
17 17  
18   - //TODO terminal 重复,请参考 '订单来源终端:[1:小程序 2:H5 3:iOS 4:安卓]'
19   - MINI_PROGRAM(1, "小程序"),
20   - H5(2, "H5"),
21   - IOS(3, "iOS"),
22   - ANDROID(3, "安卓"),;
  18 + WECHAT_MINI_PROGRAM(10, "微信小程序"),
  19 + WECHAT_WAP(11, "微信公众号"),
  20 + H5(20, "H5 网页"),
  21 + IOS(31, "苹果 App"),
  22 + ANDROID(32, "安卓 App"),
  23 + ;
23 24  
24 25 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TerminalEnum::getTerminal).toArray();
25 26  
... ...
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java
... ... @@ -25,6 +25,8 @@ public class DateUtils {
25 25  
26 26 public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss";
27 27  
  28 + public static final String FORMAT_HOUR_MINUTE_SECOND = "HH:mm:ss";
  29 +
28 30 /**
29 31 * 将 LocalDateTime 转换成 Date
30 32 *
... ...
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
... ... @@ -12,6 +12,11 @@ import java.time.LocalDateTime;
12 12 */
13 13 public class LocalDateTimeUtils {
14 14  
  15 + /**
  16 + * 空的 LocalDateTime 对象,主要用于 DB 唯一索引的默认值
  17 + */
  18 + public static LocalDateTime EMPTY = buildTime(1970, 1, 1);
  19 +
15 20 public static LocalDateTime addTime(Duration duration) {
16 21 return LocalDateTime.now().plus(duration);
17 22 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRuleTest.java
... ... @@ -227,7 +227,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
227 227 // 调用
228 228 Expression expression = rule.getExpression(tableName, tableAlias);
229 229 // 断言
230   - assertEquals("u.dept_id IN (10, 20) OR u.id = 1", expression.toString());
  230 + assertEquals("(u.dept_id IN (10, 20) OR u.id = 1)", expression.toString());
231 231 assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
232 232 }
233 233 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-ip/pom.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <artifactId>yudao-framework</artifactId>
  7 + <groupId>cn.iocoder.boot</groupId>
  8 + <version>${revision}</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 + <artifactId>yudao-spring-boot-starter-biz-ip</artifactId>
  12 + <packaging>jar</packaging>
  13 +
  14 + <name>${project.artifactId}</name>
  15 + <description>IP 拓展,支持如下功能:
  16 + 1. IP 功能:查询 IP 对应的城市信息
  17 + 基于 https://gitee.com/lionsoul/ip2region 实现
  18 + 2. 城市功能:查询城市编码对应的城市信息
  19 + 基于 https://github.com/modood/Administrative-divisions-of-China 实现
  20 + </description>
  21 + <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
  22 +
  23 + <properties>
  24 + <ip2region.version>2.6.6</ip2region.version>
  25 + </properties>
  26 +
  27 + <dependencies>
  28 + <dependency>
  29 + <groupId>cn.iocoder.boot</groupId>
  30 + <artifactId>yudao-common</artifactId>
  31 + </dependency>
  32 +
  33 + <!-- IP地址检索 -->
  34 + <dependency>
  35 + <groupId>org.lionsoul</groupId>
  36 + <artifactId>ip2region</artifactId>
  37 + </dependency>
  38 +
  39 + <dependency>
  40 + <groupId>org.projectlombok</groupId>
  41 + <artifactId>lombok</artifactId>
  42 + </dependency>
  43 +
  44 + <dependency>
  45 + <groupId>org.slf4j</groupId>
  46 + <artifactId>slf4j-api</artifactId>
  47 + <scope>provided</scope> <!-- 设置为 provided,只有工具类需要使用到 -->
  48 + </dependency>
  49 +
  50 + <!-- Test 测试相关 -->
  51 + <dependency>
  52 + <groupId>cn.iocoder.boot</groupId>
  53 + <artifactId>yudao-spring-boot-starter-test</artifactId>
  54 + <scope>test</scope>
  55 + </dependency>
  56 + </dependencies>
  57 +
  58 +</project>
... ...
yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/Area.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ip.core;
  2 +
  3 +import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Data;
  6 +import lombok.NoArgsConstructor;
  7 +
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * 区域节点,包括国家、省份、城市、地区等信息
  12 + *
  13 + * 数据可见 resources/area.csv 文件
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Data
  18 +@AllArgsConstructor
  19 +@NoArgsConstructor
  20 +public class Area {
  21 +
  22 + /**
  23 + * 编号 - 全球,即根目录
  24 + */
  25 + public static final Integer ID_GLOBAL = 0;
  26 + /**
  27 + * 编号 - 中国
  28 + */
  29 + public static final Integer ID_CHINA = 1;
  30 +
  31 + /**
  32 + * 编号
  33 + */
  34 + private Integer id;
  35 + /**
  36 + * 名字
  37 + */
  38 + private String name;
  39 + /**
  40 + * 类型
  41 + *
  42 + * 枚举 {@link AreaTypeEnum}
  43 + */
  44 + private Integer type;
  45 +
  46 + /**
  47 + * 父节点
  48 + */
  49 + private Area parent;
  50 + /**
  51 + * 子节点
  52 + */
  53 + private List<Area> children;
  54 +
  55 +}
... ...
yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/enums/AreaTypeEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ip.core.enums;
  2 +
  3 +import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Getter;
  6 +
  7 +import java.util.Arrays;
  8 +
  9 +/**
  10 + * 区域类型枚举
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@AllArgsConstructor
  15 +@Getter
  16 +public enum AreaTypeEnum implements IntArrayValuable {
  17 +
  18 + COUNTRY(1, "国家"),
  19 + PROVINCE(2, "省份"),
  20 + CITY(3, "城市"),
  21 + DISTRICT(4, "地区"), // 县、镇、区等
  22 + ;
  23 +
  24 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AreaTypeEnum::getType).toArray();
  25 +
  26 + /**
  27 + * 类型
  28 + */
  29 + private final Integer type;
  30 + /**
  31 + * 名字
  32 + */
  33 + private final String name;
  34 +
  35 + @Override
  36 + public int[] array() {
  37 + return ARRAYS;
  38 + }
  39 +}
... ...
yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtils.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ip.core.utils;
  2 +
  3 +import cn.hutool.core.io.resource.ResourceUtil;
  4 +import cn.hutool.core.lang.Assert;
  5 +import cn.hutool.core.text.csv.CsvRow;
  6 +import cn.hutool.core.text.csv.CsvUtil;
  7 +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
  8 +import cn.iocoder.yudao.framework.ip.core.Area;
  9 +import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum;
  10 +import lombok.extern.slf4j.Slf4j;
  11 +
  12 +import java.util.ArrayList;
  13 +import java.util.HashMap;
  14 +import java.util.List;
  15 +import java.util.Map;
  16 +
  17 +/**
  18 + * 区域工具类
  19 + *
  20 + * @author 芋道源码
  21 + */
  22 +@Slf4j
  23 +public class AreaUtils {
  24 +
  25 + /**
  26 + * 初始化 SEARCHER
  27 + */
  28 + @SuppressWarnings("InstantiationOfUtilityClass")
  29 + private final static AreaUtils INSTANCE = new AreaUtils();
  30 +
  31 + /**
  32 + * Area 内存缓存,提升访问速度
  33 + */
  34 + private static Map<Integer, Area> areas;
  35 +
  36 + private AreaUtils() {
  37 + long now = System.currentTimeMillis();
  38 + areas = new HashMap<>();
  39 + areas.put(Area.ID_GLOBAL, new Area(Area.ID_GLOBAL, "全球", 0,
  40 + null, new ArrayList<>()));
  41 + // 从 csv 中加载数据
  42 + List<CsvRow> rows = CsvUtil.getReader().read(ResourceUtil.getUtf8Reader("area.csv")).getRows();
  43 + rows.remove(0); // 删除 header
  44 + for (CsvRow row : rows) {
  45 + // 创建 Area 对象
  46 + Area area = new Area(Integer.valueOf(row.get(0)), row.get(1), Integer.valueOf(row.get(2)),
  47 + null, new ArrayList<>());
  48 + // 添加到 areas 中
  49 + areas.put(area.getId(), area);
  50 + }
  51 +
  52 + // 构建父子关系:因为 Area 中没有 parentId 字段,所以需要重复读取
  53 + for (CsvRow row : rows) {
  54 + Area area = areas.get(Integer.valueOf(row.get(0))); // 自己
  55 + Area parent = areas.get(Integer.valueOf(row.get(3))); // 父
  56 + Assert.isTrue(area != parent, "{}:父子节点相同", area.getName());
  57 + area.setParent(parent);
  58 + parent.getChildren().add(area);
  59 + }
  60 + log.info("启动加载 AreaUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now);
  61 + }
  62 +
  63 + /**
  64 + * 获得指定编号对应的区域
  65 + *
  66 + * @param id 区域编号
  67 + * @return 区域
  68 + */
  69 + public static Area getArea(Integer id) {
  70 + return areas.get(id);
  71 + }
  72 +
  73 + /**
  74 + * 格式化区域
  75 + *
  76 + * @param id 区域编号
  77 + * @return 格式化后的区域
  78 + */
  79 + public static String format(Integer id) {
  80 + return format(id, " ");
  81 + }
  82 +
  83 + /**
  84 + * 格式化区域
  85 + *
  86 + * 例如说:
  87 + * 1. id = “静安区”时:上海 上海市 静安区
  88 + * 2. id = “上海市”时:上海 上海市
  89 + * 3. id = “上海”时:上海
  90 + * 4. id = “美国”时:美国
  91 + * 当区域在中国时,默认不显示中国
  92 + *
  93 + * @param id 区域编号
  94 + * @param separator 分隔符
  95 + * @return 格式化后的区域
  96 + */
  97 + public static String format(Integer id, String separator) {
  98 + // 获得区域
  99 + Area area = areas.get(id);
  100 + if (area == null) {
  101 + return null;
  102 + }
  103 +
  104 + // 格式化
  105 + StringBuilder sb = new StringBuilder();
  106 + for (int i = 0; i < AreaTypeEnum.values().length; i++) { // 避免死循环
  107 + sb.insert(0, area.getName());
  108 + // “递归”父节点
  109 + area = area.getParent();
  110 + if (area == null
  111 + || ObjectUtils.equalsAny(area.getId(), Area.ID_GLOBAL, Area.ID_CHINA)) { // 跳过父节点为中国的情况
  112 + break;
  113 + }
  114 + sb.insert(0, separator);
  115 + }
  116 + return sb.toString();
  117 + }
  118 +
  119 +}
... ...
yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/IPUtils.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ip.core.utils;
  2 +
  3 +import cn.hutool.core.io.resource.ResourceUtil;
  4 +import cn.iocoder.yudao.framework.ip.core.Area;
  5 +import lombok.SneakyThrows;
  6 +import lombok.extern.slf4j.Slf4j;
  7 +import org.lionsoul.ip2region.xdb.Searcher;
  8 +
  9 +import java.io.IOException;
  10 +
  11 +/**
  12 + * IP 工具类
  13 + *
  14 + * IP 数据源来自 ip2region.xdb 精简版,基于 <a href="https://gitee.com/zhijiantianya/ip2region"/> 项目
  15 + *
  16 + * @author wanglhup
  17 + */
  18 +@Slf4j
  19 +public class IPUtils {
  20 +
  21 + /**
  22 + * 初始化 SEARCHER
  23 + */
  24 + @SuppressWarnings("InstantiationOfUtilityClass")
  25 + private final static IPUtils INSTANCE = new IPUtils();
  26 +
  27 + /**
  28 + * IP 查询器,启动加载到内存中
  29 + */
  30 + private static Searcher SEARCHER;
  31 +
  32 + /**
  33 + * 私有化构造
  34 + */
  35 + private IPUtils() {
  36 + try {
  37 + long now = System.currentTimeMillis();
  38 + byte[] bytes = ResourceUtil.readBytes("ip2region.xdb");
  39 + SEARCHER = Searcher.newWithBuffer(bytes);
  40 + log.info("启动加载 IPUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now);
  41 + } catch (IOException e) {
  42 + log.error("启动加载 IPUtils 失败", e);
  43 + }
  44 + }
  45 +
  46 + /**
  47 + * 查询 IP 对应的地区编号
  48 + *
  49 + * @param ip IP 地址,格式为 127.0.0.1
  50 + * @return 地区id
  51 + */
  52 + @SneakyThrows
  53 + public static Integer getAreaId(String ip) {
  54 + return Integer.parseInt(SEARCHER.search(ip));
  55 + }
  56 +
  57 + /**
  58 + * 查询 IP 对应的地区编号
  59 + *
  60 + * @param ip IP 地址的时间戳,格式参考{@link Searcher#checkIP(String)} 的返回
  61 + * @return 地区编号
  62 + */
  63 + @SneakyThrows
  64 + public static Integer getAreaId(long ip) {
  65 + return Integer.parseInt(SEARCHER.search(ip));
  66 + }
  67 +
  68 + /**
  69 + * 查询 IP 对应的地区
  70 + *
  71 + * @param ip IP 地址,格式为 127.0.0.1
  72 + * @return 地区
  73 + */
  74 + public static Area getArea(String ip) {
  75 + return AreaUtils.getArea(getAreaId(ip));
  76 + }
  77 +
  78 + /**
  79 + * 查询 IP 对应的地区
  80 + *
  81 + * @param ip IP 地址的时间戳,格式参考{@link Searcher#checkIP(String)} 的返回
  82 + * @return 地区
  83 + */
  84 + public static Area getArea(long ip) {
  85 + return AreaUtils.getArea(getAreaId(ip));
  86 + }
  87 +}
... ...
yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/package-info.java 0 → 100644
  1 +/**
  2 + * IP 拓展,支持如下功能:
  3 + *
  4 + * 1. IP 功能:查询 IP 对应的城市信息
  5 + * 基于 https://gitee.com/lionsoul/ip2region 实现
  6 + * 2. 城市功能:查询城市编码对应的城市信息
  7 + * 基于 https://github.com/modood/Administrative-divisions-of-China 实现
  8 + *
  9 + * @author 芋道源码
  10 + */
  11 +package cn.iocoder.yudao.framework.ip;
... ...
yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/resources/area.csv 0 → 100644
  1 +id,name,type,parentId
  2 +1,中国,1,0
  3 +2,蒙古,1,0
  4 +3,朝鲜,1,0
  5 +4,韩国,1,0
  6 +5,日本,1,0
  7 +6,菲律宾,1,0
  8 +7,越南,1,0
  9 +8,老挝,1,0
  10 +9,柬埔寨,1,0
  11 +10,缅甸,1,0
  12 +11,泰国,1,0
  13 +12,马来西亚,1,0
  14 +13,文莱,1,0
  15 +14,新加坡,1,0
  16 +15,印度尼西亚,1,0
  17 +16,东帝汶,1,0
  18 +17,尼泊尔,1,0
  19 +18,不丹,1,0
  20 +19,孟加拉国,1,0
  21 +20,印度,1,0
  22 +21,巴基斯坦,1,0
  23 +22,斯里兰卡,1,0
  24 +23,马尔代夫,1,0
  25 +24,哈萨克斯坦,1,0
  26 +25,吉尔吉斯斯坦,1,0
  27 +26,塔吉克斯坦,1,0
  28 +27,乌兹别克斯坦,1,0
  29 +28,土库曼斯坦,1,0
  30 +29,阿富汗,1,0
  31 +30,伊拉克,1,0
  32 +31,伊朗,1,0
  33 +32,叙利亚,1,0
  34 +33,约旦,1,0
  35 +34,黎巴嫩,1,0
  36 +35,以色列,1,0
  37 +36,巴勒斯坦,1,0
  38 +37,沙特阿拉伯,1,0
  39 +38,巴林,1,0
  40 +39,卡塔尔,1,0
  41 +40,科威特,1,0
  42 +41,阿拉伯联合酋长国,1,0
  43 +42,阿曼,1,0
  44 +43,也门,1,0
  45 +44,格鲁吉亚,1,0
  46 +45,亚美尼亚,1,0
  47 +46,阿塞拜疆,1,0
  48 +47,土耳其,1,0
  49 +48,塞浦路斯,1,0
  50 +49,芬兰,1,0
  51 +50,瑞典,1,0
  52 +51,挪威,1,0
  53 +52,冰岛,1,0
  54 +53,丹麦,1,0
  55 +54,爱沙尼亚,1,0
  56 +55,拉脱维亚,1,0
  57 +56,立陶宛,1,0
  58 +57,白俄罗斯,1,0
  59 +58,俄罗斯,1,0
  60 +59,乌克兰,1,0
  61 +60,摩尔多瓦,1,0
  62 +61,波兰,1,0
  63 +62,捷克,1,0
  64 +63,斯洛伐克,1,0
  65 +64,匈牙利,1,0
  66 +65,德国,1,0
  67 +66,奥地利,1,0
  68 +67,瑞士,1,0
  69 +68,列支敦士登,1,0
  70 +69,英国,1,0
  71 +70,爱尔兰,1,0
  72 +71,荷兰,1,0
  73 +72,比利时,1,0
  74 +73,卢森堡,1,0
  75 +74,法国,1,0
  76 +75,摩纳哥,1,0
  77 +76,罗马尼亚,1,0
  78 +77,保加利亚,1,0
  79 +78,塞尔维亚,1,0
  80 +79,马其顿,1,0
  81 +80,阿尔巴尼亚,1,0
  82 +81,希腊,1,0
  83 +82,斯洛文尼亚,1,0
  84 +83,克罗地亚,1,0
  85 +84,波斯尼亚和墨塞哥维那,1,0
  86 +85,意大利,1,0
  87 +86,梵蒂冈,1,0
  88 +87,圣马力诺,1,0
  89 +88,马耳他,1,0
  90 +89,西班牙,1,0
  91 +90,葡萄牙,1,0
  92 +91,安道尔共和国,1,0
  93 +92,埃及,1,0
  94 +93,利比亚,1,0
  95 +94,苏丹,1,0
  96 +95,突尼斯,1,0
  97 +96,阿尔及利亚,1,0
  98 +97,摩洛哥,1,0
  99 +98,亚速尔群岛,1,0
  100 +99,马德拉群岛,1,0
  101 +100,埃塞俄比亚,1,0
  102 +101,厄立特里亚,1,0
  103 +102,索马里,1,0
  104 +103,吉布提,1,0
  105 +104,肯尼亚,1,0
  106 +105,坦桑尼亚,1,0
  107 +106,乌干达,1,0
  108 +107,卢旺达,1,0
  109 +108,布隆迪,1,0
  110 +109,塞舌尔,1,0
  111 +110,圣多美及普林西比,1,0
  112 +111,塞内加尔,1,0
  113 +112,冈比亚,1,0
  114 +113,马里,1,0
  115 +114,布基纳法索,1,0
  116 +115,几内亚,1,0
  117 +116,几内亚比绍,1,0
  118 +117,佛得角,1,0
  119 +118,塞拉利昂,1,0
  120 +119,利比里亚,1,0
  121 +120,科特迪瓦,1,0
  122 +121,加纳,1,0
  123 +122,多哥,1,0
  124 +123,贝宁,1,0
  125 +124,尼日尔,1,0
  126 +125,加那利群岛,1,0
  127 +126,赞比亚,1,0
  128 +127,安哥拉,1,0
  129 +128,津巴布韦,1,0
  130 +129,马拉维,1,0
  131 +130,莫桑比克,1,0
  132 +131,博茨瓦纳,1,0
  133 +132,纳米比亚,1,0
  134 +133,南非,1,0
  135 +134,斯威士兰,1,0
  136 +135,莱索托,1,0
  137 +136,马达加斯加,1,0
  138 +137,科摩罗,1,0
  139 +138,毛里求斯,1,0
  140 +139,留尼旺,1,0
  141 +140,圣赫勒拿,1,0
  142 +141,澳大利亚,1,0
  143 +142,新西兰,1,0
  144 +143,巴布亚新几内亚,1,0
  145 +144,所罗门群岛,1,0
  146 +145,瓦努阿图共和国,1,0
  147 +146,密克罗尼西亚,1,0
  148 +147,马绍尔群岛,1,0
  149 +148,帕劳,1,0
  150 +149,瑙鲁,1,0
  151 +150,基里巴斯,1,0
  152 +151,图瓦卢,1,0
  153 +152,萨摩亚,1,0
  154 +153,斐济,1,0
  155 +154,汤加,1,0
  156 +155,库克群岛,1,0
  157 +156,关岛,1,0
  158 +157,新喀里多尼亚,1,0
  159 +158,法属波利尼西亚,1,0
  160 +159,皮特凯恩岛,1,0
  161 +160,瓦利斯与富图纳,1,0
  162 +161,纽埃,1,0
  163 +162,托克劳,1,0
  164 +163,美属萨摩亚,1,0
  165 +164,北马里亚纳,1,0
  166 +165,加拿大,1,0
  167 +166,美国,1,0
  168 +167,墨西哥,1,0
  169 +168,格陵兰,1,0
  170 +169,危地马拉,1,0
  171 +170,伯利兹,1,0
  172 +171,萨尔瓦多,1,0
  173 +172,洪都拉斯,1,0
  174 +173,尼加拉瓜,1,0
  175 +174,哥斯达黎加,1,0
  176 +175,巴拿马,1,0
  177 +176,巴哈马,1,0
  178 +177,古巴,1,0
  179 +178,牙买加,1,0
  180 +179,海地,1,0
  181 +180,多米尼加共和国,1,0
  182 +181,安提瓜和巴布达,1,0
  183 +182,圣基茨和尼维斯,1,0
  184 +183,多米尼克,1,0
  185 +184,圣卢西亚,1,0
  186 +185,圣文森特和格林纳丁斯,1,0
  187 +186,格林纳达,1,0
  188 +187,巴巴多斯,1,0
  189 +188,特立尼达和多巴哥,1,0
  190 +189,波多黎各,1,0
  191 +190,英属维尔京群岛,1,0
  192 +191,美属维尔京群岛,1,0
  193 +192,安圭拉,1,0
  194 +193,蒙特塞拉特岛,1,0
  195 +194,瓜德罗普,1,0
  196 +195,马提尼克,1,0
  197 +196,荷属安的列斯,1,0
  198 +197,阿鲁巴,1,0
  199 +198,特克斯和凯科斯群岛,1,0
  200 +199,开曼群岛,1,0
  201 +200,百慕大,1,0
  202 +201,哥伦比亚,1,0
  203 +202,委内瑞拉,1,0
  204 +203,圭亚那,1,0
  205 +204,法属圭亚那,1,0
  206 +205,苏里南,1,0
  207 +206,厄瓜多尔,1,0
  208 +207,秘鲁,1,0
  209 +208,玻利维亚,1,0
  210 +209,巴西,1,0
  211 +210,智利,1,0
  212 +211,阿根廷,1,0
  213 +212,乌拉圭,1,0
  214 +213,巴拉圭,1,0
  215 +214,波黑,1,0
  216 +215,直布罗陀,1,0
  217 +216,新喀里多尼亚群岛,1,0
  218 +217,瓦利斯和富图纳群岛,1,0
  219 +218,泽西岛,1,0
  220 +219,黑山,1,0
  221 +220,英属马恩岛,1,0
  222 +221,尼日利亚,1,0
  223 +222,喀麦隆,1,0
  224 +223,加蓬,1,0
  225 +224,乍得,1,0
  226 +225,刚果共和国,1,0
  227 +226,中非共和国,1,0
  228 +227,南苏丹,1,0
  229 +228,赤道几内亚,1,0
  230 +229,毛里塔尼亚,1,0
  231 +230,刚果民主共和国,1,0
  232 +231,留尼汪岛,1,0
  233 +232,格陵兰岛,1,0
  234 +233,法罗群岛,1,0
  235 +234,根西岛,1,0
  236 +235,百慕大群岛,1,0
  237 +236,圣皮埃尔和密克隆群岛,1,0
  238 +237,法属圣马丁,1,0
  239 +238,奥兰群岛,1,0
  240 +239,北马里亚纳群岛,1,0
  241 +240,库拉索,1,0
  242 +241,博内尔岛,1,0
  243 +242,圣马丁岛,1,0
  244 +243,圣巴泰勒米岛,1,0
  245 +244,福克兰群岛,1,0
  246 +245,圣多美和普林西比,1,0
  247 +246,英属印度洋领地,1,0
  248 +247,东萨摩亚,1,0
  249 +248,诺福克岛,1,0
  250 +110000,北京,2,1
  251 +120000,天津,2,1
  252 +130000,河北省,2,1
  253 +140000,山西省,2,1
  254 +150000,内蒙古自治区,2,1
  255 +210000,辽宁省,2,1
  256 +220000,吉林省,2,1
  257 +230000,黑龙江省,2,1
  258 +310000,上海,2,1
  259 +320000,江苏省,2,1
  260 +330000,浙江省,2,1
  261 +340000,安徽省,2,1
  262 +350000,福建省,2,1
  263 +360000,江西省,2,1
  264 +370000,山东省,2,1
  265 +410000,河南省,2,1
  266 +420000,湖北省,2,1
  267 +430000,湖南省,2,1
  268 +440000,广东省,2,1
  269 +450000,广西壮族自治区,2,1
  270 +460000,海南省,2,1
  271 +500000,重庆,2,1
  272 +510000,四川省,2,1
  273 +520000,贵州省,2,1
  274 +530000,云南省,2,1
  275 +540000,西藏自治区,2,1
  276 +610000,陕西省,2,1
  277 +620000,甘肃省,2,1
  278 +630000,青海省,2,1
  279 +640000,宁夏回族自治区,2,1
  280 +650000,新疆维吾尔自治区,2,1
  281 +110100,北京市,3,110000
  282 +120100,天津市,3,120000
  283 +130100,石家庄市,3,130000
  284 +130200,唐山市,3,130000
  285 +130300,秦皇岛市,3,130000
  286 +130400,邯郸市,3,130000
  287 +130500,邢台市,3,130000
  288 +130600,保定市,3,130000
  289 +130700,张家口市,3,130000
  290 +130800,承德市,3,130000
  291 +130900,沧州市,3,130000
  292 +131000,廊坊市,3,130000
  293 +131100,衡水市,3,130000
  294 +140100,太原市,3,140000
  295 +140200,大同市,3,140000
  296 +140300,阳泉市,3,140000
  297 +140400,长治市,3,140000
  298 +140500,晋城市,3,140000
  299 +140600,朔州市,3,140000
  300 +140700,晋中市,3,140000
  301 +140800,运城市,3,140000
  302 +140900,忻州市,3,140000
  303 +141000,临汾市,3,140000
  304 +141100,吕梁市,3,140000
  305 +150100,呼和浩特市,3,150000
  306 +150200,包头市,3,150000
  307 +150300,乌海市,3,150000
  308 +150400,赤峰市,3,150000
  309 +150500,通辽市,3,150000
  310 +150600,鄂尔多斯市,3,150000
  311 +150700,呼伦贝尔市,3,150000
  312 +150800,巴彦淖尔市,3,150000
  313 +150900,乌兰察布市,3,150000
  314 +152200,兴安盟,3,150000
  315 +152500,锡林郭勒盟,3,150000
  316 +152900,阿拉善盟,3,150000
  317 +210100,沈阳市,3,210000
  318 +210200,大连市,3,210000
  319 +210300,鞍山市,3,210000
  320 +210400,抚顺市,3,210000
  321 +210500,本溪市,3,210000
  322 +210600,丹东市,3,210000
  323 +210700,锦州市,3,210000
  324 +210800,营口市,3,210000
  325 +210900,阜新市,3,210000
  326 +211000,辽阳市,3,210000
  327 +211100,盘锦市,3,210000
  328 +211200,铁岭市,3,210000
  329 +211300,朝阳市,3,210000
  330 +211400,葫芦岛市,3,210000
  331 +220100,长春市,3,220000
  332 +220200,吉林市,3,220000
  333 +220300,四平市,3,220000
  334 +220400,辽源市,3,220000
  335 +220500,通化市,3,220000
  336 +220600,白山市,3,220000
  337 +220700,松原市,3,220000
  338 +220800,白城市,3,220000
  339 +222400,延边朝鲜族自治州,3,220000
  340 +230100,哈尔滨市,3,230000
  341 +230200,齐齐哈尔市,3,230000
  342 +230300,鸡西市,3,230000
  343 +230400,鹤岗市,3,230000
  344 +230500,双鸭山市,3,230000
  345 +230600,大庆市,3,230000
  346 +230700,伊春市,3,230000
  347 +230800,佳木斯市,3,230000
  348 +230900,七台河市,3,230000
  349 +231000,牡丹江市,3,230000
  350 +231100,黑河市,3,230000
  351 +231200,绥化市,3,230000
  352 +232700,大兴安岭地区,3,230000
  353 +310100,上海市,3,310000
  354 +320100,南京市,3,320000
  355 +320200,无锡市,3,320000
  356 +320300,徐州市,3,320000
  357 +320400,常州市,3,320000
  358 +320500,苏州市,3,320000
  359 +320600,南通市,3,320000
  360 +320700,连云港市,3,320000
  361 +320800,淮安市,3,320000
  362 +320900,盐城市,3,320000
  363 +321000,扬州市,3,320000
  364 +321100,镇江市,3,320000
  365 +321200,泰州市,3,320000
  366 +321300,宿迁市,3,320000
  367 +330100,杭州市,3,330000
  368 +330200,宁波市,3,330000
  369 +330300,温州市,3,330000
  370 +330400,嘉兴市,3,330000
  371 +330500,湖州市,3,330000
  372 +330600,绍兴市,3,330000
  373 +330700,金华市,3,330000
  374 +330800,衢州市,3,330000
  375 +330900,舟山市,3,330000
  376 +331000,台州市,3,330000
  377 +331100,丽水市,3,330000
  378 +340100,合肥市,3,340000
  379 +340200,芜湖市,3,340000
  380 +340300,蚌埠市,3,340000
  381 +340400,淮南市,3,340000
  382 +340500,马鞍山市,3,340000
  383 +340600,淮北市,3,340000
  384 +340700,铜陵市,3,340000
  385 +340800,安庆市,3,340000
  386 +341000,黄山市,3,340000
  387 +341100,滁州市,3,340000
  388 +341200,阜阳市,3,340000
  389 +341300,宿州市,3,340000
  390 +341500,六安市,3,340000
  391 +341600,亳州市,3,340000
  392 +341700,池州市,3,340000
  393 +341800,宣城市,3,340000
  394 +350100,福州市,3,350000
  395 +350200,厦门市,3,350000
  396 +350300,莆田市,3,350000
  397 +350400,三明市,3,350000
  398 +350500,泉州市,3,350000
  399 +350600,漳州市,3,350000
  400 +350700,南平市,3,350000
  401 +350800,龙岩市,3,350000
  402 +350900,宁德市,3,350000
  403 +360100,南昌市,3,360000
  404 +360200,景德镇市,3,360000
  405 +360300,萍乡市,3,360000
  406 +360400,九江市,3,360000
  407 +360500,新余市,3,360000
  408 +360600,鹰潭市,3,360000
  409 +360700,赣州市,3,360000
  410 +360800,吉安市,3,360000
  411 +360900,宜春市,3,360000
  412 +361000,抚州市,3,360000
  413 +361100,上饶市,3,360000
  414 +370100,济南市,3,370000
  415 +370200,青岛市,3,370000
  416 +370300,淄博市,3,370000
  417 +370400,枣庄市,3,370000
  418 +370500,东营市,3,370000
  419 +370600,烟台市,3,370000
  420 +370700,潍坊市,3,370000
  421 +370800,济宁市,3,370000
  422 +370900,泰安市,3,370000
  423 +371000,威海市,3,370000
  424 +371100,日照市,3,370000
  425 +371300,临沂市,3,370000
  426 +371400,德州市,3,370000
  427 +371500,聊城市,3,370000
  428 +371600,滨州市,3,370000
  429 +371700,菏泽市,3,370000
  430 +410100,郑州市,3,410000
  431 +410200,开封市,3,410000
  432 +410300,洛阳市,3,410000
  433 +410400,平顶山市,3,410000
  434 +410500,安阳市,3,410000
  435 +410600,鹤壁市,3,410000
  436 +410700,新乡市,3,410000
  437 +410800,焦作市,3,410000
  438 +410900,濮阳市,3,410000
  439 +411000,许昌市,3,410000
  440 +411100,漯河市,3,410000
  441 +411200,三门峡市,3,410000
  442 +411300,南阳市,3,410000
  443 +411400,商丘市,3,410000
  444 +411500,信阳市,3,410000
  445 +411600,周口市,3,410000
  446 +411700,驻马店市,3,410000
  447 +419000,省直辖县级行政区划,3,410000
  448 +420100,武汉市,3,420000
  449 +420200,黄石市,3,420000
  450 +420300,十堰市,3,420000
  451 +420500,宜昌市,3,420000
  452 +420600,襄阳市,3,420000
  453 +420700,鄂州市,3,420000
  454 +420800,荆门市,3,420000
  455 +420900,孝感市,3,420000
  456 +421000,荆州市,3,420000
  457 +421100,黄冈市,3,420000
  458 +421200,咸宁市,3,420000
  459 +421300,随州市,3,420000
  460 +422800,恩施土家族苗族自治州,3,420000
  461 +429000,省直辖县级行政区划,3,420000
  462 +430100,长沙市,3,430000
  463 +430200,株洲市,3,430000
  464 +430300,湘潭市,3,430000
  465 +430400,衡阳市,3,430000
  466 +430500,邵阳市,3,430000
  467 +430600,岳阳市,3,430000
  468 +430700,常德市,3,430000
  469 +430800,张家界市,3,430000
  470 +430900,益阳市,3,430000
  471 +431000,郴州市,3,430000
  472 +431100,永州市,3,430000
  473 +431200,怀化市,3,430000
  474 +431300,娄底市,3,430000
  475 +433100,湘西土家族苗族自治州,3,430000
  476 +440100,广州市,3,440000
  477 +440200,韶关市,3,440000
  478 +440300,深圳市,3,440000
  479 +440400,珠海市,3,440000
  480 +440500,汕头市,3,440000
  481 +440600,佛山市,3,440000
  482 +440700,江门市,3,440000
  483 +440800,湛江市,3,440000
  484 +440900,茂名市,3,440000
  485 +441200,肇庆市,3,440000
  486 +441300,惠州市,3,440000
  487 +441400,梅州市,3,440000
  488 +441500,汕尾市,3,440000
  489 +441600,河源市,3,440000
  490 +441700,阳江市,3,440000
  491 +441800,清远市,3,440000
  492 +441900,东莞市,3,440000
  493 +442000,中山市,3,440000
  494 +445100,潮州市,3,440000
  495 +445200,揭阳市,3,440000
  496 +445300,云浮市,3,440000
  497 +450100,南宁市,3,450000
  498 +450200,柳州市,3,450000
  499 +450300,桂林市,3,450000
  500 +450400,梧州市,3,450000
  501 +450500,北海市,3,450000
  502 +450600,防城港市,3,450000
  503 +450700,钦州市,3,450000
  504 +450800,贵港市,3,450000
  505 +450900,玉林市,3,450000
  506 +451000,百色市,3,450000
  507 +451100,贺州市,3,450000
  508 +451200,河池市,3,450000
  509 +451300,来宾市,3,450000
  510 +451400,崇左市,3,450000
  511 +460100,海口市,3,460000
  512 +460200,三亚市,3,460000
  513 +460300,三沙市,3,460000
  514 +460400,儋州市,3,460000
  515 +469000,省直辖县级行政区划,3,460000
  516 +500100,重庆市,3,500000
  517 +510100,成都市,3,510000
  518 +510300,自贡市,3,510000
  519 +510400,攀枝花市,3,510000
  520 +510500,泸州市,3,510000
  521 +510600,德阳市,3,510000
  522 +510700,绵阳市,3,510000
  523 +510800,广元市,3,510000
  524 +510900,遂宁市,3,510000
  525 +511000,内江市,3,510000
  526 +511100,乐山市,3,510000
  527 +511300,南充市,3,510000
  528 +511400,眉山市,3,510000
  529 +511500,宜宾市,3,510000
  530 +511600,广安市,3,510000
  531 +511700,达州市,3,510000
  532 +511800,雅安市,3,510000
  533 +511900,巴中市,3,510000
  534 +512000,资阳市,3,510000
  535 +513200,阿坝藏族羌族自治州,3,510000
  536 +513300,甘孜藏族自治州,3,510000
  537 +513400,凉山彝族自治州,3,510000
  538 +520100,贵阳市,3,520000
  539 +520200,六盘水市,3,520000
  540 +520300,遵义市,3,520000
  541 +520400,安顺市,3,520000
  542 +520500,毕节市,3,520000
  543 +520600,铜仁市,3,520000
  544 +522300,黔西南布依族苗族自治州,3,520000
  545 +522600,黔东南苗族侗族自治州,3,520000
  546 +522700,黔南布依族苗族自治州,3,520000
  547 +530100,昆明市,3,530000
  548 +530300,曲靖市,3,530000
  549 +530400,玉溪市,3,530000
  550 +530500,保山市,3,530000
  551 +530600,昭通市,3,530000
  552 +530700,丽江市,3,530000
  553 +530800,普洱市,3,530000
  554 +530900,临沧市,3,530000
  555 +532300,楚雄彝族自治州,3,530000
  556 +532500,红河哈尼族彝族自治州,3,530000
  557 +532600,文山壮族苗族自治州,3,530000
  558 +532800,西双版纳傣族自治州,3,530000
  559 +532900,大理白族自治州,3,530000
  560 +533100,德宏傣族景颇族自治州,3,530000
  561 +533300,怒江傈僳族自治州,3,530000
  562 +533400,迪庆藏族自治州,3,530000
  563 +540100,拉萨市,3,540000
  564 +540200,日喀则市,3,540000
  565 +540300,昌都市,3,540000
  566 +540400,林芝市,3,540000
  567 +540500,山南市,3,540000
  568 +540600,那曲市,3,540000
  569 +542500,阿里地区,3,540000
  570 +610100,西安市,3,610000
  571 +610200,铜川市,3,610000
  572 +610300,宝鸡市,3,610000
  573 +610400,咸阳市,3,610000
  574 +610500,渭南市,3,610000
  575 +610600,延安市,3,610000
  576 +610700,汉中市,3,610000
  577 +610800,榆林市,3,610000
  578 +610900,安康市,3,610000
  579 +611000,商洛市,3,610000
  580 +620100,兰州市,3,620000
  581 +620200,嘉峪关市,3,620000
  582 +620300,金昌市,3,620000
  583 +620400,白银市,3,620000
  584 +620500,天水市,3,620000
  585 +620600,武威市,3,620000
  586 +620700,张掖市,3,620000
  587 +620800,平凉市,3,620000
  588 +620900,酒泉市,3,620000
  589 +621000,庆阳市,3,620000
  590 +621100,定西市,3,620000
  591 +621200,陇南市,3,620000
  592 +622900,临夏回族自治州,3,620000
  593 +623000,甘南藏族自治州,3,620000
  594 +630100,西宁市,3,630000
  595 +630200,海东市,3,630000
  596 +632200,海北藏族自治州,3,630000
  597 +632300,黄南藏族自治州,3,630000
  598 +632500,海南藏族自治州,3,630000
  599 +632600,果洛藏族自治州,3,630000
  600 +632700,玉树藏族自治州,3,630000
  601 +632800,海西蒙古族藏族自治州,3,630000
  602 +640100,银川市,3,640000
  603 +640200,石嘴山市,3,640000
  604 +640300,吴忠市,3,640000
  605 +640400,固原市,3,640000
  606 +640500,中卫市,3,640000
  607 +650100,乌鲁木齐市,3,650000
  608 +650200,克拉玛依市,3,650000
  609 +650400,吐鲁番市,3,650000
  610 +650500,哈密市,3,650000
  611 +652300,昌吉回族自治州,3,650000
  612 +652700,博尔塔拉蒙古自治州,3,650000
  613 +652800,巴音郭楞蒙古自治州,3,650000
  614 +652900,阿克苏地区,3,650000
  615 +653000,克孜勒苏柯尔克孜自治州,3,650000
  616 +653100,喀什地区,3,650000
  617 +653200,和田地区,3,650000
  618 +654000,伊犁哈萨克自治州,3,650000
  619 +654200,塔城地区,3,650000
  620 +654300,阿勒泰地区,3,650000
  621 +659000,自治区直辖县级行政区划,3,650000
  622 +110101,东城区,4,110100
  623 +110102,西城区,4,110100
  624 +110105,朝阳区,4,110100
  625 +110106,丰台区,4,110100
  626 +110107,石景山区,4,110100
  627 +110108,海淀区,4,110100
  628 +110109,门头沟区,4,110100
  629 +110111,房山区,4,110100
  630 +110112,通州区,4,110100
  631 +110113,顺义区,4,110100
  632 +110114,昌平区,4,110100
  633 +110115,大兴区,4,110100
  634 +110116,怀柔区,4,110100
  635 +110117,平谷区,4,110100
  636 +110118,密云区,4,110100
  637 +110119,延庆区,4,110100
  638 +120101,和平区,4,120100
  639 +120102,河东区,4,120100
  640 +120103,河西区,4,120100
  641 +120104,南开区,4,120100
  642 +120105,河北区,4,120100
  643 +120106,红桥区,4,120100
  644 +120110,东丽区,4,120100
  645 +120111,西青区,4,120100
  646 +120112,津南区,4,120100
  647 +120113,北辰区,4,120100
  648 +120114,武清区,4,120100
  649 +120115,宝坻区,4,120100
  650 +120116,滨海新区,4,120100
  651 +120117,宁河区,4,120100
  652 +120118,静海区,4,120100
  653 +120119,蓟州区,4,120100
  654 +130102,长安区,4,130100
  655 +130104,桥西区,4,130100
  656 +130105,新华区,4,130100
  657 +130107,井陉矿区,4,130100
  658 +130108,裕华区,4,130100
  659 +130109,藁城区,4,130100
  660 +130110,鹿泉区,4,130100
  661 +130111,栾城区,4,130100
  662 +130121,井陉县,4,130100
  663 +130123,正定县,4,130100
  664 +130125,行唐县,4,130100
  665 +130126,灵寿县,4,130100
  666 +130127,高邑县,4,130100
  667 +130128,深泽县,4,130100
  668 +130129,赞皇县,4,130100
  669 +130130,无极县,4,130100
  670 +130131,平山县,4,130100
  671 +130132,元氏县,4,130100
  672 +130133,赵县,4,130100
  673 +130171,石家庄高新技术产业开发区,4,130100
  674 +130172,石家庄循环化工园区,4,130100
  675 +130181,辛集市,4,130100
  676 +130183,晋州市,4,130100
  677 +130184,新乐市,4,130100
  678 +130202,路南区,4,130200
  679 +130203,路北区,4,130200
  680 +130204,古冶区,4,130200
  681 +130205,开平区,4,130200
  682 +130207,丰南区,4,130200
  683 +130208,丰润区,4,130200
  684 +130209,曹妃甸区,4,130200
  685 +130224,滦南县,4,130200
  686 +130225,乐亭县,4,130200
  687 +130227,迁西县,4,130200
  688 +130229,玉田县,4,130200
  689 +130271,河北唐山芦台经济开发区,4,130200
  690 +130272,唐山市汉沽管理区,4,130200
  691 +130273,唐山高新技术产业开发区,4,130200
  692 +130274,河北唐山海港经济开发区,4,130200
  693 +130281,遵化市,4,130200
  694 +130283,迁安市,4,130200
  695 +130284,滦州市,4,130200
  696 +130302,海港区,4,130300
  697 +130303,山海关区,4,130300
  698 +130304,北戴河区,4,130300
  699 +130306,抚宁区,4,130300
  700 +130321,青龙满族自治县,4,130300
  701 +130322,昌黎县,4,130300
  702 +130324,卢龙县,4,130300
  703 +130371,秦皇岛市经济技术开发区,4,130300
  704 +130372,北戴河新区,4,130300
  705 +130402,邯山区,4,130400
  706 +130403,丛台区,4,130400
  707 +130404,复兴区,4,130400
  708 +130406,峰峰矿区,4,130400
  709 +130407,肥乡区,4,130400
  710 +130408,永年区,4,130400
  711 +130423,临漳县,4,130400
  712 +130424,成安县,4,130400
  713 +130425,大名县,4,130400
  714 +130426,涉县,4,130400
  715 +130427,磁县,4,130400
  716 +130430,邱县,4,130400
  717 +130431,鸡泽县,4,130400
  718 +130432,广平县,4,130400
  719 +130433,馆陶县,4,130400
  720 +130434,魏县,4,130400
  721 +130435,曲周县,4,130400
  722 +130471,邯郸经济技术开发区,4,130400
  723 +130473,邯郸冀南新区,4,130400
  724 +130481,武安市,4,130400
  725 +130502,襄都区,4,130500
  726 +130503,信都区,4,130500
  727 +130505,任泽区,4,130500
  728 +130506,南和区,4,130500
  729 +130522,临城县,4,130500
  730 +130523,内丘县,4,130500
  731 +130524,柏乡县,4,130500
  732 +130525,隆尧县,4,130500
  733 +130528,宁晋县,4,130500
  734 +130529,巨鹿县,4,130500
  735 +130530,新河县,4,130500
  736 +130531,广宗县,4,130500
  737 +130532,平乡县,4,130500
  738 +130533,威县,4,130500
  739 +130534,清河县,4,130500
  740 +130535,临西县,4,130500
  741 +130571,河北邢台经济开发区,4,130500
  742 +130581,南宫市,4,130500
  743 +130582,沙河市,4,130500
  744 +130602,竞秀区,4,130600
  745 +130606,莲池区,4,130600
  746 +130607,满城区,4,130600
  747 +130608,清苑区,4,130600
  748 +130609,徐水区,4,130600
  749 +130623,涞水县,4,130600
  750 +130624,阜平县,4,130600
  751 +130626,定兴县,4,130600
  752 +130627,唐县,4,130600
  753 +130628,高阳县,4,130600
  754 +130629,容城县,4,130600
  755 +130630,涞源县,4,130600
  756 +130631,望都县,4,130600
  757 +130632,安新县,4,130600
  758 +130633,易县,4,130600
  759 +130634,曲阳县,4,130600
  760 +130635,蠡县,4,130600
  761 +130636,顺平县,4,130600
  762 +130637,博野县,4,130600
  763 +130638,雄县,4,130600
  764 +130671,保定高新技术产业开发区,4,130600
  765 +130672,保定白沟新城,4,130600
  766 +130681,涿州市,4,130600
  767 +130682,定州市,4,130600
  768 +130683,安国市,4,130600
  769 +130684,高碑店市,4,130600
  770 +130702,桥东区,4,130700
  771 +130703,桥西区,4,130700
  772 +130705,宣化区,4,130700
  773 +130706,下花园区,4,130700
  774 +130708,万全区,4,130700
  775 +130709,崇礼区,4,130700
  776 +130722,张北县,4,130700
  777 +130723,康保县,4,130700
  778 +130724,沽源县,4,130700
  779 +130725,尚义县,4,130700
  780 +130726,蔚县,4,130700
  781 +130727,阳原县,4,130700
  782 +130728,怀安县,4,130700
  783 +130730,怀来县,4,130700
  784 +130731,涿鹿县,4,130700
  785 +130732,赤城县,4,130700
  786 +130771,张家口经济开发区,4,130700
  787 +130772,张家口市察北管理区,4,130700
  788 +130773,张家口市塞北管理区,4,130700
  789 +130802,双桥区,4,130800
  790 +130803,双滦区,4,130800
  791 +130804,鹰手营子矿区,4,130800
  792 +130821,承德县,4,130800
  793 +130822,兴隆县,4,130800
  794 +130824,滦平县,4,130800
  795 +130825,隆化县,4,130800
  796 +130826,丰宁满族自治县,4,130800
  797 +130827,宽城满族自治县,4,130800
  798 +130828,围场满族蒙古族自治县,4,130800
  799 +130871,承德高新技术产业开发区,4,130800
  800 +130881,平泉市,4,130800
  801 +130902,新华区,4,130900
  802 +130903,运河区,4,130900
  803 +130921,沧县,4,130900
  804 +130922,青县,4,130900
  805 +130923,东光县,4,130900
  806 +130924,海兴县,4,130900
  807 +130925,盐山县,4,130900
  808 +130926,肃宁县,4,130900
  809 +130927,南皮县,4,130900
  810 +130928,吴桥县,4,130900
  811 +130929,献县,4,130900
  812 +130930,孟村回族自治县,4,130900
  813 +130971,河北沧州经济开发区,4,130900
  814 +130972,沧州高新技术产业开发区,4,130900
  815 +130973,沧州渤海新区,4,130900
  816 +130981,泊头市,4,130900
  817 +130982,任丘市,4,130900
  818 +130983,黄骅市,4,130900
  819 +130984,河间市,4,130900
  820 +131002,安次区,4,131000
  821 +131003,广阳区,4,131000
  822 +131022,固安县,4,131000
  823 +131023,永清县,4,131000
  824 +131024,香河县,4,131000
  825 +131025,大城县,4,131000
  826 +131026,文安县,4,131000
  827 +131028,大厂回族自治县,4,131000
  828 +131071,廊坊经济技术开发区,4,131000
  829 +131081,霸州市,4,131000
  830 +131082,三河市,4,131000
  831 +131102,桃城区,4,131100
  832 +131103,冀州区,4,131100
  833 +131121,枣强县,4,131100
  834 +131122,武邑县,4,131100
  835 +131123,武强县,4,131100
  836 +131124,饶阳县,4,131100
  837 +131125,安平县,4,131100
  838 +131126,故城县,4,131100
  839 +131127,景县,4,131100
  840 +131128,阜城县,4,131100
  841 +131171,河北衡水高新技术产业开发区,4,131100
  842 +131172,衡水滨湖新区,4,131100
  843 +131182,深州市,4,131100
  844 +140105,小店区,4,140100
  845 +140106,迎泽区,4,140100
  846 +140107,杏花岭区,4,140100
  847 +140108,尖草坪区,4,140100
  848 +140109,万柏林区,4,140100
  849 +140110,晋源区,4,140100
  850 +140121,清徐县,4,140100
  851 +140122,阳曲县,4,140100
  852 +140123,娄烦县,4,140100
  853 +140171,山西转型综合改革示范区,4,140100
  854 +140181,古交市,4,140100
  855 +140212,新荣区,4,140200
  856 +140213,平城区,4,140200
  857 +140214,云冈区,4,140200
  858 +140215,云州区,4,140200
  859 +140221,阳高县,4,140200
  860 +140222,天镇县,4,140200
  861 +140223,广灵县,4,140200
  862 +140224,灵丘县,4,140200
  863 +140225,浑源县,4,140200
  864 +140226,左云县,4,140200
  865 +140271,山西大同经济开发区,4,140200
  866 +140302,城区,4,140300
  867 +140303,矿区,4,140300
  868 +140311,郊区,4,140300
  869 +140321,平定县,4,140300
  870 +140322,盂县,4,140300
  871 +140403,潞州区,4,140400
  872 +140404,上党区,4,140400
  873 +140405,屯留区,4,140400
  874 +140406,潞城区,4,140400
  875 +140423,襄垣县,4,140400
  876 +140425,平顺县,4,140400
  877 +140426,黎城县,4,140400
  878 +140427,壶关县,4,140400
  879 +140428,长子县,4,140400
  880 +140429,武乡县,4,140400
  881 +140430,沁县,4,140400
  882 +140431,沁源县,4,140400
  883 +140471,山西长治高新技术产业园区,4,140400
  884 +140502,城区,4,140500
  885 +140521,沁水县,4,140500
  886 +140522,阳城县,4,140500
  887 +140524,陵川县,4,140500
  888 +140525,泽州县,4,140500
  889 +140581,高平市,4,140500
  890 +140602,朔城区,4,140600
  891 +140603,平鲁区,4,140600
  892 +140621,山阴县,4,140600
  893 +140622,应县,4,140600
  894 +140623,右玉县,4,140600
  895 +140671,山西朔州经济开发区,4,140600
  896 +140681,怀仁市,4,140600
  897 +140702,榆次区,4,140700
  898 +140703,太谷区,4,140700
  899 +140721,榆社县,4,140700
  900 +140722,左权县,4,140700
  901 +140723,和顺县,4,140700
  902 +140724,昔阳县,4,140700
  903 +140725,寿阳县,4,140700
  904 +140727,祁县,4,140700
  905 +140728,平遥县,4,140700
  906 +140729,灵石县,4,140700
  907 +140781,介休市,4,140700
  908 +140802,盐湖区,4,140800
  909 +140821,临猗县,4,140800
  910 +140822,万荣县,4,140800
  911 +140823,闻喜县,4,140800
  912 +140824,稷山县,4,140800
  913 +140825,新绛县,4,140800
  914 +140826,绛县,4,140800
  915 +140827,垣曲县,4,140800
  916 +140828,夏县,4,140800
  917 +140829,平陆县,4,140800
  918 +140830,芮城县,4,140800
  919 +140881,永济市,4,140800
  920 +140882,河津市,4,140800
  921 +140902,忻府区,4,140900
  922 +140921,定襄县,4,140900
  923 +140922,五台县,4,140900
  924 +140923,代县,4,140900
  925 +140924,繁峙县,4,140900
  926 +140925,宁武县,4,140900
  927 +140926,静乐县,4,140900
  928 +140927,神池县,4,140900
  929 +140928,五寨县,4,140900
  930 +140929,岢岚县,4,140900
  931 +140930,河曲县,4,140900
  932 +140931,保德县,4,140900
  933 +140932,偏关县,4,140900
  934 +140971,五台山风景名胜区,4,140900
  935 +140981,原平市,4,140900
  936 +141002,尧都区,4,141000
  937 +141021,曲沃县,4,141000
  938 +141022,翼城县,4,141000
  939 +141023,襄汾县,4,141000
  940 +141024,洪洞县,4,141000
  941 +141025,古县,4,141000
  942 +141026,安泽县,4,141000
  943 +141027,浮山县,4,141000
  944 +141028,吉县,4,141000
  945 +141029,乡宁县,4,141000
  946 +141030,大宁县,4,141000
  947 +141031,隰县,4,141000
  948 +141032,永和县,4,141000
  949 +141033,蒲县,4,141000
  950 +141034,汾西县,4,141000
  951 +141081,侯马市,4,141000
  952 +141082,霍州市,4,141000
  953 +141102,离石区,4,141100
  954 +141121,文水县,4,141100
  955 +141122,交城县,4,141100
  956 +141123,兴县,4,141100
  957 +141124,临县,4,141100
  958 +141125,柳林县,4,141100
  959 +141126,石楼县,4,141100
  960 +141127,岚县,4,141100
  961 +141128,方山县,4,141100
  962 +141129,中阳县,4,141100
  963 +141130,交口县,4,141100
  964 +141181,孝义市,4,141100
  965 +141182,汾阳市,4,141100
  966 +150102,新城区,4,150100
  967 +150103,回民区,4,150100
  968 +150104,玉泉区,4,150100
  969 +150105,赛罕区,4,150100
  970 +150121,土默特左旗,4,150100
  971 +150122,托克托县,4,150100
  972 +150123,和林格尔县,4,150100
  973 +150124,清水河县,4,150100
  974 +150125,武川县,4,150100
  975 +150172,呼和浩特经济技术开发区,4,150100
  976 +150202,东河区,4,150200
  977 +150203,昆都仑区,4,150200
  978 +150204,青山区,4,150200
  979 +150205,石拐区,4,150200
  980 +150206,白云鄂博矿区,4,150200
  981 +150207,九原区,4,150200
  982 +150221,土默特右旗,4,150200
  983 +150222,固阳县,4,150200
  984 +150223,达尔罕茂明安联合旗,4,150200
  985 +150271,包头稀土高新技术产业开发区,4,150200
  986 +150302,海勃湾区,4,150300
  987 +150303,海南区,4,150300
  988 +150304,乌达区,4,150300
  989 +150402,红山区,4,150400
  990 +150403,元宝山区,4,150400
  991 +150404,松山区,4,150400
  992 +150421,阿鲁科尔沁旗,4,150400
  993 +150422,巴林左旗,4,150400
  994 +150423,巴林右旗,4,150400
  995 +150424,林西县,4,150400
  996 +150425,克什克腾旗,4,150400
  997 +150426,翁牛特旗,4,150400
  998 +150428,喀喇沁旗,4,150400
  999 +150429,宁城县,4,150400
  1000 +150430,敖汉旗,4,150400
  1001 +150502,科尔沁区,4,150500
  1002 +150521,科尔沁左翼中旗,4,150500
  1003 +150522,科尔沁左翼后旗,4,150500
  1004 +150523,开鲁县,4,150500
  1005 +150524,库伦旗,4,150500
  1006 +150525,奈曼旗,4,150500
  1007 +150526,扎鲁特旗,4,150500
  1008 +150571,通辽经济技术开发区,4,150500
  1009 +150581,霍林郭勒市,4,150500
  1010 +150602,东胜区,4,150600
  1011 +150603,康巴什区,4,150600
  1012 +150621,达拉特旗,4,150600
  1013 +150622,准格尔旗,4,150600
  1014 +150623,鄂托克前旗,4,150600
  1015 +150624,鄂托克旗,4,150600
  1016 +150625,杭锦旗,4,150600
  1017 +150626,乌审旗,4,150600
  1018 +150627,伊金霍洛旗,4,150600
  1019 +150702,海拉尔区,4,150700
  1020 +150703,扎赉诺尔区,4,150700
  1021 +150721,阿荣旗,4,150700
  1022 +150722,莫力达瓦达斡尔族自治旗,4,150700
  1023 +150723,鄂伦春自治旗,4,150700
  1024 +150724,鄂温克族自治旗,4,150700
  1025 +150725,陈巴尔虎旗,4,150700
  1026 +150726,新巴尔虎左旗,4,150700
  1027 +150727,新巴尔虎右旗,4,150700
  1028 +150781,满洲里市,4,150700
  1029 +150782,牙克石市,4,150700
  1030 +150783,扎兰屯市,4,150700
  1031 +150784,额尔古纳市,4,150700
  1032 +150785,根河市,4,150700
  1033 +150802,临河区,4,150800
  1034 +150821,五原县,4,150800
  1035 +150822,磴口县,4,150800
  1036 +150823,乌拉特前旗,4,150800
  1037 +150824,乌拉特中旗,4,150800
  1038 +150825,乌拉特后旗,4,150800
  1039 +150826,杭锦后旗,4,150800
  1040 +150902,集宁区,4,150900
  1041 +150921,卓资县,4,150900
  1042 +150922,化德县,4,150900
  1043 +150923,商都县,4,150900
  1044 +150924,兴和县,4,150900
  1045 +150925,凉城县,4,150900
  1046 +150926,察哈尔右翼前旗,4,150900
  1047 +150927,察哈尔右翼中旗,4,150900
  1048 +150928,察哈尔右翼后旗,4,150900
  1049 +150929,四子王旗,4,150900
  1050 +150981,丰镇市,4,150900
  1051 +152201,乌兰浩特市,4,152200
  1052 +152202,阿尔山市,4,152200
  1053 +152221,科尔沁右翼前旗,4,152200
  1054 +152222,科尔沁右翼中旗,4,152200
  1055 +152223,扎赉特旗,4,152200
  1056 +152224,突泉县,4,152200
  1057 +152501,二连浩特市,4,152500
  1058 +152502,锡林浩特市,4,152500
  1059 +152522,阿巴嘎旗,4,152500
  1060 +152523,苏尼特左旗,4,152500
  1061 +152524,苏尼特右旗,4,152500
  1062 +152525,东乌珠穆沁旗,4,152500
  1063 +152526,西乌珠穆沁旗,4,152500
  1064 +152527,太仆寺旗,4,152500
  1065 +152528,镶黄旗,4,152500
  1066 +152529,正镶白旗,4,152500
  1067 +152530,正蓝旗,4,152500
  1068 +152531,多伦县,4,152500
  1069 +152571,乌拉盖管委会,4,152500
  1070 +152921,阿拉善左旗,4,152900
  1071 +152922,阿拉善右旗,4,152900
  1072 +152923,额济纳旗,4,152900
  1073 +152971,内蒙古阿拉善高新技术产业开发区,4,152900
  1074 +210102,和平区,4,210100
  1075 +210103,沈河区,4,210100
  1076 +210104,大东区,4,210100
  1077 +210105,皇姑区,4,210100
  1078 +210106,铁西区,4,210100
  1079 +210111,苏家屯区,4,210100
  1080 +210112,浑南区,4,210100
  1081 +210113,沈北新区,4,210100
  1082 +210114,于洪区,4,210100
  1083 +210115,辽中区,4,210100
  1084 +210123,康平县,4,210100
  1085 +210124,法库县,4,210100
  1086 +210181,新民市,4,210100
  1087 +210202,中山区,4,210200
  1088 +210203,西岗区,4,210200
  1089 +210204,沙河口区,4,210200
  1090 +210211,甘井子区,4,210200
  1091 +210212,旅顺口区,4,210200
  1092 +210213,金州区,4,210200
  1093 +210214,普兰店区,4,210200
  1094 +210224,长海县,4,210200
  1095 +210281,瓦房店市,4,210200
  1096 +210283,庄河市,4,210200
  1097 +210302,铁东区,4,210300
  1098 +210303,铁西区,4,210300
  1099 +210304,立山区,4,210300
  1100 +210311,千山区,4,210300
  1101 +210321,台安县,4,210300
  1102 +210323,岫岩满族自治县,4,210300
  1103 +210381,海城市,4,210300
  1104 +210402,新抚区,4,210400
  1105 +210403,东洲区,4,210400
  1106 +210404,望花区,4,210400
  1107 +210411,顺城区,4,210400
  1108 +210421,抚顺县,4,210400
  1109 +210422,新宾满族自治县,4,210400
  1110 +210423,清原满族自治县,4,210400
  1111 +210502,平山区,4,210500
  1112 +210503,溪湖区,4,210500
  1113 +210504,明山区,4,210500
  1114 +210505,南芬区,4,210500
  1115 +210521,本溪满族自治县,4,210500
  1116 +210522,桓仁满族自治县,4,210500
  1117 +210602,元宝区,4,210600
  1118 +210603,振兴区,4,210600
  1119 +210604,振安区,4,210600
  1120 +210624,宽甸满族自治县,4,210600
  1121 +210681,东港市,4,210600
  1122 +210682,凤城市,4,210600
  1123 +210702,古塔区,4,210700
  1124 +210703,凌河区,4,210700
  1125 +210711,太和区,4,210700
  1126 +210726,黑山县,4,210700
  1127 +210727,义县,4,210700
  1128 +210781,凌海市,4,210700
  1129 +210782,北镇市,4,210700
  1130 +210802,站前区,4,210800
  1131 +210803,西市区,4,210800
  1132 +210804,鲅鱼圈区,4,210800
  1133 +210811,老边区,4,210800
  1134 +210881,盖州市,4,210800
  1135 +210882,大石桥市,4,210800
  1136 +210902,海州区,4,210900
  1137 +210903,新邱区,4,210900
  1138 +210904,太平区,4,210900
  1139 +210905,清河门区,4,210900
  1140 +210911,细河区,4,210900
  1141 +210921,阜新蒙古族自治县,4,210900
  1142 +210922,彰武县,4,210900
  1143 +211002,白塔区,4,211000
  1144 +211003,文圣区,4,211000
  1145 +211004,宏伟区,4,211000
  1146 +211005,弓长岭区,4,211000
  1147 +211011,太子河区,4,211000
  1148 +211021,辽阳县,4,211000
  1149 +211081,灯塔市,4,211000
  1150 +211102,双台子区,4,211100
  1151 +211103,兴隆台区,4,211100
  1152 +211104,大洼区,4,211100
  1153 +211122,盘山县,4,211100
  1154 +211202,银州区,4,211200
  1155 +211204,清河区,4,211200
  1156 +211221,铁岭县,4,211200
  1157 +211223,西丰县,4,211200
  1158 +211224,昌图县,4,211200
  1159 +211281,调兵山市,4,211200
  1160 +211282,开原市,4,211200
  1161 +211302,双塔区,4,211300
  1162 +211303,龙城区,4,211300
  1163 +211321,朝阳县,4,211300
  1164 +211322,建平县,4,211300
  1165 +211324,喀喇沁左翼蒙古族自治县,4,211300
  1166 +211381,北票市,4,211300
  1167 +211382,凌源市,4,211300
  1168 +211402,连山区,4,211400
  1169 +211403,龙港区,4,211400
  1170 +211404,南票区,4,211400
  1171 +211421,绥中县,4,211400
  1172 +211422,建昌县,4,211400
  1173 +211481,兴城市,4,211400
  1174 +220102,南关区,4,220100
  1175 +220103,宽城区,4,220100
  1176 +220104,朝阳区,4,220100
  1177 +220105,二道区,4,220100
  1178 +220106,绿园区,4,220100
  1179 +220112,双阳区,4,220100
  1180 +220113,九台区,4,220100
  1181 +220122,农安县,4,220100
  1182 +220171,长春经济技术开发区,4,220100
  1183 +220172,长春净月高新技术产业开发区,4,220100
  1184 +220173,长春高新技术产业开发区,4,220100
  1185 +220174,长春汽车经济技术开发区,4,220100
  1186 +220182,榆树市,4,220100
  1187 +220183,德惠市,4,220100
  1188 +220184,公主岭市,4,220100
  1189 +220202,昌邑区,4,220200
  1190 +220203,龙潭区,4,220200
  1191 +220204,船营区,4,220200
  1192 +220211,丰满区,4,220200
  1193 +220221,永吉县,4,220200
  1194 +220271,吉林经济开发区,4,220200
  1195 +220272,吉林高新技术产业开发区,4,220200
  1196 +220273,吉林中国新加坡食品区,4,220200
  1197 +220281,蛟河市,4,220200
  1198 +220282,桦甸市,4,220200
  1199 +220283,舒兰市,4,220200
  1200 +220284,磐石市,4,220200
  1201 +220302,铁西区,4,220300
  1202 +220303,铁东区,4,220300
  1203 +220322,梨树县,4,220300
  1204 +220323,伊通满族自治县,4,220300
  1205 +220382,双辽市,4,220300
  1206 +220402,龙山区,4,220400
  1207 +220403,西安区,4,220400
  1208 +220421,东丰县,4,220400
  1209 +220422,东辽县,4,220400
  1210 +220502,东昌区,4,220500
  1211 +220503,二道江区,4,220500
  1212 +220521,通化县,4,220500
  1213 +220523,辉南县,4,220500
  1214 +220524,柳河县,4,220500
  1215 +220581,梅河口市,4,220500
  1216 +220582,集安市,4,220500
  1217 +220602,浑江区,4,220600
  1218 +220605,江源区,4,220600
  1219 +220621,抚松县,4,220600
  1220 +220622,靖宇县,4,220600
  1221 +220623,长白朝鲜族自治县,4,220600
  1222 +220681,临江市,4,220600
  1223 +220702,宁江区,4,220700
  1224 +220721,前郭尔罗斯蒙古族自治县,4,220700
  1225 +220722,长岭县,4,220700
  1226 +220723,乾安县,4,220700
  1227 +220771,吉林松原经济开发区,4,220700
  1228 +220781,扶余市,4,220700
  1229 +220802,洮北区,4,220800
  1230 +220821,镇赉县,4,220800
  1231 +220822,通榆县,4,220800
  1232 +220871,吉林白城经济开发区,4,220800
  1233 +220881,洮南市,4,220800
  1234 +220882,大安市,4,220800
  1235 +222401,延吉市,4,222400
  1236 +222402,图们市,4,222400
  1237 +222403,敦化市,4,222400
  1238 +222404,珲春市,4,222400
  1239 +222405,龙井市,4,222400
  1240 +222406,和龙市,4,222400
  1241 +222424,汪清县,4,222400
  1242 +222426,安图县,4,222400
  1243 +230102,道里区,4,230100
  1244 +230103,南岗区,4,230100
  1245 +230104,道外区,4,230100
  1246 +230108,平房区,4,230100
  1247 +230109,松北区,4,230100
  1248 +230110,香坊区,4,230100
  1249 +230111,呼兰区,4,230100
  1250 +230112,阿城区,4,230100
  1251 +230113,双城区,4,230100
  1252 +230123,依兰县,4,230100
  1253 +230124,方正县,4,230100
  1254 +230125,宾县,4,230100
  1255 +230126,巴彦县,4,230100
  1256 +230127,木兰县,4,230100
  1257 +230128,通河县,4,230100
  1258 +230129,延寿县,4,230100
  1259 +230183,尚志市,4,230100
  1260 +230184,五常市,4,230100
  1261 +230202,龙沙区,4,230200
  1262 +230203,建华区,4,230200
  1263 +230204,铁锋区,4,230200
  1264 +230205,昂昂溪区,4,230200
  1265 +230206,富拉尔基区,4,230200
  1266 +230207,碾子山区,4,230200
  1267 +230208,梅里斯达斡尔族区,4,230200
  1268 +230221,龙江县,4,230200
  1269 +230223,依安县,4,230200
  1270 +230224,泰来县,4,230200
  1271 +230225,甘南县,4,230200
  1272 +230227,富裕县,4,230200
  1273 +230229,克山县,4,230200
  1274 +230230,克东县,4,230200
  1275 +230231,拜泉县,4,230200
  1276 +230281,讷河市,4,230200
  1277 +230302,鸡冠区,4,230300
  1278 +230303,恒山区,4,230300
  1279 +230304,滴道区,4,230300
  1280 +230305,梨树区,4,230300
  1281 +230306,城子河区,4,230300
  1282 +230307,麻山区,4,230300
  1283 +230321,鸡东县,4,230300
  1284 +230381,虎林市,4,230300
  1285 +230382,密山市,4,230300
  1286 +230402,向阳区,4,230400
  1287 +230403,工农区,4,230400
  1288 +230404,南山区,4,230400
  1289 +230405,兴安区,4,230400
  1290 +230406,东山区,4,230400
  1291 +230407,兴山区,4,230400
  1292 +230421,萝北县,4,230400
  1293 +230422,绥滨县,4,230400
  1294 +230502,尖山区,4,230500
  1295 +230503,岭东区,4,230500
  1296 +230505,四方台区,4,230500
  1297 +230506,宝山区,4,230500
  1298 +230521,集贤县,4,230500
  1299 +230522,友谊县,4,230500
  1300 +230523,宝清县,4,230500
  1301 +230524,饶河县,4,230500
  1302 +230602,萨尔图区,4,230600
  1303 +230603,龙凤区,4,230600
  1304 +230604,让胡路区,4,230600
  1305 +230605,红岗区,4,230600
  1306 +230606,大同区,4,230600
  1307 +230621,肇州县,4,230600
  1308 +230622,肇源县,4,230600
  1309 +230623,林甸县,4,230600
  1310 +230624,杜尔伯特蒙古族自治县,4,230600
  1311 +230671,大庆高新技术产业开发区,4,230600
  1312 +230717,伊美区,4,230700
  1313 +230718,乌翠区,4,230700
  1314 +230719,友好区,4,230700
  1315 +230722,嘉荫县,4,230700
  1316 +230723,汤旺县,4,230700
  1317 +230724,丰林县,4,230700
  1318 +230725,大箐山县,4,230700
  1319 +230726,南岔县,4,230700
  1320 +230751,金林区,4,230700
  1321 +230781,铁力市,4,230700
  1322 +230803,向阳区,4,230800
  1323 +230804,前进区,4,230800
  1324 +230805,东风区,4,230800
  1325 +230811,郊区,4,230800
  1326 +230822,桦南县,4,230800
  1327 +230826,桦川县,4,230800
  1328 +230828,汤原县,4,230800
  1329 +230881,同江市,4,230800
  1330 +230882,富锦市,4,230800
  1331 +230883,抚远市,4,230800
  1332 +230902,新兴区,4,230900
  1333 +230903,桃山区,4,230900
  1334 +230904,茄子河区,4,230900
  1335 +230921,勃利县,4,230900
  1336 +231002,东安区,4,231000
  1337 +231003,阳明区,4,231000
  1338 +231004,爱民区,4,231000
  1339 +231005,西安区,4,231000
  1340 +231025,林口县,4,231000
  1341 +231071,牡丹江经济技术开发区,4,231000
  1342 +231081,绥芬河市,4,231000
  1343 +231083,海林市,4,231000
  1344 +231084,宁安市,4,231000
  1345 +231085,穆棱市,4,231000
  1346 +231086,东宁市,4,231000
  1347 +231102,爱辉区,4,231100
  1348 +231123,逊克县,4,231100
  1349 +231124,孙吴县,4,231100
  1350 +231181,北安市,4,231100
  1351 +231182,五大连池市,4,231100
  1352 +231183,嫩江市,4,231100
  1353 +231202,北林区,4,231200
  1354 +231221,望奎县,4,231200
  1355 +231222,兰西县,4,231200
  1356 +231223,青冈县,4,231200
  1357 +231224,庆安县,4,231200
  1358 +231225,明水县,4,231200
  1359 +231226,绥棱县,4,231200
  1360 +231281,安达市,4,231200
  1361 +231282,肇东市,4,231200
  1362 +231283,海伦市,4,231200
  1363 +232701,漠河市,4,232700
  1364 +232721,呼玛县,4,232700
  1365 +232722,塔河县,4,232700
  1366 +232761,加格达奇区,4,232700
  1367 +232762,松岭区,4,232700
  1368 +232763,新林区,4,232700
  1369 +232764,呼中区,4,232700
  1370 +310101,黄浦区,4,310100
  1371 +310104,徐汇区,4,310100
  1372 +310105,长宁区,4,310100
  1373 +310106,静安区,4,310100
  1374 +310107,普陀区,4,310100
  1375 +310109,虹口区,4,310100
  1376 +310110,杨浦区,4,310100
  1377 +310112,闵行区,4,310100
  1378 +310113,宝山区,4,310100
  1379 +310114,嘉定区,4,310100
  1380 +310115,浦东新区,4,310100
  1381 +310116,金山区,4,310100
  1382 +310117,松江区,4,310100
  1383 +310118,青浦区,4,310100
  1384 +310120,奉贤区,4,310100
  1385 +310151,崇明区,4,310100
  1386 +320102,玄武区,4,320100
  1387 +320104,秦淮区,4,320100
  1388 +320105,建邺区,4,320100
  1389 +320106,鼓楼区,4,320100
  1390 +320111,浦口区,4,320100
  1391 +320113,栖霞区,4,320100
  1392 +320114,雨花台区,4,320100
  1393 +320115,江宁区,4,320100
  1394 +320116,六合区,4,320100
  1395 +320117,溧水区,4,320100
  1396 +320118,高淳区,4,320100
  1397 +320205,锡山区,4,320200
  1398 +320206,惠山区,4,320200
  1399 +320211,滨湖区,4,320200
  1400 +320213,梁溪区,4,320200
  1401 +320214,新吴区,4,320200
  1402 +320281,江阴市,4,320200
  1403 +320282,宜兴市,4,320200
  1404 +320302,鼓楼区,4,320300
  1405 +320303,云龙区,4,320300
  1406 +320305,贾汪区,4,320300
  1407 +320311,泉山区,4,320300
  1408 +320312,铜山区,4,320300
  1409 +320321,丰县,4,320300
  1410 +320322,沛县,4,320300
  1411 +320324,睢宁县,4,320300
  1412 +320371,徐州经济技术开发区,4,320300
  1413 +320381,新沂市,4,320300
  1414 +320382,邳州市,4,320300
  1415 +320402,天宁区,4,320400
  1416 +320404,钟楼区,4,320400
  1417 +320411,新北区,4,320400
  1418 +320412,武进区,4,320400
  1419 +320413,金坛区,4,320400
  1420 +320481,溧阳市,4,320400
  1421 +320505,虎丘区,4,320500
  1422 +320506,吴中区,4,320500
  1423 +320507,相城区,4,320500
  1424 +320508,姑苏区,4,320500
  1425 +320509,吴江区,4,320500
  1426 +320571,苏州工业园区,4,320500
  1427 +320581,常熟市,4,320500
  1428 +320582,张家港市,4,320500
  1429 +320583,昆山市,4,320500
  1430 +320585,太仓市,4,320500
  1431 +320612,通州区,4,320600
  1432 +320613,崇川区,4,320600
  1433 +320614,海门区,4,320600
  1434 +320623,如东县,4,320600
  1435 +320671,南通经济技术开发区,4,320600
  1436 +320681,启东市,4,320600
  1437 +320682,如皋市,4,320600
  1438 +320685,海安市,4,320600
  1439 +320703,连云区,4,320700
  1440 +320706,海州区,4,320700
  1441 +320707,赣榆区,4,320700
  1442 +320722,东海县,4,320700
  1443 +320723,灌云县,4,320700
  1444 +320724,灌南县,4,320700
  1445 +320771,连云港经济技术开发区,4,320700
  1446 +320772,连云港高新技术产业开发区,4,320700
  1447 +320803,淮安区,4,320800
  1448 +320804,淮阴区,4,320800
  1449 +320812,清江浦区,4,320800
  1450 +320813,洪泽区,4,320800
  1451 +320826,涟水县,4,320800
  1452 +320830,盱眙县,4,320800
  1453 +320831,金湖县,4,320800
  1454 +320871,淮安经济技术开发区,4,320800
  1455 +320902,亭湖区,4,320900
  1456 +320903,盐都区,4,320900
  1457 +320904,大丰区,4,320900
  1458 +320921,响水县,4,320900
  1459 +320922,滨海县,4,320900
  1460 +320923,阜宁县,4,320900
  1461 +320924,射阳县,4,320900
  1462 +320925,建湖县,4,320900
  1463 +320971,盐城经济技术开发区,4,320900
  1464 +320981,东台市,4,320900
  1465 +321002,广陵区,4,321000
  1466 +321003,邗江区,4,321000
  1467 +321012,江都区,4,321000
  1468 +321023,宝应县,4,321000
  1469 +321071,扬州经济技术开发区,4,321000
  1470 +321081,仪征市,4,321000
  1471 +321084,高邮市,4,321000
  1472 +321102,京口区,4,321100
  1473 +321111,润州区,4,321100
  1474 +321112,丹徒区,4,321100
  1475 +321171,镇江新区,4,321100
  1476 +321181,丹阳市,4,321100
  1477 +321182,扬中市,4,321100
  1478 +321183,句容市,4,321100
  1479 +321202,海陵区,4,321200
  1480 +321203,高港区,4,321200
  1481 +321204,姜堰区,4,321200
  1482 +321271,泰州医药高新技术产业开发区,4,321200
  1483 +321281,兴化市,4,321200
  1484 +321282,靖江市,4,321200
  1485 +321283,泰兴市,4,321200
  1486 +321302,宿城区,4,321300
  1487 +321311,宿豫区,4,321300
  1488 +321322,沭阳县,4,321300
  1489 +321323,泗阳县,4,321300
  1490 +321324,泗洪县,4,321300
  1491 +321371,宿迁经济技术开发区,4,321300
  1492 +330102,上城区,4,330100
  1493 +330105,拱墅区,4,330100
  1494 +330106,西湖区,4,330100
  1495 +330108,滨江区,4,330100
  1496 +330109,萧山区,4,330100
  1497 +330110,余杭区,4,330100
  1498 +330111,富阳区,4,330100
  1499 +330112,临安区,4,330100
  1500 +330113,临平区,4,330100
  1501 +330114,钱塘区,4,330100
  1502 +330122,桐庐县,4,330100
  1503 +330127,淳安县,4,330100
  1504 +330182,建德市,4,330100
  1505 +330203,海曙区,4,330200
  1506 +330205,江北区,4,330200
  1507 +330206,北仑区,4,330200
  1508 +330211,镇海区,4,330200
  1509 +330212,鄞州区,4,330200
  1510 +330213,奉化区,4,330200
  1511 +330225,象山县,4,330200
  1512 +330226,宁海县,4,330200
  1513 +330281,余姚市,4,330200
  1514 +330282,慈溪市,4,330200
  1515 +330302,鹿城区,4,330300
  1516 +330303,龙湾区,4,330300
  1517 +330304,瓯海区,4,330300
  1518 +330305,洞头区,4,330300
  1519 +330324,永嘉县,4,330300
  1520 +330326,平阳县,4,330300
  1521 +330327,苍南县,4,330300
  1522 +330328,文成县,4,330300
  1523 +330329,泰顺县,4,330300
  1524 +330371,温州经济技术开发区,4,330300
  1525 +330381,瑞安市,4,330300
  1526 +330382,乐清市,4,330300
  1527 +330383,龙港市,4,330300
  1528 +330402,南湖区,4,330400
  1529 +330411,秀洲区,4,330400
  1530 +330421,嘉善县,4,330400
  1531 +330424,海盐县,4,330400
  1532 +330481,海宁市,4,330400
  1533 +330482,平湖市,4,330400
  1534 +330483,桐乡市,4,330400
  1535 +330502,吴兴区,4,330500
  1536 +330503,南浔区,4,330500
  1537 +330521,德清县,4,330500
  1538 +330522,长兴县,4,330500
  1539 +330523,安吉县,4,330500
  1540 +330602,越城区,4,330600
  1541 +330603,柯桥区,4,330600
  1542 +330604,上虞区,4,330600
  1543 +330624,新昌县,4,330600
  1544 +330681,诸暨市,4,330600
  1545 +330683,嵊州市,4,330600
  1546 +330702,婺城区,4,330700
  1547 +330703,金东区,4,330700
  1548 +330723,武义县,4,330700
  1549 +330726,浦江县,4,330700
  1550 +330727,磐安县,4,330700
  1551 +330781,兰溪市,4,330700
  1552 +330782,义乌市,4,330700
  1553 +330783,东阳市,4,330700
  1554 +330784,永康市,4,330700
  1555 +330802,柯城区,4,330800
  1556 +330803,衢江区,4,330800
  1557 +330822,常山县,4,330800
  1558 +330824,开化县,4,330800
  1559 +330825,龙游县,4,330800
  1560 +330881,江山市,4,330800
  1561 +330902,定海区,4,330900
  1562 +330903,普陀区,4,330900
  1563 +330921,岱山县,4,330900
  1564 +330922,嵊泗县,4,330900
  1565 +331002,椒江区,4,331000
  1566 +331003,黄岩区,4,331000
  1567 +331004,路桥区,4,331000
  1568 +331022,三门县,4,331000
  1569 +331023,天台县,4,331000
  1570 +331024,仙居县,4,331000
  1571 +331081,温岭市,4,331000
  1572 +331082,临海市,4,331000
  1573 +331083,玉环市,4,331000
  1574 +331102,莲都区,4,331100
  1575 +331121,青田县,4,331100
  1576 +331122,缙云县,4,331100
  1577 +331123,遂昌县,4,331100
  1578 +331124,松阳县,4,331100
  1579 +331125,云和县,4,331100
  1580 +331126,庆元县,4,331100
  1581 +331127,景宁畲族自治县,4,331100
  1582 +331181,龙泉市,4,331100
  1583 +340102,瑶海区,4,340100
  1584 +340103,庐阳区,4,340100
  1585 +340104,蜀山区,4,340100
  1586 +340111,包河区,4,340100
  1587 +340121,长丰县,4,340100
  1588 +340122,肥东县,4,340100
  1589 +340123,肥西县,4,340100
  1590 +340124,庐江县,4,340100
  1591 +340171,合肥高新技术产业开发区,4,340100
  1592 +340172,合肥经济技术开发区,4,340100
  1593 +340173,合肥新站高新技术产业开发区,4,340100
  1594 +340181,巢湖市,4,340100
  1595 +340202,镜湖区,4,340200
  1596 +340207,鸠江区,4,340200
  1597 +340209,弋江区,4,340200
  1598 +340210,湾沚区,4,340200
  1599 +340212,繁昌区,4,340200
  1600 +340223,南陵县,4,340200
  1601 +340271,芜湖经济技术开发区,4,340200
  1602 +340272,安徽芜湖三山经济开发区,4,340200
  1603 +340281,无为市,4,340200
  1604 +340302,龙子湖区,4,340300
  1605 +340303,蚌山区,4,340300
  1606 +340304,禹会区,4,340300
  1607 +340311,淮上区,4,340300
  1608 +340321,怀远县,4,340300
  1609 +340322,五河县,4,340300
  1610 +340323,固镇县,4,340300
  1611 +340371,蚌埠市高新技术开发区,4,340300
  1612 +340372,蚌埠市经济开发区,4,340300
  1613 +340402,大通区,4,340400
  1614 +340403,田家庵区,4,340400
  1615 +340404,谢家集区,4,340400
  1616 +340405,八公山区,4,340400
  1617 +340406,潘集区,4,340400
  1618 +340421,凤台县,4,340400
  1619 +340422,寿县,4,340400
  1620 +340503,花山区,4,340500
  1621 +340504,雨山区,4,340500
  1622 +340506,博望区,4,340500
  1623 +340521,当涂县,4,340500
  1624 +340522,含山县,4,340500
  1625 +340523,和县,4,340500
  1626 +340602,杜集区,4,340600
  1627 +340603,相山区,4,340600
  1628 +340604,烈山区,4,340600
  1629 +340621,濉溪县,4,340600
  1630 +340705,铜官区,4,340700
  1631 +340706,义安区,4,340700
  1632 +340711,郊区,4,340700
  1633 +340722,枞阳县,4,340700
  1634 +340802,迎江区,4,340800
  1635 +340803,大观区,4,340800
  1636 +340811,宜秀区,4,340800
  1637 +340822,怀宁县,4,340800
  1638 +340825,太湖县,4,340800
  1639 +340826,宿松县,4,340800
  1640 +340827,望江县,4,340800
  1641 +340828,岳西县,4,340800
  1642 +340871,安徽安庆经济开发区,4,340800
  1643 +340881,桐城市,4,340800
  1644 +340882,潜山市,4,340800
  1645 +341002,屯溪区,4,341000
  1646 +341003,黄山区,4,341000
  1647 +341004,徽州区,4,341000
  1648 +341021,歙县,4,341000
  1649 +341022,休宁县,4,341000
  1650 +341023,黟县,4,341000
  1651 +341024,祁门县,4,341000
  1652 +341102,琅琊区,4,341100
  1653 +341103,南谯区,4,341100
  1654 +341122,来安县,4,341100
  1655 +341124,全椒县,4,341100
  1656 +341125,定远县,4,341100
  1657 +341126,凤阳县,4,341100
  1658 +341171,中新苏滁高新技术产业开发区,4,341100
  1659 +341172,滁州经济技术开发区,4,341100
  1660 +341181,天长市,4,341100
  1661 +341182,明光市,4,341100
  1662 +341202,颍州区,4,341200
  1663 +341203,颍东区,4,341200
  1664 +341204,颍泉区,4,341200
  1665 +341221,临泉县,4,341200
  1666 +341222,太和县,4,341200
  1667 +341225,阜南县,4,341200
  1668 +341226,颍上县,4,341200
  1669 +341271,阜阳合肥现代产业园区,4,341200
  1670 +341272,阜阳经济技术开发区,4,341200
  1671 +341282,界首市,4,341200
  1672 +341302,埇桥区,4,341300
  1673 +341321,砀山县,4,341300
  1674 +341322,萧县,4,341300
  1675 +341323,灵璧县,4,341300
  1676 +341324,泗县,4,341300
  1677 +341371,宿州马鞍山现代产业园区,4,341300
  1678 +341372,宿州经济技术开发区,4,341300
  1679 +341502,金安区,4,341500
  1680 +341503,裕安区,4,341500
  1681 +341504,叶集区,4,341500
  1682 +341522,霍邱县,4,341500
  1683 +341523,舒城县,4,341500
  1684 +341524,金寨县,4,341500
  1685 +341525,霍山县,4,341500
  1686 +341602,谯城区,4,341600
  1687 +341621,涡阳县,4,341600
  1688 +341622,蒙城县,4,341600
  1689 +341623,利辛县,4,341600
  1690 +341702,贵池区,4,341700
  1691 +341721,东至县,4,341700
  1692 +341722,石台县,4,341700
  1693 +341723,青阳县,4,341700
  1694 +341802,宣州区,4,341800
  1695 +341821,郎溪县,4,341800
  1696 +341823,泾县,4,341800
  1697 +341824,绩溪县,4,341800
  1698 +341825,旌德县,4,341800
  1699 +341871,宣城市经济开发区,4,341800
  1700 +341881,宁国市,4,341800
  1701 +341882,广德市,4,341800
  1702 +350102,鼓楼区,4,350100
  1703 +350103,台江区,4,350100
  1704 +350104,仓山区,4,350100
  1705 +350105,马尾区,4,350100
  1706 +350111,晋安区,4,350100
  1707 +350112,长乐区,4,350100
  1708 +350121,闽侯县,4,350100
  1709 +350122,连江县,4,350100
  1710 +350123,罗源县,4,350100
  1711 +350124,闽清县,4,350100
  1712 +350125,永泰县,4,350100
  1713 +350128,平潭县,4,350100
  1714 +350181,福清市,4,350100
  1715 +350203,思明区,4,350200
  1716 +350205,海沧区,4,350200
  1717 +350206,湖里区,4,350200
  1718 +350211,集美区,4,350200
  1719 +350212,同安区,4,350200
  1720 +350213,翔安区,4,350200
  1721 +350302,城厢区,4,350300
  1722 +350303,涵江区,4,350300
  1723 +350304,荔城区,4,350300
  1724 +350305,秀屿区,4,350300
  1725 +350322,仙游县,4,350300
  1726 +350404,三元区,4,350400
  1727 +350405,沙县区,4,350400
  1728 +350421,明溪县,4,350400
  1729 +350423,清流县,4,350400
  1730 +350424,宁化县,4,350400
  1731 +350425,大田县,4,350400
  1732 +350426,尤溪县,4,350400
  1733 +350428,将乐县,4,350400
  1734 +350429,泰宁县,4,350400
  1735 +350430,建宁县,4,350400
  1736 +350481,永安市,4,350400
  1737 +350502,鲤城区,4,350500
  1738 +350503,丰泽区,4,350500
  1739 +350504,洛江区,4,350500
  1740 +350505,泉港区,4,350500
  1741 +350521,惠安县,4,350500
  1742 +350524,安溪县,4,350500
  1743 +350525,永春县,4,350500
  1744 +350526,德化县,4,350500
  1745 +350527,金门县,4,350500
  1746 +350581,石狮市,4,350500
  1747 +350582,晋江市,4,350500
  1748 +350583,南安市,4,350500
  1749 +350602,芗城区,4,350600
  1750 +350603,龙文区,4,350600
  1751 +350604,龙海区,4,350600
  1752 +350605,长泰区,4,350600
  1753 +350622,云霄县,4,350600
  1754 +350623,漳浦县,4,350600
  1755 +350624,诏安县,4,350600
  1756 +350626,东山县,4,350600
  1757 +350627,南靖县,4,350600
  1758 +350628,平和县,4,350600
  1759 +350629,华安县,4,350600
  1760 +350702,延平区,4,350700
  1761 +350703,建阳区,4,350700
  1762 +350721,顺昌县,4,350700
  1763 +350722,浦城县,4,350700
  1764 +350723,光泽县,4,350700
  1765 +350724,松溪县,4,350700
  1766 +350725,政和县,4,350700
  1767 +350781,邵武市,4,350700
  1768 +350782,武夷山市,4,350700
  1769 +350783,建瓯市,4,350700
  1770 +350802,新罗区,4,350800
  1771 +350803,永定区,4,350800
  1772 +350821,长汀县,4,350800
  1773 +350823,上杭县,4,350800
  1774 +350824,武平县,4,350800
  1775 +350825,连城县,4,350800
  1776 +350881,漳平市,4,350800
  1777 +350902,蕉城区,4,350900
  1778 +350921,霞浦县,4,350900
  1779 +350922,古田县,4,350900
  1780 +350923,屏南县,4,350900
  1781 +350924,寿宁县,4,350900
  1782 +350925,周宁县,4,350900
  1783 +350926,柘荣县,4,350900
  1784 +350981,福安市,4,350900
  1785 +350982,福鼎市,4,350900
  1786 +360102,东湖区,4,360100
  1787 +360103,西湖区,4,360100
  1788 +360104,青云谱区,4,360100
  1789 +360111,青山湖区,4,360100
  1790 +360112,新建区,4,360100
  1791 +360113,红谷滩区,4,360100
  1792 +360121,南昌县,4,360100
  1793 +360123,安义县,4,360100
  1794 +360124,进贤县,4,360100
  1795 +360202,昌江区,4,360200
  1796 +360203,珠山区,4,360200
  1797 +360222,浮梁县,4,360200
  1798 +360281,乐平市,4,360200
  1799 +360302,安源区,4,360300
  1800 +360313,湘东区,4,360300
  1801 +360321,莲花县,4,360300
  1802 +360322,上栗县,4,360300
  1803 +360323,芦溪县,4,360300
  1804 +360402,濂溪区,4,360400
  1805 +360403,浔阳区,4,360400
  1806 +360404,柴桑区,4,360400
  1807 +360423,武宁县,4,360400
  1808 +360424,修水县,4,360400
  1809 +360425,永修县,4,360400
  1810 +360426,德安县,4,360400
  1811 +360428,都昌县,4,360400
  1812 +360429,湖口县,4,360400
  1813 +360430,彭泽县,4,360400
  1814 +360481,瑞昌市,4,360400
  1815 +360482,共青城市,4,360400
  1816 +360483,庐山市,4,360400
  1817 +360502,渝水区,4,360500
  1818 +360521,分宜县,4,360500
  1819 +360602,月湖区,4,360600
  1820 +360603,余江区,4,360600
  1821 +360681,贵溪市,4,360600
  1822 +360702,章贡区,4,360700
  1823 +360703,南康区,4,360700
  1824 +360704,赣县区,4,360700
  1825 +360722,信丰县,4,360700
  1826 +360723,大余县,4,360700
  1827 +360724,上犹县,4,360700
  1828 +360725,崇义县,4,360700
  1829 +360726,安远县,4,360700
  1830 +360728,定南县,4,360700
  1831 +360729,全南县,4,360700
  1832 +360730,宁都县,4,360700
  1833 +360731,于都县,4,360700
  1834 +360732,兴国县,4,360700
  1835 +360733,会昌县,4,360700
  1836 +360734,寻乌县,4,360700
  1837 +360735,石城县,4,360700
  1838 +360781,瑞金市,4,360700
  1839 +360783,龙南市,4,360700
  1840 +360802,吉州区,4,360800
  1841 +360803,青原区,4,360800
  1842 +360821,吉安县,4,360800
  1843 +360822,吉水县,4,360800
  1844 +360823,峡江县,4,360800
  1845 +360824,新干县,4,360800
  1846 +360825,永丰县,4,360800
  1847 +360826,泰和县,4,360800
  1848 +360827,遂川县,4,360800
  1849 +360828,万安县,4,360800
  1850 +360829,安福县,4,360800
  1851 +360830,永新县,4,360800
  1852 +360881,井冈山市,4,360800
  1853 +360902,袁州区,4,360900
  1854 +360921,奉新县,4,360900
  1855 +360922,万载县,4,360900
  1856 +360923,上高县,4,360900
  1857 +360924,宜丰县,4,360900
  1858 +360925,靖安县,4,360900
  1859 +360926,铜鼓县,4,360900
  1860 +360981,丰城市,4,360900
  1861 +360982,樟树市,4,360900
  1862 +360983,高安市,4,360900
  1863 +361002,临川区,4,361000
  1864 +361003,东乡区,4,361000
  1865 +361021,南城县,4,361000
  1866 +361022,黎川县,4,361000
  1867 +361023,南丰县,4,361000
  1868 +361024,崇仁县,4,361000
  1869 +361025,乐安县,4,361000
  1870 +361026,宜黄县,4,361000
  1871 +361027,金溪县,4,361000
  1872 +361028,资溪县,4,361000
  1873 +361030,广昌县,4,361000
  1874 +361102,信州区,4,361100
  1875 +361103,广丰区,4,361100
  1876 +361104,广信区,4,361100
  1877 +361123,玉山县,4,361100
  1878 +361124,铅山县,4,361100
  1879 +361125,横峰县,4,361100
  1880 +361126,弋阳县,4,361100
  1881 +361127,余干县,4,361100
  1882 +361128,鄱阳县,4,361100
  1883 +361129,万年县,4,361100
  1884 +361130,婺源县,4,361100
  1885 +361181,德兴市,4,361100
  1886 +370102,历下区,4,370100
  1887 +370103,市中区,4,370100
  1888 +370104,槐荫区,4,370100
  1889 +370105,天桥区,4,370100
  1890 +370112,历城区,4,370100
  1891 +370113,长清区,4,370100
  1892 +370114,章丘区,4,370100
  1893 +370115,济阳区,4,370100
  1894 +370116,莱芜区,4,370100
  1895 +370117,钢城区,4,370100
  1896 +370124,平阴县,4,370100
  1897 +370126,商河县,4,370100
  1898 +370171,济南高新技术产业开发区,4,370100
  1899 +370202,市南区,4,370200
  1900 +370203,市北区,4,370200
  1901 +370211,黄岛区,4,370200
  1902 +370212,崂山区,4,370200
  1903 +370213,李沧区,4,370200
  1904 +370214,城阳区,4,370200
  1905 +370215,即墨区,4,370200
  1906 +370271,青岛高新技术产业开发区,4,370200
  1907 +370281,胶州市,4,370200
  1908 +370283,平度市,4,370200
  1909 +370285,莱西市,4,370200
  1910 +370302,淄川区,4,370300
  1911 +370303,张店区,4,370300
  1912 +370304,博山区,4,370300
  1913 +370305,临淄区,4,370300
  1914 +370306,周村区,4,370300
  1915 +370321,桓台县,4,370300
  1916 +370322,高青县,4,370300
  1917 +370323,沂源县,4,370300
  1918 +370402,市中区,4,370400
  1919 +370403,薛城区,4,370400
  1920 +370404,峄城区,4,370400
  1921 +370405,台儿庄区,4,370400
  1922 +370406,山亭区,4,370400
  1923 +370481,滕州市,4,370400
  1924 +370502,东营区,4,370500
  1925 +370503,河口区,4,370500
  1926 +370505,垦利区,4,370500
  1927 +370522,利津县,4,370500
  1928 +370523,广饶县,4,370500
  1929 +370571,东营经济技术开发区,4,370500
  1930 +370572,东营港经济开发区,4,370500
  1931 +370602,芝罘区,4,370600
  1932 +370611,福山区,4,370600
  1933 +370612,牟平区,4,370600
  1934 +370613,莱山区,4,370600
  1935 +370614,蓬莱区,4,370600
  1936 +370671,烟台高新技术产业开发区,4,370600
  1937 +370672,烟台经济技术开发区,4,370600
  1938 +370681,龙口市,4,370600
  1939 +370682,莱阳市,4,370600
  1940 +370683,莱州市,4,370600
  1941 +370685,招远市,4,370600
  1942 +370686,栖霞市,4,370600
  1943 +370687,海阳市,4,370600
  1944 +370702,潍城区,4,370700
  1945 +370703,寒亭区,4,370700
  1946 +370704,坊子区,4,370700
  1947 +370705,奎文区,4,370700
  1948 +370724,临朐县,4,370700
  1949 +370725,昌乐县,4,370700
  1950 +370772,潍坊滨海经济技术开发区,4,370700
  1951 +370781,青州市,4,370700
  1952 +370782,诸城市,4,370700
  1953 +370783,寿光市,4,370700
  1954 +370784,安丘市,4,370700
  1955 +370785,高密市,4,370700
  1956 +370786,昌邑市,4,370700
  1957 +370811,任城区,4,370800
  1958 +370812,兖州区,4,370800
  1959 +370826,微山县,4,370800
  1960 +370827,鱼台县,4,370800
  1961 +370828,金乡县,4,370800
  1962 +370829,嘉祥县,4,370800
  1963 +370830,汶上县,4,370800
  1964 +370831,泗水县,4,370800
  1965 +370832,梁山县,4,370800
  1966 +370871,济宁高新技术产业开发区,4,370800
  1967 +370881,曲阜市,4,370800
  1968 +370883,邹城市,4,370800
  1969 +370902,泰山区,4,370900
  1970 +370911,岱岳区,4,370900
  1971 +370921,宁阳县,4,370900
  1972 +370923,东平县,4,370900
  1973 +370982,新泰市,4,370900
  1974 +370983,肥城市,4,370900
  1975 +371002,环翠区,4,371000
  1976 +371003,文登区,4,371000
  1977 +371071,威海火炬高技术产业开发区,4,371000
  1978 +371072,威海经济技术开发区,4,371000
  1979 +371073,威海临港经济技术开发区,4,371000
  1980 +371082,荣成市,4,371000
  1981 +371083,乳山市,4,371000
  1982 +371102,东港区,4,371100
  1983 +371103,岚山区,4,371100
  1984 +371121,五莲县,4,371100
  1985 +371122,莒县,4,371100
  1986 +371171,日照经济技术开发区,4,371100
  1987 +371302,兰山区,4,371300
  1988 +371311,罗庄区,4,371300
  1989 +371312,河东区,4,371300
  1990 +371321,沂南县,4,371300
  1991 +371322,郯城县,4,371300
  1992 +371323,沂水县,4,371300
  1993 +371324,兰陵县,4,371300
  1994 +371325,费县,4,371300
  1995 +371326,平邑县,4,371300
  1996 +371327,莒南县,4,371300
  1997 +371328,蒙阴县,4,371300
  1998 +371329,临沭县,4,371300
  1999 +371371,临沂高新技术产业开发区,4,371300
  2000 +371402,德城区,4,371400
  2001 +371403,陵城区,4,371400
  2002 +371422,宁津县,4,371400
  2003 +371423,庆云县,4,371400
  2004 +371424,临邑县,4,371400
  2005 +371425,齐河县,4,371400
  2006 +371426,平原县,4,371400
  2007 +371427,夏津县,4,371400
  2008 +371428,武城县,4,371400
  2009 +371471,德州经济技术开发区,4,371400
  2010 +371472,德州运河经济开发区,4,371400
  2011 +371481,乐陵市,4,371400
  2012 +371482,禹城市,4,371400
  2013 +371502,东昌府区,4,371500
  2014 +371503,茌平区,4,371500
  2015 +371521,阳谷县,4,371500
  2016 +371522,莘县,4,371500
  2017 +371524,东阿县,4,371500
  2018 +371525,冠县,4,371500
  2019 +371526,高唐县,4,371500
  2020 +371581,临清市,4,371500
  2021 +371602,滨城区,4,371600
  2022 +371603,沾化区,4,371600
  2023 +371621,惠民县,4,371600
  2024 +371622,阳信县,4,371600
  2025 +371623,无棣县,4,371600
  2026 +371625,博兴县,4,371600
  2027 +371681,邹平市,4,371600
  2028 +371702,牡丹区,4,371700
  2029 +371703,定陶区,4,371700
  2030 +371721,曹县,4,371700
  2031 +371722,单县,4,371700
  2032 +371723,成武县,4,371700
  2033 +371724,巨野县,4,371700
  2034 +371725,郓城县,4,371700
  2035 +371726,鄄城县,4,371700
  2036 +371728,东明县,4,371700
  2037 +371771,菏泽经济技术开发区,4,371700
  2038 +371772,菏泽高新技术开发区,4,371700
  2039 +410102,中原区,4,410100
  2040 +410103,二七区,4,410100
  2041 +410104,管城回族区,4,410100
  2042 +410105,金水区,4,410100
  2043 +410106,上街区,4,410100
  2044 +410108,惠济区,4,410100
  2045 +410122,中牟县,4,410100
  2046 +410171,郑州经济技术开发区,4,410100
  2047 +410172,郑州高新技术产业开发区,4,410100
  2048 +410173,郑州航空港经济综合实验区,4,410100
  2049 +410181,巩义市,4,410100
  2050 +410182,荥阳市,4,410100
  2051 +410183,新密市,4,410100
  2052 +410184,新郑市,4,410100
  2053 +410185,登封市,4,410100
  2054 +410202,龙亭区,4,410200
  2055 +410203,顺河回族区,4,410200
  2056 +410204,鼓楼区,4,410200
  2057 +410205,禹王台区,4,410200
  2058 +410212,祥符区,4,410200
  2059 +410221,杞县,4,410200
  2060 +410222,通许县,4,410200
  2061 +410223,尉氏县,4,410200
  2062 +410225,兰考县,4,410200
  2063 +410302,老城区,4,410300
  2064 +410303,西工区,4,410300
  2065 +410304,瀍河回族区,4,410300
  2066 +410305,涧西区,4,410300
  2067 +410307,偃师区,4,410300
  2068 +410308,孟津区,4,410300
  2069 +410311,洛龙区,4,410300
  2070 +410323,新安县,4,410300
  2071 +410324,栾川县,4,410300
  2072 +410325,嵩县,4,410300
  2073 +410326,汝阳县,4,410300
  2074 +410327,宜阳县,4,410300
  2075 +410328,洛宁县,4,410300
  2076 +410329,伊川县,4,410300
  2077 +410371,洛阳高新技术产业开发区,4,410300
  2078 +410402,新华区,4,410400
  2079 +410403,卫东区,4,410400
  2080 +410404,石龙区,4,410400
  2081 +410411,湛河区,4,410400
  2082 +410421,宝丰县,4,410400
  2083 +410422,叶县,4,410400
  2084 +410423,鲁山县,4,410400
  2085 +410425,郏县,4,410400
  2086 +410471,平顶山高新技术产业开发区,4,410400
  2087 +410472,平顶山市城乡一体化示范区,4,410400
  2088 +410481,舞钢市,4,410400
  2089 +410482,汝州市,4,410400
  2090 +410502,文峰区,4,410500
  2091 +410503,北关区,4,410500
  2092 +410505,殷都区,4,410500
  2093 +410506,龙安区,4,410500
  2094 +410522,安阳县,4,410500
  2095 +410523,汤阴县,4,410500
  2096 +410526,滑县,4,410500
  2097 +410527,内黄县,4,410500
  2098 +410571,安阳高新技术产业开发区,4,410500
  2099 +410581,林州市,4,410500
  2100 +410602,鹤山区,4,410600
  2101 +410603,山城区,4,410600
  2102 +410611,淇滨区,4,410600
  2103 +410621,浚县,4,410600
  2104 +410622,淇县,4,410600
  2105 +410671,鹤壁经济技术开发区,4,410600
  2106 +410702,红旗区,4,410700
  2107 +410703,卫滨区,4,410700
  2108 +410704,凤泉区,4,410700
  2109 +410711,牧野区,4,410700
  2110 +410721,新乡县,4,410700
  2111 +410724,获嘉县,4,410700
  2112 +410725,原阳县,4,410700
  2113 +410726,延津县,4,410700
  2114 +410727,封丘县,4,410700
  2115 +410771,新乡高新技术产业开发区,4,410700
  2116 +410772,新乡经济技术开发区,4,410700
  2117 +410773,新乡市平原城乡一体化示范区,4,410700
  2118 +410781,卫辉市,4,410700
  2119 +410782,辉县市,4,410700
  2120 +410783,长垣市,4,410700
  2121 +410802,解放区,4,410800
  2122 +410803,中站区,4,410800
  2123 +410804,马村区,4,410800
  2124 +410811,山阳区,4,410800
  2125 +410821,修武县,4,410800
  2126 +410822,博爱县,4,410800
  2127 +410823,武陟县,4,410800
  2128 +410825,温县,4,410800
  2129 +410871,焦作城乡一体化示范区,4,410800
  2130 +410882,沁阳市,4,410800
  2131 +410883,孟州市,4,410800
  2132 +410902,华龙区,4,410900
  2133 +410922,清丰县,4,410900
  2134 +410923,南乐县,4,410900
  2135 +410926,范县,4,410900
  2136 +410927,台前县,4,410900
  2137 +410928,濮阳县,4,410900
  2138 +410971,河南濮阳工业园区,4,410900
  2139 +410972,濮阳经济技术开发区,4,410900
  2140 +411002,魏都区,4,411000
  2141 +411003,建安区,4,411000
  2142 +411024,鄢陵县,4,411000
  2143 +411025,襄城县,4,411000
  2144 +411071,许昌经济技术开发区,4,411000
  2145 +411081,禹州市,4,411000
  2146 +411082,长葛市,4,411000
  2147 +411102,源汇区,4,411100
  2148 +411103,郾城区,4,411100
  2149 +411104,召陵区,4,411100
  2150 +411121,舞阳县,4,411100
  2151 +411122,临颍县,4,411100
  2152 +411171,漯河经济技术开发区,4,411100
  2153 +411202,湖滨区,4,411200
  2154 +411203,陕州区,4,411200
  2155 +411221,渑池县,4,411200
  2156 +411224,卢氏县,4,411200
  2157 +411271,河南三门峡经济开发区,4,411200
  2158 +411281,义马市,4,411200
  2159 +411282,灵宝市,4,411200
  2160 +411302,宛城区,4,411300
  2161 +411303,卧龙区,4,411300
  2162 +411321,南召县,4,411300
  2163 +411322,方城县,4,411300
  2164 +411323,西峡县,4,411300
  2165 +411324,镇平县,4,411300
  2166 +411325,内乡县,4,411300
  2167 +411326,淅川县,4,411300
  2168 +411327,社旗县,4,411300
  2169 +411328,唐河县,4,411300
  2170 +411329,新野县,4,411300
  2171 +411330,桐柏县,4,411300
  2172 +411371,南阳高新技术产业开发区,4,411300
  2173 +411372,南阳市城乡一体化示范区,4,411300
  2174 +411381,邓州市,4,411300
  2175 +411402,梁园区,4,411400
  2176 +411403,睢阳区,4,411400
  2177 +411421,民权县,4,411400
  2178 +411422,睢县,4,411400
  2179 +411423,宁陵县,4,411400
  2180 +411424,柘城县,4,411400
  2181 +411425,虞城县,4,411400
  2182 +411426,夏邑县,4,411400
  2183 +411471,豫东综合物流产业聚集区,4,411400
  2184 +411472,河南商丘经济开发区,4,411400
  2185 +411481,永城市,4,411400
  2186 +411502,浉河区,4,411500
  2187 +411503,平桥区,4,411500
  2188 +411521,罗山县,4,411500
  2189 +411522,光山县,4,411500
  2190 +411523,新县,4,411500
  2191 +411524,商城县,4,411500
  2192 +411525,固始县,4,411500
  2193 +411526,潢川县,4,411500
  2194 +411527,淮滨县,4,411500
  2195 +411528,息县,4,411500
  2196 +411571,信阳高新技术产业开发区,4,411500
  2197 +411602,川汇区,4,411600
  2198 +411603,淮阳区,4,411600
  2199 +411621,扶沟县,4,411600
  2200 +411622,西华县,4,411600
  2201 +411623,商水县,4,411600
  2202 +411624,沈丘县,4,411600
  2203 +411625,郸城县,4,411600
  2204 +411627,太康县,4,411600
  2205 +411628,鹿邑县,4,411600
  2206 +411671,河南周口经济开发区,4,411600
  2207 +411681,项城市,4,411600
  2208 +411702,驿城区,4,411700
  2209 +411721,西平县,4,411700
  2210 +411722,上蔡县,4,411700
  2211 +411723,平舆县,4,411700
  2212 +411724,正阳县,4,411700
  2213 +411725,确山县,4,411700
  2214 +411726,泌阳县,4,411700
  2215 +411727,汝南县,4,411700
  2216 +411728,遂平县,4,411700
  2217 +411729,新蔡县,4,411700
  2218 +411771,河南驻马店经济开发区,4,411700
  2219 +419001,济源市,4,419000
  2220 +420102,江岸区,4,420100
  2221 +420103,江汉区,4,420100
  2222 +420104,硚口区,4,420100
  2223 +420105,汉阳区,4,420100
  2224 +420106,武昌区,4,420100
  2225 +420107,青山区,4,420100
  2226 +420111,洪山区,4,420100
  2227 +420112,东西湖区,4,420100
  2228 +420113,汉南区,4,420100
  2229 +420114,蔡甸区,4,420100
  2230 +420115,江夏区,4,420100
  2231 +420116,黄陂区,4,420100
  2232 +420117,新洲区,4,420100
  2233 +420202,黄石港区,4,420200
  2234 +420203,西塞山区,4,420200
  2235 +420204,下陆区,4,420200
  2236 +420205,铁山区,4,420200
  2237 +420222,阳新县,4,420200
  2238 +420281,大冶市,4,420200
  2239 +420302,茅箭区,4,420300
  2240 +420303,张湾区,4,420300
  2241 +420304,郧阳区,4,420300
  2242 +420322,郧西县,4,420300
  2243 +420323,竹山县,4,420300
  2244 +420324,竹溪县,4,420300
  2245 +420325,房县,4,420300
  2246 +420381,丹江口市,4,420300
  2247 +420502,西陵区,4,420500
  2248 +420503,伍家岗区,4,420500
  2249 +420504,点军区,4,420500
  2250 +420505,猇亭区,4,420500
  2251 +420506,夷陵区,4,420500
  2252 +420525,远安县,4,420500
  2253 +420526,兴山县,4,420500
  2254 +420527,秭归县,4,420500
  2255 +420528,长阳土家族自治县,4,420500
  2256 +420529,五峰土家族自治县,4,420500
  2257 +420581,宜都市,4,420500
  2258 +420582,当阳市,4,420500
  2259 +420583,枝江市,4,420500
  2260 +420602,襄城区,4,420600
  2261 +420606,樊城区,4,420600
  2262 +420607,襄州区,4,420600
  2263 +420624,南漳县,4,420600
  2264 +420625,谷城县,4,420600
  2265 +420626,保康县,4,420600
  2266 +420682,老河口市,4,420600
  2267 +420683,枣阳市,4,420600
  2268 +420684,宜城市,4,420600
  2269 +420702,梁子湖区,4,420700
  2270 +420703,华容区,4,420700
  2271 +420704,鄂城区,4,420700
  2272 +420802,东宝区,4,420800
  2273 +420804,掇刀区,4,420800
  2274 +420822,沙洋县,4,420800
  2275 +420881,钟祥市,4,420800
  2276 +420882,京山市,4,420800
  2277 +420902,孝南区,4,420900
  2278 +420921,孝昌县,4,420900
  2279 +420922,大悟县,4,420900
  2280 +420923,云梦县,4,420900
  2281 +420981,应城市,4,420900
  2282 +420982,安陆市,4,420900
  2283 +420984,汉川市,4,420900
  2284 +421002,沙市区,4,421000
  2285 +421003,荆州区,4,421000
  2286 +421022,公安县,4,421000
  2287 +421024,江陵县,4,421000
  2288 +421071,荆州经济技术开发区,4,421000
  2289 +421081,石首市,4,421000
  2290 +421083,洪湖市,4,421000
  2291 +421087,松滋市,4,421000
  2292 +421088,监利市,4,421000
  2293 +421102,黄州区,4,421100
  2294 +421121,团风县,4,421100
  2295 +421122,红安县,4,421100
  2296 +421123,罗田县,4,421100
  2297 +421124,英山县,4,421100
  2298 +421125,浠水县,4,421100
  2299 +421126,蕲春县,4,421100
  2300 +421127,黄梅县,4,421100
  2301 +421171,龙感湖管理区,4,421100
  2302 +421181,麻城市,4,421100
  2303 +421182,武穴市,4,421100
  2304 +421202,咸安区,4,421200
  2305 +421221,嘉鱼县,4,421200
  2306 +421222,通城县,4,421200
  2307 +421223,崇阳县,4,421200
  2308 +421224,通山县,4,421200
  2309 +421281,赤壁市,4,421200
  2310 +421303,曾都区,4,421300
  2311 +421321,随县,4,421300
  2312 +421381,广水市,4,421300
  2313 +422801,恩施市,4,422800
  2314 +422802,利川市,4,422800
  2315 +422822,建始县,4,422800
  2316 +422823,巴东县,4,422800
  2317 +422825,宣恩县,4,422800
  2318 +422826,咸丰县,4,422800
  2319 +422827,来凤县,4,422800
  2320 +422828,鹤峰县,4,422800
  2321 +429004,仙桃市,4,429000
  2322 +429005,潜江市,4,429000
  2323 +429006,天门市,4,429000
  2324 +429021,神农架林区,4,429000
  2325 +430102,芙蓉区,4,430100
  2326 +430103,天心区,4,430100
  2327 +430104,岳麓区,4,430100
  2328 +430105,开福区,4,430100
  2329 +430111,雨花区,4,430100
  2330 +430112,望城区,4,430100
  2331 +430121,长沙县,4,430100
  2332 +430181,浏阳市,4,430100
  2333 +430182,宁乡市,4,430100
  2334 +430202,荷塘区,4,430200
  2335 +430203,芦淞区,4,430200
  2336 +430204,石峰区,4,430200
  2337 +430211,天元区,4,430200
  2338 +430212,渌口区,4,430200
  2339 +430223,攸县,4,430200
  2340 +430224,茶陵县,4,430200
  2341 +430225,炎陵县,4,430200
  2342 +430271,云龙示范区,4,430200
  2343 +430281,醴陵市,4,430200
  2344 +430302,雨湖区,4,430300
  2345 +430304,岳塘区,4,430300
  2346 +430321,湘潭县,4,430300
  2347 +430371,湖南湘潭高新技术产业园区,4,430300
  2348 +430372,湘潭昭山示范区,4,430300
  2349 +430373,湘潭九华示范区,4,430300
  2350 +430381,湘乡市,4,430300
  2351 +430382,韶山市,4,430300
  2352 +430405,珠晖区,4,430400
  2353 +430406,雁峰区,4,430400
  2354 +430407,石鼓区,4,430400
  2355 +430408,蒸湘区,4,430400
  2356 +430412,南岳区,4,430400
  2357 +430421,衡阳县,4,430400
  2358 +430422,衡南县,4,430400
  2359 +430423,衡山县,4,430400
  2360 +430424,衡东县,4,430400
  2361 +430426,祁东县,4,430400
  2362 +430471,衡阳综合保税区,4,430400
  2363 +430472,湖南衡阳高新技术产业园区,4,430400
  2364 +430473,湖南衡阳松木经济开发区,4,430400
  2365 +430481,耒阳市,4,430400
  2366 +430482,常宁市,4,430400
  2367 +430502,双清区,4,430500
  2368 +430503,大祥区,4,430500
  2369 +430511,北塔区,4,430500
  2370 +430522,新邵县,4,430500
  2371 +430523,邵阳县,4,430500
  2372 +430524,隆回县,4,430500
  2373 +430525,洞口县,4,430500
  2374 +430527,绥宁县,4,430500
  2375 +430528,新宁县,4,430500
  2376 +430529,城步苗族自治县,4,430500
  2377 +430581,武冈市,4,430500
  2378 +430582,邵东市,4,430500
  2379 +430602,岳阳楼区,4,430600
  2380 +430603,云溪区,4,430600
  2381 +430611,君山区,4,430600
  2382 +430621,岳阳县,4,430600
  2383 +430623,华容县,4,430600
  2384 +430624,湘阴县,4,430600
  2385 +430626,平江县,4,430600
  2386 +430671,岳阳市屈原管理区,4,430600
  2387 +430681,汨罗市,4,430600
  2388 +430682,临湘市,4,430600
  2389 +430702,武陵区,4,430700
  2390 +430703,鼎城区,4,430700
  2391 +430721,安乡县,4,430700
  2392 +430722,汉寿县,4,430700
  2393 +430723,澧县,4,430700
  2394 +430724,临澧县,4,430700
  2395 +430725,桃源县,4,430700
  2396 +430726,石门县,4,430700
  2397 +430771,常德市西洞庭管理区,4,430700
  2398 +430781,津市市,4,430700
  2399 +430802,永定区,4,430800
  2400 +430811,武陵源区,4,430800
  2401 +430821,慈利县,4,430800
  2402 +430822,桑植县,4,430800
  2403 +430902,资阳区,4,430900
  2404 +430903,赫山区,4,430900
  2405 +430921,南县,4,430900
  2406 +430922,桃江县,4,430900
  2407 +430923,安化县,4,430900
  2408 +430971,益阳市大通湖管理区,4,430900
  2409 +430972,湖南益阳高新技术产业园区,4,430900
  2410 +430981,沅江市,4,430900
  2411 +431002,北湖区,4,431000
  2412 +431003,苏仙区,4,431000
  2413 +431021,桂阳县,4,431000
  2414 +431022,宜章县,4,431000
  2415 +431023,永兴县,4,431000
  2416 +431024,嘉禾县,4,431000
  2417 +431025,临武县,4,431000
  2418 +431026,汝城县,4,431000
  2419 +431027,桂东县,4,431000
  2420 +431028,安仁县,4,431000
  2421 +431081,资兴市,4,431000
  2422 +431102,零陵区,4,431100
  2423 +431103,冷水滩区,4,431100
  2424 +431122,东安县,4,431100
  2425 +431123,双牌县,4,431100
  2426 +431124,道县,4,431100
  2427 +431125,江永县,4,431100
  2428 +431126,宁远县,4,431100
  2429 +431127,蓝山县,4,431100
  2430 +431128,新田县,4,431100
  2431 +431129,江华瑶族自治县,4,431100
  2432 +431171,永州经济技术开发区,4,431100
  2433 +431173,永州市回龙圩管理区,4,431100
  2434 +431181,祁阳市,4,431100
  2435 +431202,鹤城区,4,431200
  2436 +431221,中方县,4,431200
  2437 +431222,沅陵县,4,431200
  2438 +431223,辰溪县,4,431200
  2439 +431224,溆浦县,4,431200
  2440 +431225,会同县,4,431200
  2441 +431226,麻阳苗族自治县,4,431200
  2442 +431227,新晃侗族自治县,4,431200
  2443 +431228,芷江侗族自治县,4,431200
  2444 +431229,靖州苗族侗族自治县,4,431200
  2445 +431230,通道侗族自治县,4,431200
  2446 +431271,怀化市洪江管理区,4,431200
  2447 +431281,洪江市,4,431200
  2448 +431302,娄星区,4,431300
  2449 +431321,双峰县,4,431300
  2450 +431322,新化县,4,431300
  2451 +431381,冷水江市,4,431300
  2452 +431382,涟源市,4,431300
  2453 +433101,吉首市,4,433100
  2454 +433122,泸溪县,4,433100
  2455 +433123,凤凰县,4,433100
  2456 +433124,花垣县,4,433100
  2457 +433125,保靖县,4,433100
  2458 +433126,古丈县,4,433100
  2459 +433127,永顺县,4,433100
  2460 +433130,龙山县,4,433100
  2461 +440103,荔湾区,4,440100
  2462 +440104,越秀区,4,440100
  2463 +440105,海珠区,4,440100
  2464 +440106,天河区,4,440100
  2465 +440111,白云区,4,440100
  2466 +440112,黄埔区,4,440100
  2467 +440113,番禺区,4,440100
  2468 +440114,花都区,4,440100
  2469 +440115,南沙区,4,440100
  2470 +440117,从化区,4,440100
  2471 +440118,增城区,4,440100
  2472 +440203,武江区,4,440200
  2473 +440204,浈江区,4,440200
  2474 +440205,曲江区,4,440200
  2475 +440222,始兴县,4,440200
  2476 +440224,仁化县,4,440200
  2477 +440229,翁源县,4,440200
  2478 +440232,乳源瑶族自治县,4,440200
  2479 +440233,新丰县,4,440200
  2480 +440281,乐昌市,4,440200
  2481 +440282,南雄市,4,440200
  2482 +440303,罗湖区,4,440300
  2483 +440304,福田区,4,440300
  2484 +440305,南山区,4,440300
  2485 +440306,宝安区,4,440300
  2486 +440307,龙岗区,4,440300
  2487 +440308,盐田区,4,440300
  2488 +440309,龙华区,4,440300
  2489 +440310,坪山区,4,440300
  2490 +440311,光明区,4,440300
  2491 +440402,香洲区,4,440400
  2492 +440403,斗门区,4,440400
  2493 +440404,金湾区,4,440400
  2494 +440507,龙湖区,4,440500
  2495 +440511,金平区,4,440500
  2496 +440512,濠江区,4,440500
  2497 +440513,潮阳区,4,440500
  2498 +440514,潮南区,4,440500
  2499 +440515,澄海区,4,440500
  2500 +440523,南澳县,4,440500
  2501 +440604,禅城区,4,440600
  2502 +440605,南海区,4,440600
  2503 +440606,顺德区,4,440600
  2504 +440607,三水区,4,440600
  2505 +440608,高明区,4,440600
  2506 +440703,蓬江区,4,440700
  2507 +440704,江海区,4,440700
  2508 +440705,新会区,4,440700
  2509 +440781,台山市,4,440700
  2510 +440783,开平市,4,440700
  2511 +440784,鹤山市,4,440700
  2512 +440785,恩平市,4,440700
  2513 +440802,赤坎区,4,440800
  2514 +440803,霞山区,4,440800
  2515 +440804,坡头区,4,440800
  2516 +440811,麻章区,4,440800
  2517 +440823,遂溪县,4,440800
  2518 +440825,徐闻县,4,440800
  2519 +440881,廉江市,4,440800
  2520 +440882,雷州市,4,440800
  2521 +440883,吴川市,4,440800
  2522 +440902,茂南区,4,440900
  2523 +440904,电白区,4,440900
  2524 +440981,高州市,4,440900
  2525 +440982,化州市,4,440900
  2526 +440983,信宜市,4,440900
  2527 +441202,端州区,4,441200
  2528 +441203,鼎湖区,4,441200
  2529 +441204,高要区,4,441200
  2530 +441223,广宁县,4,441200
  2531 +441224,怀集县,4,441200
  2532 +441225,封开县,4,441200
  2533 +441226,德庆县,4,441200
  2534 +441284,四会市,4,441200
  2535 +441302,惠城区,4,441300
  2536 +441303,惠阳区,4,441300
  2537 +441322,博罗县,4,441300
  2538 +441323,惠东县,4,441300
  2539 +441324,龙门县,4,441300
  2540 +441402,梅江区,4,441400
  2541 +441403,梅县区,4,441400
  2542 +441422,大埔县,4,441400
  2543 +441423,丰顺县,4,441400
  2544 +441424,五华县,4,441400
  2545 +441426,平远县,4,441400
  2546 +441427,蕉岭县,4,441400
  2547 +441481,兴宁市,4,441400
  2548 +441502,城区,4,441500
  2549 +441521,海丰县,4,441500
  2550 +441523,陆河县,4,441500
  2551 +441581,陆丰市,4,441500
  2552 +441602,源城区,4,441600
  2553 +441621,紫金县,4,441600
  2554 +441622,龙川县,4,441600
  2555 +441623,连平县,4,441600
  2556 +441624,和平县,4,441600
  2557 +441625,东源县,4,441600
  2558 +441702,江城区,4,441700
  2559 +441704,阳东区,4,441700
  2560 +441721,阳西县,4,441700
  2561 +441781,阳春市,4,441700
  2562 +441802,清城区,4,441800
  2563 +441803,清新区,4,441800
  2564 +441821,佛冈县,4,441800
  2565 +441823,阳山县,4,441800
  2566 +441825,连山壮族瑶族自治县,4,441800
  2567 +441826,连南瑶族自治县,4,441800
  2568 +441881,英德市,4,441800
  2569 +441882,连州市,4,441800
  2570 +445102,湘桥区,4,445100
  2571 +445103,潮安区,4,445100
  2572 +445122,饶平县,4,445100
  2573 +445202,榕城区,4,445200
  2574 +445203,揭东区,4,445200
  2575 +445222,揭西县,4,445200
  2576 +445224,惠来县,4,445200
  2577 +445281,普宁市,4,445200
  2578 +445302,云城区,4,445300
  2579 +445303,云安区,4,445300
  2580 +445321,新兴县,4,445300
  2581 +445322,郁南县,4,445300
  2582 +445381,罗定市,4,445300
  2583 +450102,兴宁区,4,450100
  2584 +450103,青秀区,4,450100
  2585 +450105,江南区,4,450100
  2586 +450107,西乡塘区,4,450100
  2587 +450108,良庆区,4,450100
  2588 +450109,邕宁区,4,450100
  2589 +450110,武鸣区,4,450100
  2590 +450123,隆安县,4,450100
  2591 +450124,马山县,4,450100
  2592 +450125,上林县,4,450100
  2593 +450126,宾阳县,4,450100
  2594 +450181,横州市,4,450100
  2595 +450202,城中区,4,450200
  2596 +450203,鱼峰区,4,450200
  2597 +450204,柳南区,4,450200
  2598 +450205,柳北区,4,450200
  2599 +450206,柳江区,4,450200
  2600 +450222,柳城县,4,450200
  2601 +450223,鹿寨县,4,450200
  2602 +450224,融安县,4,450200
  2603 +450225,融水苗族自治县,4,450200
  2604 +450226,三江侗族自治县,4,450200
  2605 +450302,秀峰区,4,450300
  2606 +450303,叠彩区,4,450300
  2607 +450304,象山区,4,450300
  2608 +450305,七星区,4,450300
  2609 +450311,雁山区,4,450300
  2610 +450312,临桂区,4,450300
  2611 +450321,阳朔县,4,450300
  2612 +450323,灵川县,4,450300
  2613 +450324,全州县,4,450300
  2614 +450325,兴安县,4,450300
  2615 +450326,永福县,4,450300
  2616 +450327,灌阳县,4,450300
  2617 +450328,龙胜各族自治县,4,450300
  2618 +450329,资源县,4,450300
  2619 +450330,平乐县,4,450300
  2620 +450332,恭城瑶族自治县,4,450300
  2621 +450381,荔浦市,4,450300
  2622 +450403,万秀区,4,450400
  2623 +450405,长洲区,4,450400
  2624 +450406,龙圩区,4,450400
  2625 +450421,苍梧县,4,450400
  2626 +450422,藤县,4,450400
  2627 +450423,蒙山县,4,450400
  2628 +450481,岑溪市,4,450400
  2629 +450502,海城区,4,450500
  2630 +450503,银海区,4,450500
  2631 +450512,铁山港区,4,450500
  2632 +450521,合浦县,4,450500
  2633 +450602,港口区,4,450600
  2634 +450603,防城区,4,450600
  2635 +450621,上思县,4,450600
  2636 +450681,东兴市,4,450600
  2637 +450702,钦南区,4,450700
  2638 +450703,钦北区,4,450700
  2639 +450721,灵山县,4,450700
  2640 +450722,浦北县,4,450700
  2641 +450802,港北区,4,450800
  2642 +450803,港南区,4,450800
  2643 +450804,覃塘区,4,450800
  2644 +450821,平南县,4,450800
  2645 +450881,桂平市,4,450800
  2646 +450902,玉州区,4,450900
  2647 +450903,福绵区,4,450900
  2648 +450921,容县,4,450900
  2649 +450922,陆川县,4,450900
  2650 +450923,博白县,4,450900
  2651 +450924,兴业县,4,450900
  2652 +450981,北流市,4,450900
  2653 +451002,右江区,4,451000
  2654 +451003,田阳区,4,451000
  2655 +451022,田东县,4,451000
  2656 +451024,德保县,4,451000
  2657 +451026,那坡县,4,451000
  2658 +451027,凌云县,4,451000
  2659 +451028,乐业县,4,451000
  2660 +451029,田林县,4,451000
  2661 +451030,西林县,4,451000
  2662 +451031,隆林各族自治县,4,451000
  2663 +451081,靖西市,4,451000
  2664 +451082,平果市,4,451000
  2665 +451102,八步区,4,451100
  2666 +451103,平桂区,4,451100
  2667 +451121,昭平县,4,451100
  2668 +451122,钟山县,4,451100
  2669 +451123,富川瑶族自治县,4,451100
  2670 +451202,金城江区,4,451200
  2671 +451203,宜州区,4,451200
  2672 +451221,南丹县,4,451200
  2673 +451222,天峨县,4,451200
  2674 +451223,凤山县,4,451200
  2675 +451224,东兰县,4,451200
  2676 +451225,罗城仫佬族自治县,4,451200
  2677 +451226,环江毛南族自治县,4,451200
  2678 +451227,巴马瑶族自治县,4,451200
  2679 +451228,都安瑶族自治县,4,451200
  2680 +451229,大化瑶族自治县,4,451200
  2681 +451302,兴宾区,4,451300
  2682 +451321,忻城县,4,451300
  2683 +451322,象州县,4,451300
  2684 +451323,武宣县,4,451300
  2685 +451324,金秀瑶族自治县,4,451300
  2686 +451381,合山市,4,451300
  2687 +451402,江州区,4,451400
  2688 +451421,扶绥县,4,451400
  2689 +451422,宁明县,4,451400
  2690 +451423,龙州县,4,451400
  2691 +451424,大新县,4,451400
  2692 +451425,天等县,4,451400
  2693 +451481,凭祥市,4,451400
  2694 +460105,秀英区,4,460100
  2695 +460106,龙华区,4,460100
  2696 +460107,琼山区,4,460100
  2697 +460108,美兰区,4,460100
  2698 +460202,海棠区,4,460200
  2699 +460203,吉阳区,4,460200
  2700 +460204,天涯区,4,460200
  2701 +460205,崖州区,4,460200
  2702 +460321,西沙群岛,4,460300
  2703 +460322,南沙群岛,4,460300
  2704 +460323,中沙群岛的岛礁及其海域,4,460300
  2705 +469001,五指山市,4,469000
  2706 +469002,琼海市,4,469000
  2707 +469005,文昌市,4,469000
  2708 +469006,万宁市,4,469000
  2709 +469007,东方市,4,469000
  2710 +469021,定安县,4,469000
  2711 +469022,屯昌县,4,469000
  2712 +469023,澄迈县,4,469000
  2713 +469024,临高县,4,469000
  2714 +469025,白沙黎族自治县,4,469000
  2715 +469026,昌江黎族自治县,4,469000
  2716 +469027,乐东黎族自治县,4,469000
  2717 +469028,陵水黎族自治县,4,469000
  2718 +469029,保亭黎族苗族自治县,4,469000
  2719 +469030,琼中黎族苗族自治县,4,469000
  2720 +500101,万州区,4,500100
  2721 +500102,涪陵区,4,500100
  2722 +500103,渝中区,4,500100
  2723 +500104,大渡口区,4,500100
  2724 +500105,江北区,4,500100
  2725 +500106,沙坪坝区,4,500100
  2726 +500107,九龙坡区,4,500100
  2727 +500108,南岸区,4,500100
  2728 +500109,北碚区,4,500100
  2729 +500110,綦江区,4,500100
  2730 +500111,大足区,4,500100
  2731 +500112,渝北区,4,500100
  2732 +500113,巴南区,4,500100
  2733 +500114,黔江区,4,500100
  2734 +500115,长寿区,4,500100
  2735 +500116,江津区,4,500100
  2736 +500117,合川区,4,500100
  2737 +500118,永川区,4,500100
  2738 +500119,南川区,4,500100
  2739 +500120,璧山区,4,500100
  2740 +500151,铜梁区,4,500100
  2741 +500152,潼南区,4,500100
  2742 +500153,荣昌区,4,500100
  2743 +500154,开州区,4,500100
  2744 +500155,梁平区,4,500100
  2745 +500156,武隆区,4,500100
  2746 +500229,城口县,4,500100
  2747 +500230,丰都县,4,500100
  2748 +500231,垫江县,4,500100
  2749 +500233,忠县,4,500100
  2750 +500235,云阳县,4,500100
  2751 +500236,奉节县,4,500100
  2752 +500237,巫山县,4,500100
  2753 +500238,巫溪县,4,500100
  2754 +500240,石柱土家族自治县,4,500100
  2755 +500241,秀山土家族苗族自治县,4,500100
  2756 +500242,酉阳土家族苗族自治县,4,500100
  2757 +500243,彭水苗族土家族自治县,4,500100
  2758 +510104,锦江区,4,510100
  2759 +510105,青羊区,4,510100
  2760 +510106,金牛区,4,510100
  2761 +510107,武侯区,4,510100
  2762 +510108,成华区,4,510100
  2763 +510112,龙泉驿区,4,510100
  2764 +510113,青白江区,4,510100
  2765 +510114,新都区,4,510100
  2766 +510115,温江区,4,510100
  2767 +510116,双流区,4,510100
  2768 +510117,郫都区,4,510100
  2769 +510118,新津区,4,510100
  2770 +510121,金堂县,4,510100
  2771 +510129,大邑县,4,510100
  2772 +510131,蒲江县,4,510100
  2773 +510181,都江堰市,4,510100
  2774 +510182,彭州市,4,510100
  2775 +510183,邛崃市,4,510100
  2776 +510184,崇州市,4,510100
  2777 +510185,简阳市,4,510100
  2778 +510302,自流井区,4,510300
  2779 +510303,贡井区,4,510300
  2780 +510304,大安区,4,510300
  2781 +510311,沿滩区,4,510300
  2782 +510321,荣县,4,510300
  2783 +510322,富顺县,4,510300
  2784 +510402,东区,4,510400
  2785 +510403,西区,4,510400
  2786 +510411,仁和区,4,510400
  2787 +510421,米易县,4,510400
  2788 +510422,盐边县,4,510400
  2789 +510502,江阳区,4,510500
  2790 +510503,纳溪区,4,510500
  2791 +510504,龙马潭区,4,510500
  2792 +510521,泸县,4,510500
  2793 +510522,合江县,4,510500
  2794 +510524,叙永县,4,510500
  2795 +510525,古蔺县,4,510500
  2796 +510603,旌阳区,4,510600
  2797 +510604,罗江区,4,510600
  2798 +510623,中江县,4,510600
  2799 +510681,广汉市,4,510600
  2800 +510682,什邡市,4,510600
  2801 +510683,绵竹市,4,510600
  2802 +510703,涪城区,4,510700
  2803 +510704,游仙区,4,510700
  2804 +510705,安州区,4,510700
  2805 +510722,三台县,4,510700
  2806 +510723,盐亭县,4,510700
  2807 +510725,梓潼县,4,510700
  2808 +510726,北川羌族自治县,4,510700
  2809 +510727,平武县,4,510700
  2810 +510781,江油市,4,510700
  2811 +510802,利州区,4,510800
  2812 +510811,昭化区,4,510800
  2813 +510812,朝天区,4,510800
  2814 +510821,旺苍县,4,510800
  2815 +510822,青川县,4,510800
  2816 +510823,剑阁县,4,510800
  2817 +510824,苍溪县,4,510800
  2818 +510903,船山区,4,510900
  2819 +510904,安居区,4,510900
  2820 +510921,蓬溪县,4,510900
  2821 +510923,大英县,4,510900
  2822 +510981,射洪市,4,510900
  2823 +511002,市中区,4,511000
  2824 +511011,东兴区,4,511000
  2825 +511024,威远县,4,511000
  2826 +511025,资中县,4,511000
  2827 +511071,内江经济开发区,4,511000
  2828 +511083,隆昌市,4,511000
  2829 +511102,市中区,4,511100
  2830 +511111,沙湾区,4,511100
  2831 +511112,五通桥区,4,511100
  2832 +511113,金口河区,4,511100
  2833 +511123,犍为县,4,511100
  2834 +511124,井研县,4,511100
  2835 +511126,夹江县,4,511100
  2836 +511129,沐川县,4,511100
  2837 +511132,峨边彝族自治县,4,511100
  2838 +511133,马边彝族自治县,4,511100
  2839 +511181,峨眉山市,4,511100
  2840 +511302,顺庆区,4,511300
  2841 +511303,高坪区,4,511300
  2842 +511304,嘉陵区,4,511300
  2843 +511321,南部县,4,511300
  2844 +511322,营山县,4,511300
  2845 +511323,蓬安县,4,511300
  2846 +511324,仪陇县,4,511300
  2847 +511325,西充县,4,511300
  2848 +511381,阆中市,4,511300
  2849 +511402,东坡区,4,511400
  2850 +511403,彭山区,4,511400
  2851 +511421,仁寿县,4,511400
  2852 +511423,洪雅县,4,511400
  2853 +511424,丹棱县,4,511400
  2854 +511425,青神县,4,511400
  2855 +511502,翠屏区,4,511500
  2856 +511503,南溪区,4,511500
  2857 +511504,叙州区,4,511500
  2858 +511523,江安县,4,511500
  2859 +511524,长宁县,4,511500
  2860 +511525,高县,4,511500
  2861 +511526,珙县,4,511500
  2862 +511527,筠连县,4,511500
  2863 +511528,兴文县,4,511500
  2864 +511529,屏山县,4,511500
  2865 +511602,广安区,4,511600
  2866 +511603,前锋区,4,511600
  2867 +511621,岳池县,4,511600
  2868 +511622,武胜县,4,511600
  2869 +511623,邻水县,4,511600
  2870 +511681,华蓥市,4,511600
  2871 +511702,通川区,4,511700
  2872 +511703,达川区,4,511700
  2873 +511722,宣汉县,4,511700
  2874 +511723,开江县,4,511700
  2875 +511724,大竹县,4,511700
  2876 +511725,渠县,4,511700
  2877 +511771,达州经济开发区,4,511700
  2878 +511781,万源市,4,511700
  2879 +511802,雨城区,4,511800
  2880 +511803,名山区,4,511800
  2881 +511822,荥经县,4,511800
  2882 +511823,汉源县,4,511800
  2883 +511824,石棉县,4,511800
  2884 +511825,天全县,4,511800
  2885 +511826,芦山县,4,511800
  2886 +511827,宝兴县,4,511800
  2887 +511902,巴州区,4,511900
  2888 +511903,恩阳区,4,511900
  2889 +511921,通江县,4,511900
  2890 +511922,南江县,4,511900
  2891 +511923,平昌县,4,511900
  2892 +511971,巴中经济开发区,4,511900
  2893 +512002,雁江区,4,512000
  2894 +512021,安岳县,4,512000
  2895 +512022,乐至县,4,512000
  2896 +513201,马尔康市,4,513200
  2897 +513221,汶川县,4,513200
  2898 +513222,理县,4,513200
  2899 +513223,茂县,4,513200
  2900 +513224,松潘县,4,513200
  2901 +513225,九寨沟县,4,513200
  2902 +513226,金川县,4,513200
  2903 +513227,小金县,4,513200
  2904 +513228,黑水县,4,513200
  2905 +513230,壤塘县,4,513200
  2906 +513231,阿坝县,4,513200
  2907 +513232,若尔盖县,4,513200
  2908 +513233,红原县,4,513200
  2909 +513301,康定市,4,513300
  2910 +513322,泸定县,4,513300
  2911 +513323,丹巴县,4,513300
  2912 +513324,九龙县,4,513300
  2913 +513325,雅江县,4,513300
  2914 +513326,道孚县,4,513300
  2915 +513327,炉霍县,4,513300
  2916 +513328,甘孜县,4,513300
  2917 +513329,新龙县,4,513300
  2918 +513330,德格县,4,513300
  2919 +513331,白玉县,4,513300
  2920 +513332,石渠县,4,513300
  2921 +513333,色达县,4,513300
  2922 +513334,理塘县,4,513300
  2923 +513335,巴塘县,4,513300
  2924 +513336,乡城县,4,513300
  2925 +513337,稻城县,4,513300
  2926 +513338,得荣县,4,513300
  2927 +513401,西昌市,4,513400
  2928 +513402,会理市,4,513400
  2929 +513422,木里藏族自治县,4,513400
  2930 +513423,盐源县,4,513400
  2931 +513424,德昌县,4,513400
  2932 +513426,会东县,4,513400
  2933 +513427,宁南县,4,513400
  2934 +513428,普格县,4,513400
  2935 +513429,布拖县,4,513400
  2936 +513430,金阳县,4,513400
  2937 +513431,昭觉县,4,513400
  2938 +513432,喜德县,4,513400
  2939 +513433,冕宁县,4,513400
  2940 +513434,越西县,4,513400
  2941 +513435,甘洛县,4,513400
  2942 +513436,美姑县,4,513400
  2943 +513437,雷波县,4,513400
  2944 +520102,南明区,4,520100
  2945 +520103,云岩区,4,520100
  2946 +520111,花溪区,4,520100
  2947 +520112,乌当区,4,520100
  2948 +520113,白云区,4,520100
  2949 +520115,观山湖区,4,520100
  2950 +520121,开阳县,4,520100
  2951 +520122,息烽县,4,520100
  2952 +520123,修文县,4,520100
  2953 +520181,清镇市,4,520100
  2954 +520201,钟山区,4,520200
  2955 +520203,六枝特区,4,520200
  2956 +520204,水城区,4,520200
  2957 +520281,盘州市,4,520200
  2958 +520302,红花岗区,4,520300
  2959 +520303,汇川区,4,520300
  2960 +520304,播州区,4,520300
  2961 +520322,桐梓县,4,520300
  2962 +520323,绥阳县,4,520300
  2963 +520324,正安县,4,520300
  2964 +520325,道真仡佬族苗族自治县,4,520300
  2965 +520326,务川仡佬族苗族自治县,4,520300
  2966 +520327,凤冈县,4,520300
  2967 +520328,湄潭县,4,520300
  2968 +520329,余庆县,4,520300
  2969 +520330,习水县,4,520300
  2970 +520381,赤水市,4,520300
  2971 +520382,仁怀市,4,520300
  2972 +520402,西秀区,4,520400
  2973 +520403,平坝区,4,520400
  2974 +520422,普定县,4,520400
  2975 +520423,镇宁布依族苗族自治县,4,520400
  2976 +520424,关岭布依族苗族自治县,4,520400
  2977 +520425,紫云苗族布依族自治县,4,520400
  2978 +520502,七星关区,4,520500
  2979 +520521,大方县,4,520500
  2980 +520523,金沙县,4,520500
  2981 +520524,织金县,4,520500
  2982 +520525,纳雍县,4,520500
  2983 +520526,威宁彝族回族苗族自治县,4,520500
  2984 +520527,赫章县,4,520500
  2985 +520581,黔西市,4,520500
  2986 +520602,碧江区,4,520600
  2987 +520603,万山区,4,520600
  2988 +520621,江口县,4,520600
  2989 +520622,玉屏侗族自治县,4,520600
  2990 +520623,石阡县,4,520600
  2991 +520624,思南县,4,520600
  2992 +520625,印江土家族苗族自治县,4,520600
  2993 +520626,德江县,4,520600
  2994 +520627,沿河土家族自治县,4,520600
  2995 +520628,松桃苗族自治县,4,520600
  2996 +522301,兴义市,4,522300
  2997 +522302,兴仁市,4,522300
  2998 +522323,普安县,4,522300
  2999 +522324,晴隆县,4,522300
  3000 +522325,贞丰县,4,522300
  3001 +522326,望谟县,4,522300
  3002 +522327,册亨县,4,522300
  3003 +522328,安龙县,4,522300
  3004 +522601,凯里市,4,522600
  3005 +522622,黄平县,4,522600
  3006 +522623,施秉县,4,522600
  3007 +522624,三穗县,4,522600
  3008 +522625,镇远县,4,522600
  3009 +522626,岑巩县,4,522600
  3010 +522627,天柱县,4,522600
  3011 +522628,锦屏县,4,522600
  3012 +522629,剑河县,4,522600
  3013 +522630,台江县,4,522600
  3014 +522631,黎平县,4,522600
  3015 +522632,榕江县,4,522600
  3016 +522633,从江县,4,522600
  3017 +522634,雷山县,4,522600
  3018 +522635,麻江县,4,522600
  3019 +522636,丹寨县,4,522600
  3020 +522701,都匀市,4,522700
  3021 +522702,福泉市,4,522700
  3022 +522722,荔波县,4,522700
  3023 +522723,贵定县,4,522700
  3024 +522725,瓮安县,4,522700
  3025 +522726,独山县,4,522700
  3026 +522727,平塘县,4,522700
  3027 +522728,罗甸县,4,522700
  3028 +522729,长顺县,4,522700
  3029 +522730,龙里县,4,522700
  3030 +522731,惠水县,4,522700
  3031 +522732,三都水族自治县,4,522700
  3032 +530102,五华区,4,530100
  3033 +530103,盘龙区,4,530100
  3034 +530111,官渡区,4,530100
  3035 +530112,西山区,4,530100
  3036 +530113,东川区,4,530100
  3037 +530114,呈贡区,4,530100
  3038 +530115,晋宁区,4,530100
  3039 +530124,富民县,4,530100
  3040 +530125,宜良县,4,530100
  3041 +530126,石林彝族自治县,4,530100
  3042 +530127,嵩明县,4,530100
  3043 +530128,禄劝彝族苗族自治县,4,530100
  3044 +530129,寻甸回族彝族自治县,4,530100
  3045 +530181,安宁市,4,530100
  3046 +530302,麒麟区,4,530300
  3047 +530303,沾益区,4,530300
  3048 +530304,马龙区,4,530300
  3049 +530322,陆良县,4,530300
  3050 +530323,师宗县,4,530300
  3051 +530324,罗平县,4,530300
  3052 +530325,富源县,4,530300
  3053 +530326,会泽县,4,530300
  3054 +530381,宣威市,4,530300
  3055 +530402,红塔区,4,530400
  3056 +530403,江川区,4,530400
  3057 +530423,通海县,4,530400
  3058 +530424,华宁县,4,530400
  3059 +530425,易门县,4,530400
  3060 +530426,峨山彝族自治县,4,530400
  3061 +530427,新平彝族傣族自治县,4,530400
  3062 +530428,元江哈尼族彝族傣族自治县,4,530400
  3063 +530481,澄江市,4,530400
  3064 +530502,隆阳区,4,530500
  3065 +530521,施甸县,4,530500
  3066 +530523,龙陵县,4,530500
  3067 +530524,昌宁县,4,530500
  3068 +530581,腾冲市,4,530500
  3069 +530602,昭阳区,4,530600
  3070 +530621,鲁甸县,4,530600
  3071 +530622,巧家县,4,530600
  3072 +530623,盐津县,4,530600
  3073 +530624,大关县,4,530600
  3074 +530625,永善县,4,530600
  3075 +530626,绥江县,4,530600
  3076 +530627,镇雄县,4,530600
  3077 +530628,彝良县,4,530600
  3078 +530629,威信县,4,530600
  3079 +530681,水富市,4,530600
  3080 +530702,古城区,4,530700
  3081 +530721,玉龙纳西族自治县,4,530700
  3082 +530722,永胜县,4,530700
  3083 +530723,华坪县,4,530700
  3084 +530724,宁蒗彝族自治县,4,530700
  3085 +530802,思茅区,4,530800
  3086 +530821,宁洱哈尼族彝族自治县,4,530800
  3087 +530822,墨江哈尼族自治县,4,530800
  3088 +530823,景东彝族自治县,4,530800
  3089 +530824,景谷傣族彝族自治县,4,530800
  3090 +530825,镇沅彝族哈尼族拉祜族自治县,4,530800
  3091 +530826,江城哈尼族彝族自治县,4,530800
  3092 +530827,孟连傣族拉祜族佤族自治县,4,530800
  3093 +530828,澜沧拉祜族自治县,4,530800
  3094 +530829,西盟佤族自治县,4,530800
  3095 +530902,临翔区,4,530900
  3096 +530921,凤庆县,4,530900
  3097 +530922,云县,4,530900
  3098 +530923,永德县,4,530900
  3099 +530924,镇康县,4,530900
  3100 +530925,双江拉祜族佤族布朗族傣族自治县,4,530900
  3101 +530926,耿马傣族佤族自治县,4,530900
  3102 +530927,沧源佤族自治县,4,530900
  3103 +532301,楚雄市,4,532300
  3104 +532302,禄丰市,4,532300
  3105 +532322,双柏县,4,532300
  3106 +532323,牟定县,4,532300
  3107 +532324,南华县,4,532300
  3108 +532325,姚安县,4,532300
  3109 +532326,大姚县,4,532300
  3110 +532327,永仁县,4,532300
  3111 +532328,元谋县,4,532300
  3112 +532329,武定县,4,532300
  3113 +532501,个旧市,4,532500
  3114 +532502,开远市,4,532500
  3115 +532503,蒙自市,4,532500
  3116 +532504,弥勒市,4,532500
  3117 +532523,屏边苗族自治县,4,532500
  3118 +532524,建水县,4,532500
  3119 +532525,石屏县,4,532500
  3120 +532527,泸西县,4,532500
  3121 +532528,元阳县,4,532500
  3122 +532529,红河县,4,532500
  3123 +532530,金平苗族瑶族傣族自治县,4,532500
  3124 +532531,绿春县,4,532500
  3125 +532532,河口瑶族自治县,4,532500
  3126 +532601,文山市,4,532600
  3127 +532622,砚山县,4,532600
  3128 +532623,西畴县,4,532600
  3129 +532624,麻栗坡县,4,532600
  3130 +532625,马关县,4,532600
  3131 +532626,丘北县,4,532600
  3132 +532627,广南县,4,532600
  3133 +532628,富宁县,4,532600
  3134 +532801,景洪市,4,532800
  3135 +532822,勐海县,4,532800
  3136 +532823,勐腊县,4,532800
  3137 +532901,大理市,4,532900
  3138 +532922,漾濞彝族自治县,4,532900
  3139 +532923,祥云县,4,532900
  3140 +532924,宾川县,4,532900
  3141 +532925,弥渡县,4,532900
  3142 +532926,南涧彝族自治县,4,532900
  3143 +532927,巍山彝族回族自治县,4,532900
  3144 +532928,永平县,4,532900
  3145 +532929,云龙县,4,532900
  3146 +532930,洱源县,4,532900
  3147 +532931,剑川县,4,532900
  3148 +532932,鹤庆县,4,532900
  3149 +533102,瑞丽市,4,533100
  3150 +533103,芒市,4,533100
  3151 +533122,梁河县,4,533100
  3152 +533123,盈江县,4,533100
  3153 +533124,陇川县,4,533100
  3154 +533301,泸水市,4,533300
  3155 +533323,福贡县,4,533300
  3156 +533324,贡山独龙族怒族自治县,4,533300
  3157 +533325,兰坪白族普米族自治县,4,533300
  3158 +533401,香格里拉市,4,533400
  3159 +533422,德钦县,4,533400
  3160 +533423,维西傈僳族自治县,4,533400
  3161 +540102,城关区,4,540100
  3162 +540103,堆龙德庆区,4,540100
  3163 +540104,达孜区,4,540100
  3164 +540121,林周县,4,540100
  3165 +540122,当雄县,4,540100
  3166 +540123,尼木县,4,540100
  3167 +540124,曲水县,4,540100
  3168 +540127,墨竹工卡县,4,540100
  3169 +540171,格尔木藏青工业园区,4,540100
  3170 +540172,拉萨经济技术开发区,4,540100
  3171 +540173,西藏文化旅游创意园区,4,540100
  3172 +540174,达孜工业园区,4,540100
  3173 +540202,桑珠孜区,4,540200
  3174 +540221,南木林县,4,540200
  3175 +540222,江孜县,4,540200
  3176 +540223,定日县,4,540200
  3177 +540224,萨迦县,4,540200
  3178 +540225,拉孜县,4,540200
  3179 +540226,昂仁县,4,540200
  3180 +540227,谢通门县,4,540200
  3181 +540228,白朗县,4,540200
  3182 +540229,仁布县,4,540200
  3183 +540230,康马县,4,540200
  3184 +540231,定结县,4,540200
  3185 +540232,仲巴县,4,540200
  3186 +540233,亚东县,4,540200
  3187 +540234,吉隆县,4,540200
  3188 +540235,聂拉木县,4,540200
  3189 +540236,萨嘎县,4,540200
  3190 +540237,岗巴县,4,540200
  3191 +540302,卡若区,4,540300
  3192 +540321,江达县,4,540300
  3193 +540322,贡觉县,4,540300
  3194 +540323,类乌齐县,4,540300
  3195 +540324,丁青县,4,540300
  3196 +540325,察雅县,4,540300
  3197 +540326,八宿县,4,540300
  3198 +540327,左贡县,4,540300
  3199 +540328,芒康县,4,540300
  3200 +540329,洛隆县,4,540300
  3201 +540330,边坝县,4,540300
  3202 +540402,巴宜区,4,540400
  3203 +540421,工布江达县,4,540400
  3204 +540422,米林县,4,540400
  3205 +540423,墨脱县,4,540400
  3206 +540424,波密县,4,540400
  3207 +540425,察隅县,4,540400
  3208 +540426,朗县,4,540400
  3209 +540502,乃东区,4,540500
  3210 +540521,扎囊县,4,540500
  3211 +540522,贡嘎县,4,540500
  3212 +540523,桑日县,4,540500
  3213 +540524,琼结县,4,540500
  3214 +540525,曲松县,4,540500
  3215 +540526,措美县,4,540500
  3216 +540527,洛扎县,4,540500
  3217 +540528,加查县,4,540500
  3218 +540529,隆子县,4,540500
  3219 +540530,错那县,4,540500
  3220 +540531,浪卡子县,4,540500
  3221 +540602,色尼区,4,540600
  3222 +540621,嘉黎县,4,540600
  3223 +540622,比如县,4,540600
  3224 +540623,聂荣县,4,540600
  3225 +540624,安多县,4,540600
  3226 +540625,申扎县,4,540600
  3227 +540626,索县,4,540600
  3228 +540627,班戈县,4,540600
  3229 +540628,巴青县,4,540600
  3230 +540629,尼玛县,4,540600
  3231 +540630,双湖县,4,540600
  3232 +542521,普兰县,4,542500
  3233 +542522,札达县,4,542500
  3234 +542523,噶尔县,4,542500
  3235 +542524,日土县,4,542500
  3236 +542525,革吉县,4,542500
  3237 +542526,改则县,4,542500
  3238 +542527,措勤县,4,542500
  3239 +610102,新城区,4,610100
  3240 +610103,碑林区,4,610100
  3241 +610104,莲湖区,4,610100
  3242 +610111,灞桥区,4,610100
  3243 +610112,未央区,4,610100
  3244 +610113,雁塔区,4,610100
  3245 +610114,阎良区,4,610100
  3246 +610115,临潼区,4,610100
  3247 +610116,长安区,4,610100
  3248 +610117,高陵区,4,610100
  3249 +610118,鄠邑区,4,610100
  3250 +610122,蓝田县,4,610100
  3251 +610124,周至县,4,610100
  3252 +610202,王益区,4,610200
  3253 +610203,印台区,4,610200
  3254 +610204,耀州区,4,610200
  3255 +610222,宜君县,4,610200
  3256 +610302,渭滨区,4,610300
  3257 +610303,金台区,4,610300
  3258 +610304,陈仓区,4,610300
  3259 +610305,凤翔区,4,610300
  3260 +610323,岐山县,4,610300
  3261 +610324,扶风县,4,610300
  3262 +610326,眉县,4,610300
  3263 +610327,陇县,4,610300
  3264 +610328,千阳县,4,610300
  3265 +610329,麟游县,4,610300
  3266 +610330,凤县,4,610300
  3267 +610331,太白县,4,610300
  3268 +610402,秦都区,4,610400
  3269 +610403,杨陵区,4,610400
  3270 +610404,渭城区,4,610400
  3271 +610422,三原县,4,610400
  3272 +610423,泾阳县,4,610400
  3273 +610424,乾县,4,610400
  3274 +610425,礼泉县,4,610400
  3275 +610426,永寿县,4,610400
  3276 +610428,长武县,4,610400
  3277 +610429,旬邑县,4,610400
  3278 +610430,淳化县,4,610400
  3279 +610431,武功县,4,610400
  3280 +610481,兴平市,4,610400
  3281 +610482,彬州市,4,610400
  3282 +610502,临渭区,4,610500
  3283 +610503,华州区,4,610500
  3284 +610522,潼关县,4,610500
  3285 +610523,大荔县,4,610500
  3286 +610524,合阳县,4,610500
  3287 +610525,澄城县,4,610500
  3288 +610526,蒲城县,4,610500
  3289 +610527,白水县,4,610500
  3290 +610528,富平县,4,610500
  3291 +610581,韩城市,4,610500
  3292 +610582,华阴市,4,610500
  3293 +610602,宝塔区,4,610600
  3294 +610603,安塞区,4,610600
  3295 +610621,延长县,4,610600
  3296 +610622,延川县,4,610600
  3297 +610625,志丹县,4,610600
  3298 +610626,吴起县,4,610600
  3299 +610627,甘泉县,4,610600
  3300 +610628,富县,4,610600
  3301 +610629,洛川县,4,610600
  3302 +610630,宜川县,4,610600
  3303 +610631,黄龙县,4,610600
  3304 +610632,黄陵县,4,610600
  3305 +610681,子长市,4,610600
  3306 +610702,汉台区,4,610700
  3307 +610703,南郑区,4,610700
  3308 +610722,城固县,4,610700
  3309 +610723,洋县,4,610700
  3310 +610724,西乡县,4,610700
  3311 +610725,勉县,4,610700
  3312 +610726,宁强县,4,610700
  3313 +610727,略阳县,4,610700
  3314 +610728,镇巴县,4,610700
  3315 +610729,留坝县,4,610700
  3316 +610730,佛坪县,4,610700
  3317 +610802,榆阳区,4,610800
  3318 +610803,横山区,4,610800
  3319 +610822,府谷县,4,610800
  3320 +610824,靖边县,4,610800
  3321 +610825,定边县,4,610800
  3322 +610826,绥德县,4,610800
  3323 +610827,米脂县,4,610800
  3324 +610828,佳县,4,610800
  3325 +610829,吴堡县,4,610800
  3326 +610830,清涧县,4,610800
  3327 +610831,子洲县,4,610800
  3328 +610881,神木市,4,610800
  3329 +610902,汉滨区,4,610900
  3330 +610921,汉阴县,4,610900
  3331 +610922,石泉县,4,610900
  3332 +610923,宁陕县,4,610900
  3333 +610924,紫阳县,4,610900
  3334 +610925,岚皋县,4,610900
  3335 +610926,平利县,4,610900
  3336 +610927,镇坪县,4,610900
  3337 +610929,白河县,4,610900
  3338 +610981,旬阳市,4,610900
  3339 +611002,商州区,4,611000
  3340 +611021,洛南县,4,611000
  3341 +611022,丹凤县,4,611000
  3342 +611023,商南县,4,611000
  3343 +611024,山阳县,4,611000
  3344 +611025,镇安县,4,611000
  3345 +611026,柞水县,4,611000
  3346 +620102,城关区,4,620100
  3347 +620103,七里河区,4,620100
  3348 +620104,西固区,4,620100
  3349 +620105,安宁区,4,620100
  3350 +620111,红古区,4,620100
  3351 +620121,永登县,4,620100
  3352 +620122,皋兰县,4,620100
  3353 +620123,榆中县,4,620100
  3354 +620171,兰州新区,4,620100
  3355 +620201,嘉峪关市,4,620200
  3356 +620302,金川区,4,620300
  3357 +620321,永昌县,4,620300
  3358 +620402,白银区,4,620400
  3359 +620403,平川区,4,620400
  3360 +620421,靖远县,4,620400
  3361 +620422,会宁县,4,620400
  3362 +620423,景泰县,4,620400
  3363 +620502,秦州区,4,620500
  3364 +620503,麦积区,4,620500
  3365 +620521,清水县,4,620500
  3366 +620522,秦安县,4,620500
  3367 +620523,甘谷县,4,620500
  3368 +620524,武山县,4,620500
  3369 +620525,张家川回族自治县,4,620500
  3370 +620602,凉州区,4,620600
  3371 +620621,民勤县,4,620600
  3372 +620622,古浪县,4,620600
  3373 +620623,天祝藏族自治县,4,620600
  3374 +620702,甘州区,4,620700
  3375 +620721,肃南裕固族自治县,4,620700
  3376 +620722,民乐县,4,620700
  3377 +620723,临泽县,4,620700
  3378 +620724,高台县,4,620700
  3379 +620725,山丹县,4,620700
  3380 +620802,崆峒区,4,620800
  3381 +620821,泾川县,4,620800
  3382 +620822,灵台县,4,620800
  3383 +620823,崇信县,4,620800
  3384 +620825,庄浪县,4,620800
  3385 +620826,静宁县,4,620800
  3386 +620881,华亭市,4,620800
  3387 +620902,肃州区,4,620900
  3388 +620921,金塔县,4,620900
  3389 +620922,瓜州县,4,620900
  3390 +620923,肃北蒙古族自治县,4,620900
  3391 +620924,阿克塞哈萨克族自治县,4,620900
  3392 +620981,玉门市,4,620900
  3393 +620982,敦煌市,4,620900
  3394 +621002,西峰区,4,621000
  3395 +621021,庆城县,4,621000
  3396 +621022,环县,4,621000
  3397 +621023,华池县,4,621000
  3398 +621024,合水县,4,621000
  3399 +621025,正宁县,4,621000
  3400 +621026,宁县,4,621000
  3401 +621027,镇原县,4,621000
  3402 +621102,安定区,4,621100
  3403 +621121,通渭县,4,621100
  3404 +621122,陇西县,4,621100
  3405 +621123,渭源县,4,621100
  3406 +621124,临洮县,4,621100
  3407 +621125,漳县,4,621100
  3408 +621126,岷县,4,621100
  3409 +621202,武都区,4,621200
  3410 +621221,成县,4,621200
  3411 +621222,文县,4,621200
  3412 +621223,宕昌县,4,621200
  3413 +621224,康县,4,621200
  3414 +621225,西和县,4,621200
  3415 +621226,礼县,4,621200
  3416 +621227,徽县,4,621200
  3417 +621228,两当县,4,621200
  3418 +622901,临夏市,4,622900
  3419 +622921,临夏县,4,622900
  3420 +622922,康乐县,4,622900
  3421 +622923,永靖县,4,622900
  3422 +622924,广河县,4,622900
  3423 +622925,和政县,4,622900
  3424 +622926,东乡族自治县,4,622900
  3425 +622927,积石山保安族东乡族撒拉族自治县,4,622900
  3426 +623001,合作市,4,623000
  3427 +623021,临潭县,4,623000
  3428 +623022,卓尼县,4,623000
  3429 +623023,舟曲县,4,623000
  3430 +623024,迭部县,4,623000
  3431 +623025,玛曲县,4,623000
  3432 +623026,碌曲县,4,623000
  3433 +623027,夏河县,4,623000
  3434 +630102,城东区,4,630100
  3435 +630103,城中区,4,630100
  3436 +630104,城西区,4,630100
  3437 +630105,城北区,4,630100
  3438 +630106,湟中区,4,630100
  3439 +630121,大通回族土族自治县,4,630100
  3440 +630123,湟源县,4,630100
  3441 +630202,乐都区,4,630200
  3442 +630203,平安区,4,630200
  3443 +630222,民和回族土族自治县,4,630200
  3444 +630223,互助土族自治县,4,630200
  3445 +630224,化隆回族自治县,4,630200
  3446 +630225,循化撒拉族自治县,4,630200
  3447 +632221,门源回族自治县,4,632200
  3448 +632222,祁连县,4,632200
  3449 +632223,海晏县,4,632200
  3450 +632224,刚察县,4,632200
  3451 +632301,同仁市,4,632300
  3452 +632322,尖扎县,4,632300
  3453 +632323,泽库县,4,632300
  3454 +632324,河南蒙古族自治县,4,632300
  3455 +632521,共和县,4,632500
  3456 +632522,同德县,4,632500
  3457 +632523,贵德县,4,632500
  3458 +632524,兴海县,4,632500
  3459 +632525,贵南县,4,632500
  3460 +632621,玛沁县,4,632600
  3461 +632622,班玛县,4,632600
  3462 +632623,甘德县,4,632600
  3463 +632624,达日县,4,632600
  3464 +632625,久治县,4,632600
  3465 +632626,玛多县,4,632600
  3466 +632701,玉树市,4,632700
  3467 +632722,杂多县,4,632700
  3468 +632723,称多县,4,632700
  3469 +632724,治多县,4,632700
  3470 +632725,囊谦县,4,632700
  3471 +632726,曲麻莱县,4,632700
  3472 +632801,格尔木市,4,632800
  3473 +632802,德令哈市,4,632800
  3474 +632803,茫崖市,4,632800
  3475 +632821,乌兰县,4,632800
  3476 +632822,都兰县,4,632800
  3477 +632823,天峻县,4,632800
  3478 +632857,大柴旦行政委员会,4,632800
  3479 +640104,兴庆区,4,640100
  3480 +640105,西夏区,4,640100
  3481 +640106,金凤区,4,640100
  3482 +640121,永宁县,4,640100
  3483 +640122,贺兰县,4,640100
  3484 +640181,灵武市,4,640100
  3485 +640202,大武口区,4,640200
  3486 +640205,惠农区,4,640200
  3487 +640221,平罗县,4,640200
  3488 +640302,利通区,4,640300
  3489 +640303,红寺堡区,4,640300
  3490 +640323,盐池县,4,640300
  3491 +640324,同心县,4,640300
  3492 +640381,青铜峡市,4,640300
  3493 +640402,原州区,4,640400
  3494 +640422,西吉县,4,640400
  3495 +640423,隆德县,4,640400
  3496 +640424,泾源县,4,640400
  3497 +640425,彭阳县,4,640400
  3498 +640502,沙坡头区,4,640500
  3499 +640521,中宁县,4,640500
  3500 +640522,海原县,4,640500
  3501 +650102,天山区,4,650100
  3502 +650103,沙依巴克区,4,650100
  3503 +650104,新市区,4,650100
  3504 +650105,水磨沟区,4,650100
  3505 +650106,头屯河区,4,650100
  3506 +650107,达坂城区,4,650100
  3507 +650109,米东区,4,650100
  3508 +650121,乌鲁木齐县,4,650100
  3509 +650202,独山子区,4,650200
  3510 +650203,克拉玛依区,4,650200
  3511 +650204,白碱滩区,4,650200
  3512 +650205,乌尔禾区,4,650200
  3513 +650402,高昌区,4,650400
  3514 +650421,鄯善县,4,650400
  3515 +650422,托克逊县,4,650400
  3516 +650502,伊州区,4,650500
  3517 +650521,巴里坤哈萨克自治县,4,650500
  3518 +650522,伊吾县,4,650500
  3519 +652301,昌吉市,4,652300
  3520 +652302,阜康市,4,652300
  3521 +652323,呼图壁县,4,652300
  3522 +652324,玛纳斯县,4,652300
  3523 +652325,奇台县,4,652300
  3524 +652327,吉木萨尔县,4,652300
  3525 +652328,木垒哈萨克自治县,4,652300
  3526 +652701,博乐市,4,652700
  3527 +652702,阿拉山口市,4,652700
  3528 +652722,精河县,4,652700
  3529 +652723,温泉县,4,652700
  3530 +652801,库尔勒市,4,652800
  3531 +652822,轮台县,4,652800
  3532 +652823,尉犁县,4,652800
  3533 +652824,若羌县,4,652800
  3534 +652825,且末县,4,652800
  3535 +652826,焉耆回族自治县,4,652800
  3536 +652827,和静县,4,652800
  3537 +652828,和硕县,4,652800
  3538 +652829,博湖县,4,652800
  3539 +652871,库尔勒经济技术开发区,4,652800
  3540 +652901,阿克苏市,4,652900
  3541 +652902,库车市,4,652900
  3542 +652922,温宿县,4,652900
  3543 +652924,沙雅县,4,652900
  3544 +652925,新和县,4,652900
  3545 +652926,拜城县,4,652900
  3546 +652927,乌什县,4,652900
  3547 +652928,阿瓦提县,4,652900
  3548 +652929,柯坪县,4,652900
  3549 +653001,阿图什市,4,653000
  3550 +653022,阿克陶县,4,653000
  3551 +653023,阿合奇县,4,653000
  3552 +653024,乌恰县,4,653000
  3553 +653101,喀什市,4,653100
  3554 +653121,疏附县,4,653100
  3555 +653122,疏勒县,4,653100
  3556 +653123,英吉沙县,4,653100
  3557 +653124,泽普县,4,653100
  3558 +653125,莎车县,4,653100
  3559 +653126,叶城县,4,653100
  3560 +653127,麦盖提县,4,653100
  3561 +653128,岳普湖县,4,653100
  3562 +653129,伽师县,4,653100
  3563 +653130,巴楚县,4,653100
  3564 +653131,塔什库尔干塔吉克自治县,4,653100
  3565 +653201,和田市,4,653200
  3566 +653221,和田县,4,653200
  3567 +653222,墨玉县,4,653200
  3568 +653223,皮山县,4,653200
  3569 +653224,洛浦县,4,653200
  3570 +653225,策勒县,4,653200
  3571 +653226,于田县,4,653200
  3572 +653227,民丰县,4,653200
  3573 +654002,伊宁市,4,654000
  3574 +654003,奎屯市,4,654000
  3575 +654004,霍尔果斯市,4,654000
  3576 +654021,伊宁县,4,654000
  3577 +654022,察布查尔锡伯自治县,4,654000
  3578 +654023,霍城县,4,654000
  3579 +654024,巩留县,4,654000
  3580 +654025,新源县,4,654000
  3581 +654026,昭苏县,4,654000
  3582 +654027,特克斯县,4,654000
  3583 +654028,尼勒克县,4,654000
  3584 +654201,塔城市,4,654200
  3585 +654202,乌苏市,4,654200
  3586 +654203,沙湾市,4,654200
  3587 +654221,额敏县,4,654200
  3588 +654224,托里县,4,654200
  3589 +654225,裕民县,4,654200
  3590 +654226,和布克赛尔蒙古自治县,4,654200
  3591 +654301,阿勒泰市,4,654300
  3592 +654321,布尔津县,4,654300
  3593 +654322,富蕴县,4,654300
  3594 +654323,福海县,4,654300
  3595 +654324,哈巴河县,4,654300
  3596 +654325,青河县,4,654300
  3597 +654326,吉木乃县,4,654300
  3598 +659001,石河子市,4,659000
  3599 +659002,阿拉尔市,4,659000
  3600 +659003,图木舒克市,4,659000
  3601 +659004,五家渠市,4,659000
  3602 +659005,北屯市,4,659000
  3603 +659006,铁门关市,4,659000
  3604 +659007,双河市,4,659000
  3605 +659008,可克达拉市,4,659000
  3606 +659009,昆玉市,4,659000
  3607 +659010,胡杨河市,4,659000
  3608 +659011,新星市,4,659000
... ...
yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/resources/ip2region.xdb 0 → 100644
No preview for this file type
yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtilsTest.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ip.core.utils;
  2 +
  3 +
  4 +import cn.iocoder.yudao.framework.ip.core.Area;
  5 +import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum;
  6 +import org.junit.jupiter.api.Test;
  7 +
  8 +import static org.junit.jupiter.api.Assertions.assertEquals;
  9 +
  10 +/**
  11 + * {@link AreaUtils} 的单元测试
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +public class AreaUtilsTest {
  16 +
  17 + @Test
  18 + public void testGetArea() {
  19 + // 调用:北京
  20 + Area area = AreaUtils.getArea(110100);
  21 + // 断言
  22 + assertEquals(area.getId(), 110100);
  23 + assertEquals(area.getName(), "北京市");
  24 + assertEquals(area.getType(), AreaTypeEnum.CITY.getType());
  25 + assertEquals(area.getParent().getId(), 110000);
  26 + assertEquals(area.getChildren().size(), 16);
  27 + }
  28 +
  29 + @Test
  30 + public void testFormat() {
  31 + assertEquals(AreaUtils.format(110105), "北京 北京市 朝阳区");
  32 + assertEquals(AreaUtils.format(1), "中国");
  33 + assertEquals(AreaUtils.format(2), "蒙古");
  34 + }
  35 +
  36 +}
... ...
yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/IPUtilsTest.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ip.core.utils;
  2 +
  3 +import cn.iocoder.yudao.framework.ip.core.Area;
  4 +import org.junit.jupiter.api.Test;
  5 +import org.lionsoul.ip2region.xdb.Searcher;
  6 +
  7 +
  8 +import static org.junit.jupiter.api.Assertions.assertEquals;
  9 +
  10 +/**
  11 + * {@link IPUtils} 的单元测试
  12 + *
  13 + * @author wanglhup
  14 + */
  15 +public class IPUtilsTest {
  16 +
  17 + @Test
  18 + public void testGetAreaId_string() {
  19 + // 120.202.4.0|120.202.4.255|420600
  20 + Integer areaId = IPUtils.getAreaId("120.202.4.50");
  21 + assertEquals(420600, areaId);
  22 + }
  23 +
  24 + @Test
  25 + public void testGetAreaId_long() throws Exception {
  26 + // 120.203.123.0|120.203.133.255|360900
  27 + long ip = Searcher.checkIP("120.203.123.250");
  28 + Integer areaId = IPUtils.getAreaId(ip);
  29 + assertEquals(360900, areaId);
  30 + }
  31 +
  32 + @Test
  33 + public void testGetArea_string() {
  34 + // 120.202.4.0|120.202.4.255|420600
  35 + Area area = IPUtils.getArea("120.202.4.50");
  36 + assertEquals("襄阳市", area.getName());
  37 + }
  38 +
  39 + @Test
  40 + public void testGetArea_long() throws Exception {
  41 + // 120.203.123.0|120.203.133.255|360900
  42 + long ip = Searcher.checkIP("120.203.123.252");
  43 + Area area = IPUtils.getArea(ip);
  44 + assertEquals("宜春市", area.getName());
  45 + }
  46 +
  47 +}
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/PayProperties.java
... ... @@ -13,26 +13,23 @@ import javax.validation.constraints.NotEmpty;
13 13 public class PayProperties {
14 14  
15 15 /**
16   - * 支付回调地址
  16 + * 回调地址
  17 + *
  18 + * 实际上,对应的 PayNotifyController 的 notifyCallback 方法的 URL
  19 + *
17 20 * 注意,支付渠道统一回调到 payNotifyUrl 地址,由支付模块统一处理;然后,自己的支付模块,在回调 PayAppDO.payNotifyUrl 地址
18 21 */
19   - @NotEmpty(message = "支付回调地址不能为空")
20   - @URL(message = "支付回调地址的格式必须是 URL")
21   - private String payNotifyUrl;
22   - /**
23   - * 退款回调地址
24   - * 注意点,同 {@link #payNotifyUrl} 属性
25   - */
26   - @NotEmpty(message = "退款回调地址不能为空")
27   - @URL(message = "退款回调地址的格式必须是 URL")
28   - private String refundNotifyUrl;
29   -
  22 + @NotEmpty(message = "回调地址不能为空")
  23 + @URL(message = "回调地址的格式必须是 URL")
  24 + private String callbackUrl;
30 25  
31 26 /**
32   - * 支付完成的返回地址
  27 + * 回跳地址
  28 + *
  29 + * 实际上,对应的 PayNotifyController 的 returnCallback 方法的 URL
33 30 */
34   - @URL(message = "支付返回的地址的格式必须是 URL")
35   - @NotEmpty(message = "支付返回的地址不能为空")
36   - private String payReturnUrl;
  31 + @URL(message = "回跳地址的格式必须是 URL")
  32 + @NotEmpty(message = "回跳地址不能为空")
  33 + private String returnUrl;
37 34  
38 35 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayNotifyDataDTO.java
... ... @@ -21,9 +21,9 @@ public class PayNotifyDataDTO {
21 21 */
22 22 private String body;
23 23  
24   -
25 24 /**
26 25 * HTTP 回调接口 content type 为 application/x-www-form-urlencoded 的所有参数
27 26 */
28 27 private Map<String,String> params;
  28 +
29 29 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderUnifiedReqDTO.java
... ... @@ -62,7 +62,7 @@ public class PayOrderUnifiedReqDTO {
62 62 */
63 63 @NotNull(message = "支付金额不能为空")
64 64 @DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零")
65   - private Long amount;
  65 + private Integer amount;
66 66  
67 67 /**
68 68 * 支付过期时间
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundUnifiedReqDTO.java
... ... @@ -63,7 +63,7 @@ public class PayRefundUnifiedReqDTO {
63 63 */
64 64 @NotNull(message = "退款金额不能为空")
65 65 @DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零")
66   - private Long amount;
  66 + private Integer amount;
67 67  
68 68 /**
69 69 * 退款结果 notify 回调地址, 支付宝退款不需要回调地址, 微信需要
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java
... ... @@ -69,7 +69,7 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen
69 69 this.init();
70 70 }
71 71  
72   - protected Double calculateAmount(Long amount) {
  72 + protected Double calculateAmount(Integer amount) {
73 73 return amount / 100.0;
74 74 }
75 75  
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXLitePayClient.java
... ... @@ -26,6 +26,8 @@ import com.github.binarywang.wxpay.service.WxPayService;
26 26 import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
27 27 import lombok.extern.slf4j.Slf4j;
28 28  
  29 +import java.time.ZoneId;
  30 +import java.util.Date;
29 31 import java.util.Objects;
30 32  
31 33 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
... ... @@ -119,7 +121,7 @@ public class WXLitePayClient extends AbstractPayClient&lt;WXPayClientConfig&gt; {
119 121 .setTotal(reqDTO
120 122 .getAmount()
121 123 .intValue())); // 单位分
122   - request.setTimeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyy-MM-dd'T'HH:mm:ssXXX")); // v3的时间格式
  124 + request.setTimeExpire(DateUtil.format(Date.from(reqDTO.getExpireTime().atZone(ZoneId.systemDefault()).toInstant()), "yyyy-MM-dd'T'HH:mm:ssXXX")); // v3的时间格式
123 125 request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(getOpenid(reqDTO)));
124 126 request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()));
125 127 request.setNotifyUrl(reqDTO.getNotifyUrl());
... ... @@ -167,7 +169,8 @@ public class WXLitePayClient extends AbstractPayClient&lt;WXPayClientConfig&gt; {
167 169 return PayOrderNotifyRespDTO
168 170 .builder()
169 171 .orderExtensionNo(result.getOutTradeNo())
170   - .channelOrderNo(result.getTradeState())
  172 + .channelOrderNo(result.getTransactionId())
  173 + .channelUserId(result.getPayer().getOpenid())
171 174 .successTime(LocalDateTimeUtil.parse(result.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ssXXX"))
172 175 .data(data.getBody())
173 176 .build();
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXNativePayClient.java
... ... @@ -24,6 +24,8 @@ import com.github.binarywang.wxpay.service.WxPayService;
24 24 import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
25 25 import lombok.extern.slf4j.Slf4j;
26 26  
  27 +import java.time.ZoneId;
  28 +import java.util.Date;
27 29 import java.util.Objects;
28 30  
29 31 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
... ... @@ -98,7 +100,7 @@ public class WXNativePayClient extends AbstractPayClient&lt;WXPayClientConfig&gt; {
98 100 .outTradeNo(reqDTO.getMerchantOrderId())
99 101 .body(reqDTO.getBody())
100 102 .totalFee(reqDTO.getAmount().intValue()) // 单位分
101   - .timeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyy-MM-dd'T'HH:mm:ssXXX"))
  103 + .timeExpire(DateUtil.format(Date.from(reqDTO.getExpireTime().atZone(ZoneId.systemDefault()).toInstant()), "yyyy-MM-dd'T'HH:mm:ssXXX"))
102 104 .spbillCreateIp(reqDTO.getUserIp())
103 105 .notifyUrl(reqDTO.getNotifyUrl())
104 106 .productId(tradeType)
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPubPayClient.java
1 1 package cn.iocoder.yudao.framework.pay.core.client.impl.wx;
2 2  
3 3 import cn.hutool.core.bean.BeanUtil;
4   -import cn.hutool.core.date.DateUtil;
5 4 import cn.hutool.core.date.LocalDateTimeUtil;
  5 +import cn.hutool.core.date.TemporalAccessorUtil;
6 6 import cn.hutool.core.lang.Assert;
7 7 import cn.hutool.core.map.MapUtil;
8 8 import cn.hutool.core.util.StrUtil;
... ... @@ -26,6 +26,8 @@ import com.github.binarywang.wxpay.service.WxPayService;
26 26 import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
27 27 import lombok.extern.slf4j.Slf4j;
28 28  
  29 +import java.time.LocalDateTime;
  30 +import java.time.ZoneId;
29 31 import java.util.Objects;
30 32  
31 33 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
... ... @@ -98,8 +100,8 @@ public class WXPubPayClient extends AbstractPayClient&lt;WXPayClientConfig&gt; {
98 100 WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder()
99 101 .outTradeNo(reqDTO.getMerchantOrderId())
100 102 .body(reqDTO.getBody())
101   - .totalFee(reqDTO.getAmount().intValue()) // 单位分
102   - .timeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyy-MM-dd'T'HH:mm:ssXXX"))
  103 + .totalFee(reqDTO.getAmount()) // 单位分
  104 + .timeExpire(formatDate(reqDTO.getExpireTime()))
103 105 .spbillCreateIp(reqDTO.getUserIp())
104 106 .openid(getOpenid(reqDTO))
105 107 .notifyUrl(reqDTO.getNotifyUrl())
... ... @@ -113,8 +115,8 @@ public class WXPubPayClient extends AbstractPayClient&lt;WXPayClientConfig&gt; {
113 115 WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
114 116 request.setOutTradeNo(reqDTO.getMerchantOrderId());
115 117 request.setDescription(reqDTO.getBody());
116   - request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getAmount().intValue())); // 单位分
117   - request.setTimeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyy-MM-dd'T'HH:mm:ssXXX"));
  118 + request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getAmount())); // 单位分
  119 + request.setTimeExpire(formatDate(reqDTO.getExpireTime()));
118 120 request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(getOpenid(reqDTO)));
119 121 request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()));
120 122 request.setNotifyUrl(reqDTO.getNotifyUrl());
... ... @@ -194,4 +196,8 @@ public class WXPubPayClient extends AbstractPayClient&lt;WXPayClientConfig&gt; {
194 196 throw new UnsupportedOperationException();
195 197 }
196 198  
  199 + private static String formatDate(LocalDateTime time) {
  200 + return TemporalAccessorUtil.format(time.atZone(ZoneId.systemDefault()), "yyyy-MM-dd'T'HH:mm:ssXXX");
  201 + }
  202 +
197 203 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/test-integration/java/cn/iocoder/yudao/framework/core/client/impl/PayClientFactoryImplTest.java renamed to yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yudao.framework.pay.core.client.impl/PayClientFactoryImplIntegrationTest.java
1   -package cn.iocoder.yudao.framework.core.client.impl;
  1 +package cn.iocoder.yudao.framework.pay.core.client.impl;
2 2  
3 3 import cn.hutool.core.io.IoUtil;
4 4 import cn.hutool.core.util.RandomUtil;
... ... @@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 6 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
7 7 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
8 8 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
9   -import cn.iocoder.yudao.framework.pay.core.client.impl.PayClientFactoryImpl;
10 9 import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
11 10 import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayQrPayClient;
12 11 import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayWapPayClient;
... ... @@ -14,6 +13,7 @@ import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
14 13 import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPubPayClient;
15 14 import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
16 15 import com.alipay.api.response.AlipayTradePrecreateResponse;
  16 +import org.junit.jupiter.api.Disabled;
17 17 import org.junit.jupiter.api.Test;
18 18  
19 19 import java.io.FileInputStream;
... ... @@ -24,7 +24,8 @@ import java.io.FileNotFoundException;
24 24 *
25 25 * @author 芋道源码
26 26 */
27   -public class PayClientFactoryImplTest {
  27 +@Disabled
  28 +public class PayClientFactoryImplIntegrationTest {
28 29  
29 30 private final PayClientFactoryImpl payClientFactory = new PayClientFactoryImpl();
30 31  
... ... @@ -91,7 +92,7 @@ public class PayClientFactoryImplTest {
91 92 PayClient client = payClientFactory.getPayClient(channelId);
92 93 // 发起支付
93 94 PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO();
94   - reqDTO.setNotifyUrl("http://niubi.natapp1.cc/api/pay/order/notify/alipay-qr/1"); // TODO @tina: 这里改成你的 natapp 回调地址
  95 + reqDTO.setNotifyUrl("http://yunai.natapp1.cc/admin-api/pay/notify/callback/18"); // TODO @tina: 这里改成你的 natapp 回调地址
95 96 CommonResult<AlipayTradePrecreateResponse> result = (CommonResult<AlipayTradePrecreateResponse>) client.unifiedOrder(reqDTO);
96 97 System.out.println(JsonUtils.toJsonString(result));
97 98 System.out.println(result.getData().getQrCode());
... ... @@ -121,7 +122,7 @@ public class PayClientFactoryImplTest {
121 122  
122 123 private static PayOrderUnifiedReqDTO buildPayOrderUnifiedReqDTO() {
123 124 PayOrderUnifiedReqDTO reqDTO = new PayOrderUnifiedReqDTO();
124   - reqDTO.setAmount(123L);
  125 + reqDTO.setAmount(123);
125 126 reqDTO.setSubject("IPhone 13");
126 127 reqDTO.setBody("biubiubiu");
127 128 reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis()));
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yudao.framework.pay.core.client.impl/alipay/AlipayQrPayClientTest.java
... ... @@ -73,7 +73,7 @@ public class AlipayQrPayClientTest extends BaseMockitoUnitTest {
73 73 Long shopOrderId = System.currentTimeMillis();
74 74 PayOrderUnifiedReqDTO reqDTO=new PayOrderUnifiedReqDTO();
75 75 reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis()));
76   - reqDTO.setAmount(1L);
  76 + reqDTO.setAmount(1);
77 77 reqDTO.setBody("内容:" + shopOrderId);
78 78 reqDTO.setSubject("标题:"+shopOrderId);
79 79 String notify="http://niubi.natapp1.cc/api/pay/order/notify";
... ...
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java
... ... @@ -35,8 +35,8 @@ public class AliyunSmsCodeMapping implements SmsCodeMapping {
35 35 case "isv.OUT_OF_SERVICE": return SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH;
36 36 case "isv.MOBILE_NUMBER_ILLEGAL": return SmsFrameworkErrorCodeConstants.SMS_MOBILE_INVALID;
37 37 case "isv.TEMPLATE_MISSING_PARAMETERS": return SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR;
  38 + default: return SmsFrameworkErrorCodeConstants.SMS_UNKNOWN;
38 39 }
39   - return SmsFrameworkErrorCodeConstants.SMS_UNKNOWN;
40 40 }
41 41  
42 42 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/aop/TenantIgnoreAspect.java
1 1 package cn.iocoder.yudao.framework.tenant.core.aop;
2 2  
3 3 import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
  4 +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
4 5 import lombok.extern.slf4j.Slf4j;
5 6 import org.aspectj.lang.ProceedingJoinPoint;
6 7 import org.aspectj.lang.annotation.Around;
... ... @@ -11,6 +12,8 @@ import org.aspectj.lang.annotation.Aspect;
11 12 * 例如说,一个定时任务,读取所有数据,进行处理。
12 13 * 又例如说,读取所有数据,进行缓存。
13 14 *
  15 + * 整体逻辑的实现,和 {@link TenantUtils#executeIgnore(Runnable)} 需要保持一致
  16 + *
14 17 * @author 芋道源码
15 18 */
16 19 @Aspect
... ...
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/util/TenantUtils.java
... ... @@ -2,6 +2,10 @@ package cn.iocoder.yudao.framework.tenant.core.util;
2 2  
3 3 import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
4 4  
  5 +import java.util.Map;
  6 +
  7 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
  8 +
5 9 /**
6 10 * 多租户 Util
7 11 *
... ... @@ -32,4 +36,32 @@ public class TenantUtils {
32 36 }
33 37 }
34 38  
  39 + /**
  40 + * 忽略租户,执行对应的逻辑
  41 + *
  42 + * @param runnable 逻辑
  43 + */
  44 + public static void executeIgnore(Runnable runnable) {
  45 + Boolean oldIgnore = TenantContextHolder.isIgnore();
  46 + try {
  47 + TenantContextHolder.setIgnore(true);
  48 + // 执行逻辑
  49 + runnable.run();
  50 + } finally {
  51 + TenantContextHolder.setIgnore(oldIgnore);
  52 + }
  53 + }
  54 +
  55 + /**
  56 + * 将多租户编号,添加到 header 中
  57 + *
  58 + * @param headers HTTP 请求 headers
  59 + */
  60 + public static void addTenantHeader(Map<String, String> headers) {
  61 + Long tenantId = TenantContextHolder.getTenantId();
  62 + if (tenantId != null) {
  63 + headers.put(HEADER_TENANT_ID, tenantId.toString());
  64 + }
  65 + }
  66 +
35 67 }
... ...
yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java
... ... @@ -9,10 +9,11 @@ import io.minio.*;
9 9 import java.io.ByteArrayInputStream;
10 10  
11 11 import static cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig.ENDPOINT_ALIYUN;
  12 +import static cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig.ENDPOINT_TENCENT;
12 13  
13 14 /**
14 15 * 基于 S3 协议的文件客户端,实现 MinIO、阿里云、腾讯云、七牛云、华为云等云服务
15   - *
  16 + * <p>
16 17 * S3 协议的客户端,采用亚马逊提供的 software.amazon.awssdk.s3 库
17 18 *
18 19 * @author 芋道源码
... ... @@ -78,6 +79,11 @@ public class S3FileClient extends AbstractFileClient&lt;S3FileClientConfig&gt; {
78 79 .replaceAll("-internal", "")// 去除内网 Endpoint 的后缀
79 80 .replaceAll("https://", "");
80 81 }
  82 + // 腾讯云必须有 region,否则会报错
  83 + if (config.getEndpoint().contains(ENDPOINT_TENCENT)) {
  84 + return StrUtil.subAfter(config.getEndpoint(), ".cos.", false)
  85 + .replaceAll("." + ENDPOINT_TENCENT, ""); // 去除 Endpoint
  86 + }
81 87 return null;
82 88 }
83 89  
... ...
yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientConfig.java
... ... @@ -19,6 +19,7 @@ public class S3FileClientConfig implements FileClientConfig {
19 19  
20 20 public static final String ENDPOINT_QINIU = "qiniucs.com";
21 21 public static final String ENDPOINT_ALIYUN = "aliyuncs.com";
  22 + public static final String ENDPOINT_TENCENT = "myqcloud.com";
22 23  
23 24 /**
24 25 * 节点地址
... ...
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/config/YudaoMQAutoConfiguration.java
... ... @@ -8,8 +8,11 @@ import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
8 8 import cn.iocoder.yudao.framework.mq.core.interceptor.RedisMessageInterceptor;
9 9 import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener;
10 10 import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener;
  11 +import cn.iocoder.yudao.framework.mq.job.RedisPendingMessageResendJob;
11 12 import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
12 13 import lombok.extern.slf4j.Slf4j;
  14 +import org.redisson.api.RedissonClient;
  15 +import org.springframework.beans.factory.annotation.Value;
13 16 import org.springframework.boot.autoconfigure.AutoConfiguration;
14 17 import org.springframework.context.annotation.Bean;
15 18 import org.springframework.data.redis.connection.RedisServerCommands;
... ... @@ -24,7 +27,7 @@ import org.springframework.data.redis.listener.ChannelTopic;
24 27 import org.springframework.data.redis.listener.RedisMessageListenerContainer;
25 28 import org.springframework.data.redis.stream.DefaultStreamMessageListenerContainerX;
26 29 import org.springframework.data.redis.stream.StreamMessageListenerContainer;
27   -import org.springframework.scheduling.annotation.Async;
  30 +import org.springframework.scheduling.annotation.EnableScheduling;
28 31  
29 32 import java.util.List;
30 33 import java.util.Properties;
... ... @@ -35,6 +38,7 @@ import java.util.Properties;
35 38 * @author 芋道源码
36 39 */
37 40 @Slf4j
  41 +@EnableScheduling // 启用定时任务,用于 RedisPendingMessageResendJob 重发消息
38 42 @AutoConfiguration(after = YudaoRedisAutoConfiguration.class)
39 43 public class YudaoMQAutoConfiguration {
40 44  
... ... @@ -70,8 +74,19 @@ public class YudaoMQAutoConfiguration {
70 74 }
71 75  
72 76 /**
  77 + * 创建 Redis Stream 重新消费的任务
  78 + */
  79 + @Bean
  80 + public RedisPendingMessageResendJob redisPendingMessageResendJob(List<AbstractStreamMessageListener<?>> listeners,
  81 + RedisMQTemplate redisTemplate,
  82 + @Value("${spring.application.name}") String groupName,
  83 + RedissonClient redissonClient) {
  84 + return new RedisPendingMessageResendJob(listeners, redisTemplate, groupName, redissonClient);
  85 + }
  86 +
  87 + /**
73 88 * 创建 Redis Stream 集群消费的容器
74   - *
  89 + * <p>
75 90 * Redis Stream 的 xreadgroup 命令:https://www.geek-book.com/src/docs/redis/redis/redis.io/commands/xreadgroup.html
76 91 */
77 92 @Bean(initMethod = "start", destroyMethod = "stop")
... ... @@ -99,7 +114,8 @@ public class YudaoMQAutoConfiguration {
99 114 // 创建 listener 对应的消费者分组
100 115 try {
101 116 redisTemplate.opsForStream().createGroup(listener.getStreamKey(), listener.getGroup());
102   - } catch (Exception ignore) {}
  117 + } catch (Exception ignore) {
  118 + }
103 119 // 设置 listener 对应的 redisTemplate
104 120 listener.setRedisMQTemplate(redisMQTemplate);
105 121 // 创建 Consumer 对象
... ...
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/job/RedisPendingMessageResendJob.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.mq.job;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
  5 +import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener;
  6 +import lombok.AllArgsConstructor;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +import org.redisson.api.RLock;
  9 +import org.redisson.api.RedissonClient;
  10 +import org.springframework.data.redis.connection.stream.Consumer;
  11 +import org.springframework.data.redis.connection.stream.MapRecord;
  12 +import org.springframework.data.redis.connection.stream.PendingMessagesSummary;
  13 +import org.springframework.data.redis.connection.stream.ReadOffset;
  14 +import org.springframework.data.redis.connection.stream.StreamOffset;
  15 +import org.springframework.data.redis.connection.stream.StreamRecords;
  16 +import org.springframework.data.redis.core.StreamOperations;
  17 +import org.springframework.scheduling.annotation.Scheduled;
  18 +
  19 +import java.util.List;
  20 +import java.util.Map;
  21 +
  22 +/**
  23 + * 这个任务用于处理,crash 之后的消费者未消费完的消息
  24 + */
  25 +@Slf4j
  26 +@AllArgsConstructor
  27 +public class RedisPendingMessageResendJob {
  28 +
  29 + private static final String LOCK_KEY = "redis:pending:msg:lock";
  30 +
  31 + private final List<AbstractStreamMessageListener<?>> listeners;
  32 + private final RedisMQTemplate redisTemplate;
  33 + private final String groupName;
  34 + private final RedissonClient redissonClient;
  35 +
  36 + /**
  37 + * 一分钟执行一次,这里选择每分钟的35秒执行,是为了避免整点任务过多的问题
  38 + */
  39 + @Scheduled(cron = "35 * * * * ?")
  40 + public void messageResend() {
  41 + RLock lock = redissonClient.getLock(LOCK_KEY);
  42 + // 尝试加锁
  43 + if (lock.tryLock()) {
  44 + try {
  45 + execute();
  46 + } catch (Exception ex) {
  47 + log.error("[messageResend][执行异常]", ex);
  48 + } finally {
  49 + lock.unlock();
  50 + }
  51 + }
  52 + }
  53 +
  54 + private void execute() {
  55 + StreamOperations<String, Object, Object> ops = redisTemplate.getRedisTemplate().opsForStream();
  56 + listeners.forEach(listener -> {
  57 + PendingMessagesSummary pendingMessagesSummary = ops.pending(listener.getStreamKey(), groupName);
  58 + // 每个消费者的 pending 队列消息数量
  59 + Map<String, Long> pendingMessagesPerConsumer = pendingMessagesSummary.getPendingMessagesPerConsumer();
  60 + pendingMessagesPerConsumer.forEach((consumerName, pendingMessageCount) -> {
  61 + log.info("[processPendingMessage][消费者({}) 消息数量({})]", consumerName, pendingMessageCount);
  62 +
  63 + // 从消费者的 pending 队列中读取消息
  64 + List<MapRecord<String, Object, Object>> records = ops.read(Consumer.from(groupName, consumerName), StreamOffset.create(listener.getStreamKey(), ReadOffset.from("0")));
  65 + if (CollUtil.isEmpty(records)) {
  66 + return;
  67 + }
  68 + for (MapRecord<String, Object, Object> record : records) {
  69 + // 重新投递消息
  70 + redisTemplate.getRedisTemplate().opsForStream().add(StreamRecords.newRecord()
  71 + .ofObject(record.getValue()) // 设置内容
  72 + .withStreamKey(listener.getStreamKey()));
  73 +
  74 + // ack 消息消费完成
  75 + redisTemplate.getRedisTemplate().opsForStream().acknowledge(groupName, record);
  76 + }
  77 + });
  78 + });
  79 + }
  80 +}
... ...
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.mybatis.core.mapper;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
5 6 import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
6 7 import com.baomidou.mybatisplus.core.conditions.Wrapper;
7 8 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
... ... @@ -75,9 +76,13 @@ public interface BaseMapperX&lt;T&gt; extends BaseMapper&lt;T&gt; {
75 76 return selectList(new LambdaQueryWrapper<T>().in(field, values));
76 77 }
77 78  
  79 + default List<T> selectList(SFunction<T, ?> leField, SFunction<T, ?> geField, Object value) {
  80 + return selectList(new LambdaQueryWrapper<T>().le(leField, value).ge(geField, value));
  81 + }
  82 +
78 83 /**
79 84 * 逐条插入,适合少量数据插入,或者对性能要求不高的场景
80   - *
  85 + * <p>
81 86 * 如果大量,请使用 {@link com.baomidou.mybatisplus.extension.service.impl.ServiceImpl#saveBatch(Collection)} 方法
82 87 * 使用示例,可见 RoleMenuBatchInsertMapper、UserRoleBatchInsertMapper 类
83 88 *
... ...
yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/AssertUtils.java
... ... @@ -33,6 +33,10 @@ public class AssertUtils {
33 33 public static void assertPojoEquals(Object expected, Object actual, String... ignoreFields) {
34 34 Field[] expectedFields = ReflectUtil.getFields(expected.getClass());
35 35 Arrays.stream(expectedFields).forEach(expectedField -> {
  36 + // 忽略 jacoco 自动生成的 $jacocoData 属性的情况
  37 + if (expectedField.isSynthetic()) {
  38 + return;
  39 + }
36 40 // 如果是忽略的属性,则不进行比对
37 41 if (ArrayUtil.contains(ignoreFields, expectedField.getName())) {
38 42 return;
... ...
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalTimeJson.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.jackson.core.databind;
  2 +
  3 +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
  4 +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
  5 +
  6 +import java.time.ZoneId;
  7 +import java.time.format.DateTimeFormatter;
  8 +
  9 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_HOUR_MINUTE_SECOND;
  10 +
  11 +public class LocalTimeJson {
  12 +
  13 + public static final LocalTimeSerializer SERIALIZER = new LocalTimeSerializer(DateTimeFormatter
  14 + .ofPattern(FORMAT_HOUR_MINUTE_SECOND)
  15 + .withZone(ZoneId.systemDefault()));
  16 +
  17 + public static final LocalTimeDeserializer DESERIALIZABLE = new LocalTimeDeserializer(DateTimeFormatter
  18 + .ofPattern(FORMAT_HOUR_MINUTE_SECOND)
  19 + .withZone(ZoneId.systemDefault()));
  20 +
  21 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/test/resources/application-unit-test.yaml
... ... @@ -9,7 +9,7 @@ spring:
9 9 # 数据源配置项
10 10 datasource:
11 11 name: ruoyi-vue-pro
12   - url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
  12 + url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
13 13 driver-class-name: org.h2.Driver
14 14 username: sa
15 15 password:
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileContentDAOImpl.java
1 1 package cn.iocoder.yudao.module.infra.dal.mysql.file;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.iocoder.yudao.framework.file.core.client.db.DBFileContentFrameworkDAO;
4 5 import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileContentDO;
5 6 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
6 7 import org.springframework.stereotype.Repository;
7 8  
8 9 import javax.annotation.Resource;
  10 +import java.util.List;
  11 +import java.util.Optional;
9 12  
10 13 @Repository
11 14 public class FileContentDAOImpl implements DBFileContentFrameworkDAO {
... ... @@ -27,9 +30,11 @@ public class FileContentDAOImpl implements DBFileContentFrameworkDAO {
27 30  
28 31 @Override
29 32 public byte[] selectContent(Long configId, String path) {
30   - FileContentDO fileContentDO = fileContentMapper.selectOne(
31   - buildQuery(configId, path).select(FileContentDO::getContent));
32   - return fileContentDO != null ? fileContentDO.getContent() : null;
  33 + List<FileContentDO> list = fileContentMapper.selectList(
  34 + buildQuery(configId, path).select(FileContentDO::getContent).orderByDesc(FileContentDO::getId));
  35 + return Optional.ofNullable(CollUtil.getFirst(list))
  36 + .map(FileContentDO::getContent)
  37 + .orElse(null);
33 38 }
34 39  
35 40 private LambdaQueryWrapper<FileContentDO> buildQuery(Long configId, String path) {
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java
... ... @@ -18,6 +18,8 @@ import org.springframework.stereotype.Component;
18 18 import java.util.*;
19 19  
20 20 import static cn.hutool.core.text.CharSequenceUtil.*;
  21 +import static cn.hutool.core.util.RandomUtil.randomEle;
  22 +import static cn.hutool.core.util.RandomUtil.randomInt;
21 23  
22 24 /**
23 25 * 代码生成器的 Builder,负责:
... ... @@ -128,6 +130,7 @@ public class CodegenBuilder {
128 130 // 初始化 Column 列的默认字段
129 131 processColumnOperation(column); // 处理 CRUD 相关的字段的默认值
130 132 processColumnUI(column); // 处理 UI 相关的字段的默认值
  133 + processColumnExample(column); // 处理字段的 swagger example 示例
131 134 }
132 135 return columns;
133 136 }
... ... @@ -169,4 +172,42 @@ public class CodegenBuilder {
169 172 }
170 173 }
171 174  
  175 + /**
  176 + * 处理字段的 swagger example 示例
  177 + *
  178 + * @param column 字段
  179 + */
  180 + private void processColumnExample(CodegenColumnDO column) {
  181 + // id、price、count 等可能是整数的后缀
  182 + if (StrUtil.endWithAnyIgnoreCase(column.getJavaField(), "id", "price", "count")) {
  183 + column.setExample(String.valueOf(randomInt(1, Short.MAX_VALUE)));
  184 + return;
  185 + }
  186 + // name
  187 + if (StrUtil.endWithIgnoreCase(column.getJavaField(), "name")) {
  188 + column.setExample(randomEle(new String[]{"张三", "李四", "王五", "赵六", "芋艿"}));
  189 + return;
  190 + }
  191 + // status
  192 + if (StrUtil.endWithAnyIgnoreCase(column.getJavaField(), "status", "type")) {
  193 + column.setExample(randomEle(new String[]{"1", "2"}));
  194 + return;
  195 + }
  196 + // url
  197 + if (StrUtil.endWithIgnoreCase(column.getColumnName(), "url")) {
  198 + column.setExample("https://www.iocoder.cn");
  199 + return;
  200 + }
  201 + // reason
  202 + if (StrUtil.endWithIgnoreCase(column.getColumnName(), "reason")) {
  203 + column.setExample(randomEle(new String[]{"不喜欢", "不对", "不好", "不香"}));
  204 + return;
  205 + }
  206 + // description、memo、remark
  207 + if (StrUtil.endWithAnyIgnoreCase(column.getColumnName(), "description", "memo", "remark")) {
  208 + column.setExample(randomEle(new String[]{"你猜", "随便", "你说的对"}));
  209 + return;
  210 + }
  211 + }
  212 +
172 213 }
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java
1 1 package cn.iocoder.yudao.module.infra.service.file;
2 2  
3   -import cn.hutool.core.collection.CollUtil;
4 3 import cn.hutool.core.io.resource.ResourceUtil;
5 4 import cn.hutool.core.util.IdUtil;
6 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
... ... @@ -20,7 +19,6 @@ import cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper;
20 19 import cn.iocoder.yudao.module.infra.mq.producer.file.FileConfigProducer;
21 20 import lombok.Getter;
22 21 import lombok.extern.slf4j.Slf4j;
23   -import org.springframework.context.annotation.Lazy;
24 22 import org.springframework.scheduling.annotation.Scheduled;
25 23 import org.springframework.stereotype.Service;
26 24 import org.springframework.transaction.annotation.Transactional;
... ... @@ -79,20 +77,36 @@ public class FileConfigServiceImpl implements FileConfigService {
79 77 @Resource
80 78 private Validator validator;
81 79  
82   - @Resource
83   - @Lazy // 注入自己,所以延迟加载
84   - private FileConfigService self;
85   -
86 80 @Override
87 81 @PostConstruct
88 82 public void initFileClients() {
89   - // 获取文件配置,如果有更新
90   - List<FileConfigDO> configs = loadFileConfigIfUpdate(maxUpdateTime);
91   - if (CollUtil.isEmpty(configs)) {
  83 + initLocalCacheIfUpdate(null);
  84 + }
  85 +
  86 + @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
  87 + public void schedulePeriodicRefresh() {
  88 + initLocalCacheIfUpdate(this.maxUpdateTime);
  89 + }
  90 +
  91 + /**
  92 + * 刷新本地缓存
  93 + *
  94 + * @param maxUpdateTime 最大更新时间
  95 + * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存
  96 + * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存
  97 + */
  98 + private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) {
  99 + // 第一步:基于 maxUpdateTime 判断缓存是否刷新。
  100 + // 如果没有增量的数据变化,则不进行本地缓存的刷新
  101 + if (maxUpdateTime != null
  102 + && fileConfigMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
  103 + log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime);
92 104 return;
93 105 }
  106 + List<FileConfigDO> configs = fileConfigMapper.selectList();
  107 + log.info("[initLocalCacheIfUpdate][缓存文件配置,数量为:{}]", configs.size());
94 108  
95   - // 创建或更新支付 Client
  109 + // 第二步:构建缓存。创建或更新文件 Client
96 110 configs.forEach(config -> {
97 111 fileClientFactory.createOrUpdateFileClient(config.getId(), config.getStorage(), config.getConfig());
98 112 // 如果是 master,进行设置
... ... @@ -101,35 +115,8 @@ public class FileConfigServiceImpl implements FileConfigService {
101 115 }
102 116 });
103 117  
104   - // 写入缓存
105   - maxUpdateTime = CollectionUtils.getMaxValue(configs, FileConfigDO::getUpdateTime);
106   - log.info("[initFileClients][初始化 FileConfig 数量为 {}]", configs.size());
107   - }
108   -
109   - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
110   - public void schedulePeriodicRefresh() {
111   - self.initFileClients();
112   - }
113   -
114   - /**
115   - * 如果文件配置发生变化,从数据库中获取最新的全量文件配置。
116   - * 如果未发生变化,则返回空
117   - *
118   - * @param maxUpdateTime 当前文件配置的最大更新时间
119   - * @return 文件配置列表
120   - */
121   - private List<FileConfigDO> loadFileConfigIfUpdate(LocalDateTime maxUpdateTime) {
122   - // 第一步,判断是否要更新。
123   - if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
124   - log.info("[loadFileConfigIfUpdate][首次加载全量文件配置]");
125   - } else { // 判断数据库中是否有更新的文件配置
126   - if (fileConfigMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
127   - return null;
128   - }
129   - log.info("[loadFileConfigIfUpdate][增量加载全量文件配置]");
130   - }
131   - // 第二步,如果有更新,则从数据库加载所有文件配置
132   - return fileConfigMapper.selectList();
  118 + // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。
  119 + this.maxUpdateTime = CollectionUtils.getMaxValue(configs, FileConfigDO::getUpdateTime);
133 120 }
134 121  
135 122 @Override
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm
1 1 <template>
2 2 <ContentWrap>
3 3 <!-- 列表 -->
4   - <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
  4 + <XTable @register="registerTable">
5 5 <template #toolbar_buttons>
6 6 <!-- 操作:新增 -->
7 7 <XButton
... ... @@ -43,7 +43,7 @@
43 43 @click="handleDelete(row.id)"
44 44 />
45 45 </template>
46   - </vxe-grid>
  46 + </XTable>
47 47 </ContentWrap>
48 48 <!-- 弹窗 -->
49 49 <XModal id="${classNameVar}Model" :loading="modelLoading" v-model="modelVisible" :title="modelTitle">
... ... @@ -79,8 +79,7 @@
79 79 import { ref, unref } from 'vue'
80 80 import { useI18n } from '@/hooks/web/useI18n'
81 81 import { useMessage } from '@/hooks/web/useMessage'
82   -import { useVxeGrid } from '@/hooks/web/useVxeGrid'
83   -import { VxeGridInstance } from 'vxe-table'
  82 +import { useXTable } from '@/hooks/web/useXTable'
84 83 import { FormExpose } from '@/components/Form'
85 84 // 业务相关的 import
86 85 import { rules, allSchemas } from './${classNameVar}.data'
... ... @@ -90,8 +89,7 @@ const { t } = useI18n() // 国际化
90 89 const message = useMessage() // 消息弹窗
91 90  
92 91 // 列表相关的变量
93   -const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
94   -const { gridOptions, getList, deleteData, exportList } = useVxeGrid<${simpleClassName}Api.${simpleClassName}VO>({
  92 +const [registerTable, { reload, deleteData, exportList }] = useXTable({
95 93 allSchemas: allSchemas,
96 94 getListApi: ${simpleClassName}Api.get${simpleClassName}PageApi,
97 95 deleteApi: ${simpleClassName}Api.delete${simpleClassName}Api,
... ... @@ -123,7 +121,7 @@ const handleCreate = () =&gt; {
123 121  
124 122 // 导出操作
125 123 const handleExport = async () => {
126   - await exportList(xGrid, '${table.classComment}.xls')
  124 + await exportList('${table.classComment}.xls')
127 125 }
128 126  
129 127 // 修改操作
... ... @@ -145,7 +143,7 @@ const handleDetail = async (rowId: number) =&gt; {
145 143  
146 144 // 删除操作
147 145 const handleDelete = async (rowId: number) => {
148   - await deleteData(xGrid, rowId)
  146 + await deleteData(rowId)
149 147 }
150 148  
151 149 // 提交按钮
... ... @@ -169,7 +167,7 @@ const submitForm = async () =&gt; {
169 167 } finally {
170 168 actionLoading.value = false
171 169 // 刷新列表
172   - await getList(xGrid)
  170 + await reload()
173 171 }
174 172 }
175 173 })
... ...
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java
... ... @@ -79,7 +79,7 @@ public class FileServiceTest extends BaseDbUnitTest {
79 79 FileClient client = mock(FileClient.class);
80 80 when(fileConfigService.getMasterFileClient()).thenReturn(client);
81 81 String url = randomString();
82   - when(client.upload(same(content), same(path), same("image/jpeg"))).thenReturn(url);
  82 + when(client.upload(same(content), same(path), eq("image/jpeg"))).thenReturn(url);
83 83 when(client.getId()).thenReturn(10L);
84 84 String name = "单测文件名";
85 85 // 调用
... ...
yudao-module-infra/yudao-module-infra-biz/src/test/resources/application-unit-test.yaml
... ... @@ -9,7 +9,7 @@ spring:
9 9 # 数据源配置项
10 10 datasource:
11 11 name: ruoyi-vue-pro
12   - url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
  12 + url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
13 13 driver-class-name: org.h2.Driver
14 14 username: sa
15 15 password:
... ...
yudao-module-mall/pom.xml
... ... @@ -15,18 +15,15 @@
15 15 <name>${project.artifactId}</name>
16 16  
17 17 <description>
18   - 商城大模块,由 product 商品、promotion 营销、trade 交易 coupon等组成
  18 + 商城大模块,由 product 商品、promotion 营销、trade 交易等组成
19 19 </description>
20 20 <modules>
21   -<!-- <module>yudao-module-coupon-api</module>-->
22   -<!-- <module>yudao-module-coupon-biz</module>-->
23 21 <module>yudao-module-promotion-api</module>
24 22 <module>yudao-module-promotion-biz</module>
25 23 <module>yudao-module-product-api</module>
26 24 <module>yudao-module-product-biz</module>
27 25 <module>yudao-module-trade-api</module>
28 26 <module>yudao-module-trade-biz</module>
29   -
30 27 </modules>
31 28  
32 29 </project>
... ...
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApi.java 0 → 100644
  1 +package cn.iocoder.yudao.module.product.api.property;
  2 +
  3 +import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
  4 +
  5 +import java.util.Collection;
  6 +import java.util.List;
  7 +
  8 +/**
  9 + * 商品属性值 API 接口
  10 + *
  11 + * @author 芋道源码
  12 + */
  13 +public interface ProductPropertyValueApi {
  14 +
  15 + /**
  16 + * 根据编号数组,获得属性值列表
  17 + *
  18 + * @param ids 编号数组
  19 + * @return 属性值明细列表
  20 + */
  21 + List<ProductPropertyValueDetailRespDTO> getPropertyValueDetailList(Collection<Long> ids);
  22 +
  23 +}
... ...
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.product.api.property.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * 商品属性项的明细 Response DTO
  7 + *
  8 + * @author 芋道源码
  9 + */
  10 +@Data
  11 +public class ProductPropertyValueDetailRespDTO {
  12 +
  13 + /**
  14 + * 属性的编号
  15 + */
  16 + private Long propertyId;
  17 +
  18 + /**
  19 + * 属性的名称
  20 + */
  21 + private String propertyName;
  22 +
  23 + /**
  24 + * 属性值的编号
  25 + */
  26 + private Long valueId;
  27 +
  28 + /**
  29 + * 属性值的名称
  30 + */
  31 + private String valueName;
  32 +
  33 +}
... ...
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java
... ... @@ -19,16 +19,16 @@ public class ProductSkuRespDTO {
19 19 */
20 20 private Long id;
21 21 /**
22   - * 商品 SKU 名字
23   - */
24   - private String name;
25   - /**
26 22 * SPU 编号
27 23 */
28 24 private Long spuId;
  25 + /**
  26 + * SPU 名字
  27 + */
  28 + private String spuName;
29 29  
30 30 /**
31   - * 规格值数组,JSON 格式
  31 + * 属性数组,JSON 格式
32 32 */
33 33 private List<Property> properties;
34 34 /**
... ...
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
... ... @@ -15,28 +15,30 @@ public interface ErrorCodeConstants {
15 15 ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类");
16 16 ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除");
17 17 ErrorCode CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用");
18   - ErrorCode CATEGORY_LEVEL_ERROR = new ErrorCode(1008001005, "商品分类不正确,原因:必须使用第三级的商品分类下");
19 18  
20 19 // ========== 商品品牌相关编号 1008002000 ==========
21 20 ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
22 21 ErrorCode BRAND_DISABLED = new ErrorCode(1008002001, "品牌不存在");
23 22 ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1008002002, "品牌名称已存在");
24 23  
25   - // ========== 商品规格名称 1008003000 ==========
26   - ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "规格名称不存在");
27   - ErrorCode PROPERTY_EXISTS = new ErrorCode(1008003001, "规格名称已存在");
  24 + // ========== 商品属性项 1008003000 ==========
  25 + ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "属性项不存在");
  26 + ErrorCode PROPERTY_EXISTS = new ErrorCode(1008003001, "属性项的名称已存在");
  27 + ErrorCode PROPERTY_DELETE_FAIL_VALUE_EXISTS = new ErrorCode(1008003002, "属性项下存在属性值,无法删除");
28 28  
29   - // ========== 规格值 1008004000 ==========
30   - ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "规格值不存在");
31   - ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1008004001, "规格值已存在");
  29 + // ========== 商品属性值 1008004000 ==========
  30 + ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "属性值不存在");
  31 + ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1008004001, "属性值的名称已存在");
32 32  
33 33 // ========== 商品 SPU 1008005000 ==========
34 34 ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在");
  35 + ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1008005001, "商品分类不正确,原因:必须使用第三级的商品分类下");
  36 + ErrorCode SPU_NOT_ENABLE = new ErrorCode(1008005002, "商品 SPU 不处于上架状态");
35 37  
36 38 // ========== 商品 SKU 1008006000 ==========
37 39 ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在");
38 40 ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品 SKU 的属性组合存在重复");
39   - ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 SPU 下的每个 SKU,其规格数必须一致");
  41 + ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 SPU 下的每个 SKU,其属性项必须一致");
40 42 ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU,必须不重复");
41 43 ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1008006004, "商品 SKU 库存不足");
42 44  
... ...
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java
... ... @@ -21,11 +21,11 @@ public enum ProductSpuSpecTypeEnum implements IntArrayValuable {
21 21 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuSpecTypeEnum::getType).toArray();
22 22  
23 23 /**
24   - * 规格
  24 + * 规格类型
25 25 */
26 26 private final Integer type;
27 27 /**
28   - * 规格名
  28 + * 规格名称
29 29 */
30 30 private final String name;
31 31  
... ...
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java
... ... @@ -35,4 +35,14 @@ public enum ProductSpuStatusEnum implements IntArrayValuable {
35 35 return ARRAYS;
36 36 }
37 37  
  38 + /**
  39 + * 判断是否处于【上架】状态
  40 + *
  41 + * @param status 状态
  42 + * @return 是否处于【上架】状态
  43 + */
  44 + public static boolean isEnable(Integer status) {
  45 + return ENABLE.getStatus().equals(status);
  46 + }
  47 +
38 48 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApiImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.product.api.property;
  2 +
  3 +import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
  4 +import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert;
  5 +import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
  6 +import org.springframework.stereotype.Service;
  7 +import org.springframework.validation.annotation.Validated;
  8 +
  9 +import javax.annotation.Resource;
  10 +import java.util.Collection;
  11 +import java.util.List;
  12 +
  13 +/**
  14 + * 商品属性值 API 实现类
  15 + *
  16 + * @author 芋道源码
  17 + */
  18 +@Service
  19 +@Validated
  20 +public class ProductPropertyValueApiImpl implements ProductPropertyValueApi {
  21 +
  22 + @Resource
  23 + private ProductPropertyValueService productPropertyValueService;
  24 +
  25 + @Override
  26 + public List<ProductPropertyValueDetailRespDTO> getPropertyValueDetailList(Collection<Long> ids) {
  27 + return ProductPropertyValueConvert.INSTANCE.convertList02(
  28 + productPropertyValueService.getPropertyValueDetailList(ids));
  29 + }
  30 +
  31 +}
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java
1 1 package cn.iocoder.yudao.module.product.controller.admin.property;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 6 import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*;
  7 +import cn.iocoder.yudao.module.product.convert.property.ProductPropertyConvert;
  8 +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
  9 +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
6 10 import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
  11 +import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
7 12 import io.swagger.v3.oas.annotations.tags.Tag;
8 13 import io.swagger.v3.oas.annotations.Parameter;
9 14 import io.swagger.v3.oas.annotations.Operation;
... ... @@ -13,12 +18,13 @@ import org.springframework.web.bind.annotation.*;
13 18  
14 19 import javax.annotation.Resource;
15 20 import javax.validation.Valid;
16   -
  21 +import java.util.Collections;
17 22 import java.util.List;
18 23  
19 24 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  25 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
20 26  
21   -@Tag(name = "管理后台 - 规格名称")
  27 +@Tag(name = "管理后台 - 商品属性项")
22 28 @RestController
23 29 @RequestMapping("/product/property")
24 30 @Validated
... ... @@ -26,16 +32,18 @@ public class ProductPropertyController {
26 32  
27 33 @Resource
28 34 private ProductPropertyService productPropertyService;
  35 + @Resource
  36 + private ProductPropertyValueService productPropertyValueService;
29 37  
30 38 @PostMapping("/create")
31   - @Operation(summary = "创建规格名称")
  39 + @Operation(summary = "创建属性项")
32 40 @PreAuthorize("@ss.hasPermission('product:property:create')")
33 41 public CommonResult<Long> createProperty(@Valid @RequestBody ProductPropertyCreateReqVO createReqVO) {
34 42 return success(productPropertyService.createProperty(createReqVO));
35 43 }
36 44  
37 45 @PutMapping("/update")
38   - @Operation(summary = "更新规格名称")
  46 + @Operation(summary = "更新属性项")
39 47 @PreAuthorize("@ss.hasPermission('product:property:update')")
40 48 public CommonResult<Boolean> updateProperty(@Valid @RequestBody ProductPropertyUpdateReqVO updateReqVO) {
41 49 productPropertyService.updateProperty(updateReqVO);
... ... @@ -43,7 +51,7 @@ public class ProductPropertyController {
43 51 }
44 52  
45 53 @DeleteMapping("/delete")
46   - @Operation(summary = "删除规格名称")
  54 + @Operation(summary = "删除属性项")
47 55 @Parameter(name = "id", description = "编号", required = true)
48 56 @PreAuthorize("@ss.hasPermission('product:property:delete')")
49 57 public CommonResult<Boolean> deleteProperty(@RequestParam("id") Long id) {
... ... @@ -52,32 +60,40 @@ public class ProductPropertyController {
52 60 }
53 61  
54 62 @GetMapping("/get")
55   - @Operation(summary = "获得规格名称")
  63 + @Operation(summary = "获得属性项")
56 64 @Parameter(name = "id", description = "编号", required = true, example = "1024")
57 65 @PreAuthorize("@ss.hasPermission('product:property:query')")
58 66 public CommonResult<ProductPropertyRespVO> getProperty(@RequestParam("id") Long id) {
59   - return success(productPropertyService.getProperty(id));
  67 + return success(ProductPropertyConvert.INSTANCE.convert(productPropertyService.getProperty(id)));
60 68 }
61 69  
62 70 @GetMapping("/list")
63   - @Operation(summary = "获得规格名称列表")
  71 + @Operation(summary = "获得属性项列表")
64 72 @PreAuthorize("@ss.hasPermission('product:property:query')")
65 73 public CommonResult<List<ProductPropertyRespVO>> getPropertyList(@Valid ProductPropertyListReqVO listReqVO) {
66   - return success(productPropertyService.getPropertyList(listReqVO));
  74 + return success(ProductPropertyConvert.INSTANCE.convertList(productPropertyService.getPropertyList(listReqVO)));
67 75 }
68 76  
69 77 @GetMapping("/page")
70   - @Operation(summary = "获得规格名称分页")
  78 + @Operation(summary = "获得属性项分页")
71 79 @PreAuthorize("@ss.hasPermission('product:property:query')")
72 80 public CommonResult<PageResult<ProductPropertyRespVO>> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) {
73   - return success(productPropertyService.getPropertyPage(pageVO));
  81 + return success(ProductPropertyConvert.INSTANCE.convertPage(productPropertyService.getPropertyPage(pageVO)));
74 82 }
75 83  
76   - @GetMapping("/listAndValue")
77   - @Operation(summary = "获得规格名称列表")
  84 + @GetMapping("/get-value-list")
  85 + @Operation(summary = "获得属性项列表")
78 86 @PreAuthorize("@ss.hasPermission('product:property:query')")
79 87 public CommonResult<List<ProductPropertyAndValueRespVO>> getPropertyAndValueList(@Valid ProductPropertyListReqVO listReqVO) {
80   - return success(productPropertyService.getPropertyAndValueList(listReqVO));
  88 + // 查询属性项
  89 + List<ProductPropertyDO> keys = productPropertyService.getPropertyList(listReqVO);
  90 + if (CollUtil.isEmpty(keys)) {
  91 + return success(Collections.emptyList());
  92 + }
  93 + // 查询属性值
  94 + List<ProductPropertyValueDO> values = productPropertyValueService.getPropertyValueListByPropertyId(
  95 + convertSet(keys, ProductPropertyDO::getId));
  96 + return success(ProductPropertyConvert.INSTANCE.convertList(keys, values));
81 97 }
82 98  
83 99 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java
... ... @@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.product.controller.admin.property;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5   -import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO;
6 5 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
7 6 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
8 7 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
9 8 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
  9 +import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert;
10 10 import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
11 11 import io.swagger.v3.oas.annotations.tags.Tag;
12 12 import io.swagger.v3.oas.annotations.Parameter;
... ... @@ -20,7 +20,7 @@ import javax.validation.Valid;
20 20  
21 21 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
22 22  
23   -@Tag(name = "管理后台 - 规格值名称")
  23 +@Tag(name = "管理后台 - 商品属性值")
24 24 @RestController
25 25 @RequestMapping("/product/property/value")
26 26 @Validated
... ... @@ -30,14 +30,14 @@ public class ProductPropertyValueController {
30 30 private ProductPropertyValueService productPropertyValueService;
31 31  
32 32 @PostMapping("/create")
33   - @Operation(summary = "创建规格名称")
  33 + @Operation(summary = "创建属性值")
34 34 @PreAuthorize("@ss.hasPermission('product:property:create')")
35 35 public CommonResult<Long> createProperty(@Valid @RequestBody ProductPropertyValueCreateReqVO createReqVO) {
36 36 return success(productPropertyValueService.createPropertyValue(createReqVO));
37 37 }
38 38  
39 39 @PutMapping("/update")
40   - @Operation(summary = "更新规格名称")
  40 + @Operation(summary = "更新属性值")
41 41 @PreAuthorize("@ss.hasPermission('product:property:update')")
42 42 public CommonResult<Boolean> updateProperty(@Valid @RequestBody ProductPropertyValueUpdateReqVO updateReqVO) {
43 43 productPropertyValueService.updatePropertyValue(updateReqVO);
... ... @@ -45,7 +45,7 @@ public class ProductPropertyValueController {
45 45 }
46 46  
47 47 @DeleteMapping("/delete")
48   - @Operation(summary = "删除规格名称")
  48 + @Operation(summary = "删除属性值")
49 49 @Parameter(name = "id", description = "编号", required = true)
50 50 @PreAuthorize("@ss.hasPermission('product:property:delete')")
51 51 public CommonResult<Boolean> deleteProperty(@RequestParam("id") Long id) {
... ... @@ -54,17 +54,17 @@ public class ProductPropertyValueController {
54 54 }
55 55  
56 56 @GetMapping("/get")
57   - @Operation(summary = "获得规格名称")
  57 + @Operation(summary = "获得属性值")
58 58 @Parameter(name = "id", description = "编号", required = true, example = "1024")
59 59 @PreAuthorize("@ss.hasPermission('product:property:query')")
60 60 public CommonResult<ProductPropertyValueRespVO> getProperty(@RequestParam("id") Long id) {
61   - return success(productPropertyValueService.getPropertyValue(id));
  61 + return success(ProductPropertyValueConvert.INSTANCE.convert(productPropertyValueService.getPropertyValue(id)));
62 62 }
63 63  
64 64 @GetMapping("/page")
65   - @Operation(summary = "获得规格名称分页")
  65 + @Operation(summary = "获得属性值分页")
66 66 @PreAuthorize("@ss.hasPermission('product:property:query')")
67 67 public CommonResult<PageResult<ProductPropertyValueRespVO>> getPropertyValuePage(@Valid ProductPropertyValuePageReqVO pageVO) {
68   - return success(productPropertyValueService.getPropertyValueListPage(pageVO));
  68 + return success(ProductPropertyValueConvert.INSTANCE.convertPage(productPropertyValueService.getPropertyValuePage(pageVO)));
69 69 }
70 70 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java
1   -package cn.iocoder.yudao.module.product.controller.admin.property.vo;
2   -
3   -import io.swagger.v3.oas.annotations.media.Schema;
4   -import lombok.Data;
5   -import lombok.ToString;
6   -
7   -import java.util.List;
8   -
9   -/**
10   - * @Description: ProductPropertyViewRespVO
11   - * @Author: franky
12   - * @CreateDate: 2022/7/5 21:29
13   - * @Version: 1.0.0
14   - */
15   -@Schema(description = "管理后台 - 规格名称详情展示 Request VO")
16   -@Data
17   -@ToString(callSuper = true)
18   -public class ProductPropertyViewRespVO {
19   -
20   - @Schema(description = "规格名称id", example = "1")
21   - public Long propertyId;
22   -
23   - @Schema(description = "规格名称", example = "内存")
24   - public String name;
25   -
26   - @Schema(description = "规格属性值集合", example = "[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]")
27   - public List<Tuple2> propertyValues;
28   -
29   - @Data
30   - @Schema(description = "规格属性值元组")
31   - public static class Tuple2 {
32   - private final long id;
33   - private final String name;
34   -
35   - public Tuple2(Long id, String name) {
36   - this.id = id;
37   - this.name = name;
38   - }
39   -
40   - }
41   -
42   -
43   -}
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java
1 1 package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
2 2  
3   -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
4 3 import io.swagger.v3.oas.annotations.media.Schema;
5 4 import lombok.Data;
6   -import lombok.EqualsAndHashCode;
7   -import lombok.ToString;
8 5  
9   -import java.time.LocalDateTime;
10 6 import java.util.List;
11 7  
12   -@Schema(description = "管理后台 - 规格 + 规格值 Response VO")
  8 +@Schema(description = "管理后台 - 商品属性项 + 属性值 Response VO")
13 9 @Data
14   -@EqualsAndHashCode(callSuper = true)
15   -@ToString(callSuper = true)
16   -public class ProductPropertyAndValueRespVO extends ProductPropertyBaseVO {
  10 +public class ProductPropertyAndValueRespVO {
17 11  
18   - @Schema(description = "规格的编号", required = true, example = "1024")
  12 + @ApiModelProperty(value = "属性项的编号", required = true, example = "1024")
19 13 private Long id;
20 14  
21   - @Schema(description = "创建时间", required = true)
22   - private LocalDateTime createTime;
  15 + @ApiModelProperty(value = "属性项的名称", required = true, example = "颜色")
  16 + private String name;
23 17  
24 18 /**
25   - * 规格值的集合
  19 + * 属性值的集合
26 20 */
27   - private List<ProductPropertyValueRespVO> values;
  21 + private List<Value> values;
  22 +
  23 + @ApiModel("管理后台 - 属性值的简单 Response VO")
  24 + @Data
  25 + public static class Value {
  26 +
  27 + @Schema(description = "属性值的编号", required = true, example = "2048")
  28 + private Long id;
  29 +
  30 + @Schema(description = "属性值的名称", required = true, example = "红色")
  31 + private String name;
  32 +
  33 + }
28 34  
29 35 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java
1 1 package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
  2 +
2 3 import io.swagger.v3.oas.annotations.media.Schema;
3 4 import lombok.Data;
4 5  
5 6 import javax.validation.constraints.NotBlank;
6   -import javax.validation.constraints.NotNull;
7 7  
8 8 /**
9   - * 规格名称 Base VO,提供给添加、修改、详细的子 VO 使用
  9 + * 商品属性项 Base VO,提供给添加、修改、详细的子 VO 使用
10 10 * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
11 11 */
12 12 @Data
13 13 public class ProductPropertyBaseVO {
14 14  
15   - @Schema(description = "规格名称", required = true, example = "颜色")
16   - @NotBlank(message = "规格名称不能为空")
  15 + @Schema(description = "名称", required = true, example = "颜色")
  16 + @NotBlank(message = "名称不能为空")
17 17 private String name;
18 18  
19 19 @Schema(description = "备注", example = "颜色")
20 20 private String remark;
21 21  
22   - @Schema(description = "状态-参见 CommonStatusEnum 枚举", required = true, example = "1")
23   - @NotNull(message = "状态不能为空")
24   - private Integer status;
25   -
26 22 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java
1 1 package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
  2 +
2 3 import io.swagger.v3.oas.annotations.media.Schema;
3 4 import lombok.Data;
4 5 import lombok.EqualsAndHashCode;
5 6 import lombok.ToString;
6 7  
7   -@Schema(description = "管理后台 - 规格名称创建 Request VO")
  8 +@Schema(description = "管理后台 - 属性项创建 Request VO")
8 9 @Data
9 10 @EqualsAndHashCode(callSuper = true)
10 11 @ToString(callSuper = true)
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java
... ... @@ -4,15 +4,12 @@ import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
5 5 import lombok.ToString;
6 6  
7   -@Schema(description = "管理后台 - 规格名称 List Request VO")
  7 +@Schema(description = "管理后台 - 属性项 List Request VO")
8 8 @Data
9 9 @ToString(callSuper = true)
10 10 public class ProductPropertyListReqVO {
11 11  
12   - @Schema(description = "规格名称", example = "颜色")
  12 + @Schema(description = "名称", example = "颜色")
13 13 private String name;
14 14  
15   - @Schema(description = "状态,参见 CommonStatusEnum 枚举", required = true, example = "1")
16   - private Integer status;
17   -
18 15 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java
... ... @@ -11,16 +11,16 @@ import java.time.LocalDateTime;
11 11  
12 12 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
13 13  
14   -@Schema(description = "管理后台 - 规格名称分页 Request VO")
  14 +@Schema(description = "管理后台 - 属性项 Request VO")
15 15 @Data
16 16 @EqualsAndHashCode(callSuper = true)
17 17 @ToString(callSuper = true)
18 18 public class ProductPropertyPageReqVO extends PageParam {
19 19  
20   - @Schema(description = "规格名称", example = "颜色")
  20 + @Schema(description = "名称", example = "颜色")
21 21 private String name;
22 22  
23   - @Schema(description = "状态,参见 CommonStatusEnum 枚举", required = true, example = "1")
  23 + @Schema(description = "状态-参见 CommonStatusEnum 枚举", required = true, example = "1")
24 24 private Integer status;
25 25  
26 26 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java
... ... @@ -7,13 +7,13 @@ import lombok.ToString;
7 7  
8 8 import java.time.LocalDateTime;
9 9  
10   -@Schema(description = "管理后台 - 规格 + 规格值 Response VO")
  10 +@Schema(description = "管理后台 - 属性项 Response VO")
11 11 @Data
12 12 @EqualsAndHashCode(callSuper = true)
13 13 @ToString(callSuper = true)
14 14 public class ProductPropertyRespVO extends ProductPropertyBaseVO {
15 15  
16   - @Schema(description = "规格的编号", required = true, example = "1024")
  16 + @Schema(description = "编号", required = true, example = "1024")
17 17 private Long id;
18 18  
19 19 @Schema(description = "创建时间", required = true)
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java
1 1 package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
  2 +
2 3 import io.swagger.v3.oas.annotations.media.Schema;
3   -import lombok.*;
4   -import javax.validation.constraints.*;
  4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
  7 +
  8 +import javax.validation.constraints.NotNull;
5 9  
6   -@Schema(description = "管理后台 - 规格名称更新 Request VO")
  10 +@Schema(description = "管理后台 - 属性项更新 Request VO")
7 11 @Data
8 12 @EqualsAndHashCode(callSuper = true)
9 13 @ToString(callSuper = true)
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java
1 1 package cn.iocoder.yudao.module.product.controller.admin.property.vo.value;
  2 +
2 3 import io.swagger.v3.oas.annotations.media.Schema;
3 4 import lombok.Data;
4 5  
... ... @@ -6,24 +7,20 @@ import javax.validation.constraints.NotEmpty;
6 7 import javax.validation.constraints.NotNull;
7 8  
8 9 /**
9   -* 规格值 Base VO,提供给添加、修改、详细的子 VO 使用
  10 +* 属性值 Base VO,提供给添加、修改、详细的子 VO 使用
10 11 * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
11 12 */
12 13 @Data
13 14 public class ProductPropertyValueBaseVO {
14 15  
15   - @Schema(description = "规格编号", required = true, example = "1024")
16   - @NotNull(message = "规格编号不能为空")
  16 + @Schema(description = "属性项的编号", required = true, example = "1024")
  17 + @NotNull(message = "属性项的编号不能为空")
17 18 private Long propertyId;
18 19  
19   - @Schema(description = "规格值名字", required = true, example = "红色")
20   - @NotEmpty(message = "规格值名字不能为空")
  20 + @Schema(description = "名称", required = true, example = "红色")
  21 + @NotEmpty(message = "名称名字不能为空")
21 22 private String name;
22 23  
23   - @Schema(description = "状态,参见 CommonStatusEnum 枚举", required = true, example = "1")
24   - @NotNull(message = "状态不能为空")
25   - private Integer status;
26   -
27 24 @Schema(description = "备注", example = "颜色")
28 25 private String remark;
29 26  
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java
1 1 package cn.iocoder.yudao.module.product.controller.admin.property.vo.value;
  2 +
2 3 import io.swagger.v3.oas.annotations.media.Schema;
3 4 import lombok.*;
4 5  
5   -@Schema(description = "管理后台 - 规格值创建 Request VO")
  6 +@Schema(description = "管理后台 - 商品属性值创建 Request VO")
6 7 @Data
7 8 @EqualsAndHashCode(callSuper = true)
8 9 @ToString(callSuper = true)
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueDetailRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.product.controller.admin.property.vo.value;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +@ApiModel("管理后台 - 商品属性值的明细 Response VO")
  8 +@Data
  9 +public class ProductPropertyValueDetailRespVO {
  10 +
  11 + @ApiModelProperty(value = "属性的编号", required = true, example = "1")
  12 + private Long propertyId;
  13 +
  14 + @ApiModelProperty(value = "属性的名称", required = true, example = "颜色")
  15 + private String propertyName;
  16 +
  17 + @ApiModelProperty(value = "属性值的编号", required = true, example = "1024")
  18 + private Long valueId;
  19 +
  20 + @ApiModelProperty(value = "属性值的名称", required = true, example = "红色")
  21 + private String valueName;
  22 +
  23 +}
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java
... ... @@ -5,26 +5,20 @@ import io.swagger.v3.oas.annotations.media.Schema;
5 5 import lombok.Data;
6 6 import lombok.EqualsAndHashCode;
7 7 import lombok.ToString;
8   -import org.springframework.format.annotation.DateTimeFormat;
9 8  
10   -import javax.validation.constraints.NotEmpty;
11   -import java.util.Date;
12   -
13   -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
14   -
15   -@Schema(description = "管理后台 - 规格名称值分页 Request VO")
  9 +@Schema(description = "管理后台 - 商品属性值分页 Request VO")
16 10 @Data
17 11 @EqualsAndHashCode(callSuper = true)
18 12 @ToString(callSuper = true)
19 13 public class ProductPropertyValuePageReqVO extends PageParam {
20 14  
21   - @Schema(description = "规格id", example = "1024")
  15 + @Schema(description = "属性项的编号", example = "1024")
22 16 private String propertyId;
23 17  
24   - @Schema(description = "规格值", example = "红色")
  18 + @Schema(description = "名称", example = "红色")
25 19 private String name;
26 20  
27   - @Schema(description = "状态,参见 CommonStatusEnum 枚举", required = true, example = "1")
  21 + @Schema(description = "状态 - 参见 CommonStatusEnum 枚举", required = true, example = "1")
28 22 private Integer status;
29 23  
30 24 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java
... ... @@ -7,13 +7,13 @@ import lombok.ToString;
7 7  
8 8 import java.time.LocalDateTime;
9 9  
10   -@Schema(description = "管理后台 - 规格值 Response VO")
  10 +@Schema(description = "管理后台 - 商品属性值 Response VO")
11 11 @Data
12 12 @EqualsAndHashCode(callSuper = true)
13 13 @ToString(callSuper = true)
14 14 public class ProductPropertyValueRespVO extends ProductPropertyValueBaseVO {
15 15  
16   - @Schema(description = "主键", required = true, example = "10")
  16 + @Schema(description = "编号", required = true, example = "10")
17 17 private Long id;
18 18  
19 19 @Schema(description = "创建时间")
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java
1 1 package cn.iocoder.yudao.module.product.controller.admin.property.vo.value;
  2 +
2 3 import io.swagger.v3.oas.annotations.media.Schema;
3 4 import lombok.*;
4 5 import javax.validation.constraints.*;
5 6  
6   -@Schema(description = "管理后台 - 规格值更新 Request VO")
  7 +@Schema(description = "管理后台 - 商品属性值更新 Request VO")
7 8 @Data
8 9 @EqualsAndHashCode(callSuper = true)
9 10 @ToString(callSuper = true)
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
... ... @@ -3,7 +3,9 @@ package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
3 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
5 5 import io.swagger.v3.oas.annotations.media.Schema;
  6 +import lombok.AllArgsConstructor;
6 7 import lombok.Data;
  8 +import lombok.NoArgsConstructor;
7 9  
8 10 import javax.validation.constraints.NotEmpty;
9 11 import javax.validation.constraints.NotNull;
... ... @@ -15,54 +17,56 @@ import javax.validation.constraints.NotNull;
15 17 @Data
16 18 public class ProductSkuBaseVO {
17 19  
18   - @Schema(description = "商品 SKU 名字", required = true, example = "芋道")
  20 + @Schema(description = "商品 SKU 名字", required = true, example = "芋道")
19 21 @NotEmpty(message = "商品 SKU 名字不能为空")
20 22 private String name;
21 23  
22   - @Schema(description = "销售价格,单位:分", required = true, example = "1024")
  24 + @Schema(description = "销售价格,单位:分", required = true, example = "1024", notes = "单位:分")
23 25 @NotNull(message = "销售价格,单位:分不能为空")
24 26 private Integer price;
25 27  
26   - @Schema(description = "市场价,单位:分", example = "1024")
  28 + @Schema(description = "市场价", example = "1024", notes = "单位:分")
27 29 private Integer marketPrice;
28 30  
29   - @Schema(description = "成本价,单位:分", example = "1024")
  31 + @Schema(description = "成本价", example = "1024", notes = "单位:分")
30 32 private Integer costPrice;
31 33  
32   - @Schema(description = "条形码", example = "haha")
  34 + @Schema(description = "条形码", example = "haha")
33 35 private String barCode;
34 36  
35   - @Schema(description = "图片地址", required = true, example = "https://www.iocoder.cn/xx.png")
  37 + @Schema(description = "图片地址", required = true, example = "https://www.iocoder.cn/xx.png")
36 38 @NotNull(message = "图片地址不能为空")
37 39 private String picUrl;
38 40  
39   - @Schema(description = "SKU 状态,参见 CommonStatusEnum 枚举", required = true, example = "1")
  41 + @Schema(description = "SKU 状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
40 42 @NotNull(message = "SKU 状态不能为空")
41 43 @InEnum(CommonStatusEnum.class)
42 44 private Integer status;
43 45  
44   - @Schema(description = "库存", required = true, example = "1")
  46 + @Schema(description = "库存", required = true, example = "1")
45 47 @NotNull(message = "库存不能为空")
46 48 private Integer stock;
47 49  
48   - @Schema(description = "预警预存", example = "1")
  50 + @Schema(description = "预警预存", example = "1")
49 51 private Integer warnStock;
50 52  
51   - @Schema(description = "商品重量,单位:kg 千克", example = "1")
  53 + @Schema(description = "商品重量 - 单位:kg 千克", example = "1")
52 54 private Double weight;
53 55  
54   - @Schema(description = "商品体积,单位:m^3 平米", example = "1024")
  56 + @Schema(description = "商品体积 - 单位:m^3 平米", example = "1024")
55 57 private Double volume;
56 58  
57   - @Schema(description = "规格值")
  59 + @ApiModel("商品属性")
58 60 @Data
  61 + @AllArgsConstructor
  62 + @NoArgsConstructor
59 63 public static class Property {
60 64  
61   - @Schema(description = "属性编号", required = true, example = "1")
  65 + @Schema(description = "属性编号", required = true, example = "1")
62 66 @NotNull(message = "属性编号不能为空")
63 67 private Long propertyId;
64 68  
65   - @Schema(description = "属性值编号", required = true, example = "1024")
  69 + @Schema(description = "属性值编号", required = true, example = "1024")
66 70 @NotNull(message = "属性值编号不能为空")
67 71 private Long valueId;
68 72  
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java
... ... @@ -13,11 +13,8 @@ import java.util.List;
13 13 @ToString(callSuper = true)
14 14 public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO {
15 15  
16   - @Schema(description = "商品 SKU 编号", example = "1")
17   - private Long id;
18   -
19 16 /**
20   - * 规格值数组
  17 + * 属性数组
21 18 */
22 19 private List<Property> properties;
23 20  
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java
... ... @@ -21,7 +21,7 @@ public class ProductSkuRespVO extends ProductSkuBaseVO {
21 21 private LocalDateTime createTime;
22 22  
23 23 /**
24   - * 规格值数组
  24 + * 属性数组
25 25 */
26 26 private List<Property> properties;
27 27  
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http 0 → 100644
  1 +### 获得商品 SPU 明细
  2 +GET {{baseUrl}}/product/spu/get-detail?id=4
  3 +Authorization: Bearer {{token}}
  4 +tenant-id: {{adminTenentId}}
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
... ... @@ -3,8 +3,13 @@ package cn.iocoder.yudao.module.product.controller.admin.spu;
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
  6 +import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
6 7 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
  8 +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
7 9 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
  10 +import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
  11 +import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
  12 +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
8 13 import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
9 14 import io.swagger.v3.oas.annotations.tags.Tag;
10 15 import io.swagger.v3.oas.annotations.Parameter;
... ... @@ -15,10 +20,11 @@ import org.springframework.web.bind.annotation.*;
15 20  
16 21 import javax.annotation.Resource;
17 22 import javax.validation.Valid;
18   -import java.util.Collection;
19 23 import java.util.List;
20 24  
  25 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
21 26 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  27 +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
22 28  
23 29 @Tag(name = "管理后台 - 商品 SPU")
24 30 @RestController
... ... @@ -27,64 +33,61 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
27 33 public class ProductSpuController {
28 34  
29 35 @Resource
30   - private ProductSpuService spuService;
  36 + private ProductSpuService productSpuService;
  37 + @Resource
  38 + private ProductSkuService productSkuService;
  39 + @Resource
  40 + private ProductPropertyValueService productPropertyValueService;
31 41  
32 42 @PostMapping("/create")
33 43 @Operation(summary = "创建商品 SPU")
34 44 @PreAuthorize("@ss.hasPermission('product:spu:create')")
35 45 public CommonResult<Long> createProductSpu(@Valid @RequestBody ProductSpuCreateReqVO createReqVO) {
36   - return success(spuService.createSpu(createReqVO));
  46 + return success(productSpuService.createSpu(createReqVO));
37 47 }
38 48  
39 49 @PutMapping("/update")
40 50 @Operation(summary = "更新商品 SPU")
41 51 @PreAuthorize("@ss.hasPermission('product:spu:update')")
42 52 public CommonResult<Boolean> updateSpu(@Valid @RequestBody ProductSpuUpdateReqVO updateReqVO) {
43   - spuService.updateSpu(updateReqVO);
  53 + productSpuService.updateSpu(updateReqVO);
44 54 return success(true);
45 55 }
46 56  
47 57 @DeleteMapping("/delete")
48 58 @Operation(summary = "删除商品 SPU")
49   - @Parameter(name = "id", description = "编号", required = true)
  59 + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
50 60 @PreAuthorize("@ss.hasPermission('product:spu:delete')")
51 61 public CommonResult<Boolean> deleteSpu(@RequestParam("id") Long id) {
52   - spuService.deleteSpu(id);
  62 + productSpuService.deleteSpu(id);
53 63 return success(true);
54 64 }
55 65  
56   - // TODO 芋艿:修改接口
57   - @GetMapping("/get/detail")
58   - @Operation(summary = "获得商品 SPU")
59   - @Parameter(name = "id", description = "编号", required = true, example = "1024")
  66 + @GetMapping("/get-detail")
  67 + @Operation(summary = "获得商品 SPU 明细")
  68 + @Parameter(name = "id", value = "编号", required = true, example = "1024")
60 69 @PreAuthorize("@ss.hasPermission('product:spu:query')")
61 70 public CommonResult<ProductSpuDetailRespVO> getSpuDetail(@RequestParam("id") Long id) {
62   - return success(spuService.getSpuDetail(id));
63   - }
64   -
65   - @GetMapping("/get")
66   - @Operation(summary = "获得商品 SPU")
67   - @Parameter(name = "id", description = "编号", required = true, example = "1024")
68   - @PreAuthorize("@ss.hasPermission('product:spu:query')")
69   - public CommonResult<ProductSpuRespVO> getSpu(@RequestParam("id") Long id) {
70   - return success(spuService.getSpu(id));
71   - }
  71 + // 获得商品 SPU
  72 + ProductSpuDO spu = productSpuService.getSpu(id);
  73 + if (spu == null) {
  74 + throw exception(SPU_NOT_EXISTS);
  75 + }
72 76  
73   -
74   - @GetMapping("/list")
75   - @Operation(summary = "获得商品 SPU 列表")
76   - @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
77   - @PreAuthorize("@ss.hasPermission('product:spu:query')")
78   - public CommonResult<List<ProductSpuRespVO>> getSpuList(@RequestParam("ids") Collection<Long> ids) {
79   - List<ProductSpuDO> list = spuService.getSpuList(ids);
80   - return success(ProductSpuConvert.INSTANCE.convertList(list));
  77 + // 查询商品 SKU
  78 + List<ProductSkuDO> skus = productSkuService.getSkuListBySpuIdAndStatus(spu.getId(), null);
  79 + // 查询商品属性
  80 + List<ProductPropertyValueDetailRespBO> propertyValues = productPropertyValueService
  81 + .getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus));
  82 + // 拼接
  83 + return success(ProductSpuConvert.INSTANCE.convert03(spu, skus, propertyValues));
81 84 }
82 85  
83 86 @GetMapping("/get-simple-list")
84 87 @Operation(summary = "获得商品 SPU 精简列表")
85 88 @PreAuthorize("@ss.hasPermission('product:spu:query')")
86 89 public CommonResult<List<ProductSpuSimpleRespVO>> getSpuSimpleList() {
87   - List<ProductSpuDO> list = spuService.getSpuList();
  90 + List<ProductSpuDO> list = productSpuService.getSpuList();
88 91 return success(ProductSpuConvert.INSTANCE.convertList02(list));
89 92 }
90 93  
... ... @@ -92,7 +95,7 @@ public class ProductSpuController {
92 95 @Operation(summary = "获得商品 SPU 分页")
93 96 @PreAuthorize("@ss.hasPermission('product:spu:query')")
94 97 public CommonResult<PageResult<ProductSpuRespVO>> getSpuPage(@Valid ProductSpuPageReqVO pageVO) {
95   - return success(spuService.getSpuPage(pageVO));
  98 + return success(ProductSpuConvert.INSTANCE.convertPage(productSpuService.getSpuPage(pageVO)));
96 99 }
97 100  
98 101 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java
... ... @@ -11,81 +11,66 @@ import javax.validation.constraints.NotNull;
11 11 import java.util.List;
12 12  
13 13 /**
14   -* 商品 SPU Base VO,提供给添加、修改、详细的子 VO 使用
15   -* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
16   -*/
  14 + * 商品 SPU Base VO,提供给添加、修改、详细的子 VO 使用
  15 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  16 + */
17 17 @Data
18 18 public class ProductSpuBaseVO {
19 19  
20   - @Schema(description = "商品名称", required = true, example = "芋道")
  20 + @Schema(description = = "商品名称", required = true, example = "芋道")
21 21 @NotEmpty(message = "商品名称不能为空")
22 22 private String name;
23 23  
24   - @Schema(description = "商品编码", example = "yudaoyuanma")
  24 + @Schema(description = = "商品编码", example = "yudaoyuanma")
25 25 private String code;
26 26  
27   - @Schema(description = "促销语", example = "好吃!")
  27 + @Schema(description = = "促销语", example = "好吃!")
28 28 private String sellPoint;
29 29  
30   - @Schema(description = "商品详情", required = true, example = "我是商品描述")
  30 + @Schema(description = = "商品详情", required = true, example = "我是商品描述")
31 31 @NotNull(message = "商品详情不能为空")
32 32 private String description;
33 33  
34   - @Schema(description = "商品分类编号", required = true, example = "1")
  34 + @Schema(description = = "商品分类编号", required = true, example = "1")
35 35 @NotNull(message = "商品分类编号不能为空")
36 36 private Long categoryId;
37 37  
38   - @Schema(description = "商品品牌编号", example = "1")
  38 + @Schema(description = = "商品品牌编号", example = "1")
39 39 private Long brandId;
40 40  
41   - @Schema(description = "商品图片的数组", required = true)
  41 + @Schema(description = = "商品图片的数组", required = true)
42 42 @NotNull(message = "商品图片的数组不能为空")
43 43 private List<String> picUrls;
44 44  
45   - @Schema(description = "商品视频", required = true)
  45 + @Schema(description = = "商品视频", required = true)
46 46 private String videoUrl;
47 47  
48   - @Schema(description = "排序字段", required = true, example = "1")
  48 + @Schema(description = = "排序字段", required = true, example = "1")
49 49 private Integer sort;
50 50  
51   - @Schema(description = "商品状态,参见 ProductSpuStatusEnum 枚举类", required = true, example = "1")
  51 + @Schema(description = = "商品状态 参见 ProductSpuStatusEnum 枚举类", required = true, example = "1")
52 52 @NotNull(message = "商品状态不能为空")
53 53 @InEnum(ProductSpuStatusEnum.class)
54 54 private Integer status;
55 55  
56 56 // ========== SKU 相关字段 =========
57 57  
58   - @Schema(description = "规格类型,参见 ProductSpuSpecTypeEnum 枚举类", required = true, example = "1")
  58 + @Schema(description = = "规格类型 参见 ProductSpuSpecTypeEnum 枚举类", required = true, example = "1")
59 59 @NotNull(message = "规格类型不能为空")
60 60 @InEnum(ProductSpuSpecTypeEnum.class)
61 61 private Integer specType;
62 62  
63   - @Schema(description = "是否展示库存", required = true, example = "true")
  63 + @Schema(description = = "是否展示库存", required = true, example = "true")
64 64 @NotNull(message = "是否展示库存不能为空")
65 65 private Boolean showStock;
66 66  
67   - @Schema(description = "库存", required = true, example = "true")
68   - private Integer totalStock;
69   -
70   - @Schema(description = "市场价", example = "1024")
  67 + @Schema(description = = "市场价", example = "1024")
71 68 private Integer marketPrice;
72 69  
73   - @Schema(description = " 最小价格,单位使用:分", required = true, example = "1024")
74   - private Integer minPrice;
75   -
76   - @Schema(description = "最大价格,单位使用:分", required = true, example = "1024")
77   - private Integer maxPrice;
78   -
79 70 // ========== 统计相关字段 =========
80 71  
81   - @Schema(description = "商品销量", example = "1024")
82   - private Integer salesCount;
83   -
84   - @Schema(description = "虚拟销量", required = true, example = "1024")
  72 + @Schema(description = = "虚拟销量", required = true, example = "1024")
85 73 @NotNull(message = "虚拟销量不能为空")
86 74 private Integer virtualSalesCount;
87 75  
88   - @Schema(description = "点击量", example = "1024")
89   - private Integer clickCount;
90   -
91 76 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
1 1 package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
2 2  
3   -import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO;
  3 +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueDetailRespVO;
4 4 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
5 5 import io.swagger.v3.oas.annotations.media.Schema;
6 6 import lombok.Data;
7 7 import lombok.EqualsAndHashCode;
8 8 import lombok.ToString;
9 9  
10   -import java.time.LocalDateTime;
11 10 import java.util.List;
12 11  
13   -@Schema(description = "管理后台 - 商品 SPU 详细 Response VO,包括关联的 SKU 等信息")
  12 +@Schema(description = "管理后台 - 商品 SPU 详细 Response VO 包括关联的 SKU 等信息")
14 13 @Data
15 14 @EqualsAndHashCode(callSuper = true)
16 15 @ToString(callSuper = true)
17   -public class ProductSpuDetailRespVO extends ProductSpuBaseVO {
  16 +public class ProductSpuDetailRespVO extends ProductSpuRespVO {
18 17  
19   - @Schema(description = "主键", required = true, example = "1")
20   - private Long id;
21   -
22   - @Schema(description = "创建时间")
23   - private LocalDateTime createTime;
  18 + // ========== SKU 相关字段 =========
24 19  
25 20 /**
26 21 * SKU 数组
... ... @@ -34,31 +29,10 @@ public class ProductSpuDetailRespVO extends ProductSpuBaseVO {
34 29 public static class Sku extends ProductSkuBaseVO {
35 30  
36 31 /**
37   - * 规格的数组
  32 + * 属性数组
38 33 */
39   - private List<ProductSpuDetailRespVO.Property> properties;
  34 + private List<ProductPropertyValueDetailRespVO> properties;
40 35  
41 36 }
42 37  
43   - @Schema(description = "管理后台 - 商品规格的详细 Response VO")
44   - @Data
45   - @EqualsAndHashCode(callSuper = true)
46   - @ToString(callSuper = true)
47   - public static class Property extends ProductSkuBaseVO.Property {
48   -
49   - @Schema(description = "规格的名字", required = true, example = "颜色")
50   - private String propertyName;
51   -
52   - @Schema(description = "规格值的名字", required = true, example = "蓝色")
53   - private String valueName;
54   -
55   - }
56   -
57   - @Schema(description = "分类 id 数组,一直递归到一级父节点", example = "4")
58   - private Long categoryId;
59   -
60   - // TODO @芋艿:在瞅瞅~
61   - @Schema(description = "规格属性修改和详情展示组合", example = "[{\"propertyId\":2,\"name\":\"内存\",\"propertyValues\":[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]},{\"propertyId\":3,\"name\":\"尺寸\",\"propertyValues\":[{\"v1\":16,\"v2\":\"6.1\"},{\"v1\":15,\"v2\":\"5.7\"}]}]")
62   - private List<ProductPropertyViewRespVO> productPropertyViews;
63   -
64 38 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
... ... @@ -18,13 +18,13 @@ public class ProductSpuPageReqVO extends PageParam {
18 18 @Schema(description = "商品编码", example = "yudaoyuanma")
19 19 private String code;
20 20  
21   - @Schema(description = "分类id", example = "1")
  21 + @Schema(description = "分类编号", example = "1")
22 22 private Long categoryId;
23 23  
24 24 @Schema(description = "商品品牌编号", example = "1")
25 25 private Long brandId;
26 26  
27   - @Schema(description = "上下架状态,参见 ProductSpuStatusEnum 枚举值", example = "1")
  27 + @Schema(description = "上下架状态 参见 ProductSpuStatusEnum 枚举值", example = "1")
28 28 private Integer status;
29 29  
30 30 @Schema(description = "销量最小值", example = "1")
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
... ... @@ -6,7 +6,6 @@ import lombok.EqualsAndHashCode;
6 6 import lombok.ToString;
7 7  
8 8 import java.time.LocalDateTime;
9   -import java.util.List;
10 9  
11 10 @Schema(description = "管理后台 - 商品 SPU Response VO")
12 11 @Data
... ... @@ -20,4 +19,22 @@ public class ProductSpuRespVO extends ProductSpuBaseVO {
20 19 @Schema(description = "创建时间")
21 20 private LocalDateTime createTime;
22 21  
  22 + // ========== SKU 相关字段 =========
  23 +
  24 + @ApiModelProperty(value = "库存", required = true, example = "true")
  25 + private Integer totalStock;
  26 +
  27 + @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
  28 + private Integer minPrice;
  29 +
  30 + @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
  31 + private Integer maxPrice;
  32 +
  33 + @ApiModelProperty(value = "商品销量", example = "1024")
  34 + private Integer salesCount;
  35 +
  36 + // ========== 统计相关字段 =========
  37 +
  38 + @ApiModelProperty(value = "点击量", example = "1024")
  39 + private Integer clickCount;
23 40 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java 0 → 100644
  1 +/**
  2 + * 占位符,无时间作用,避免 package 缩进
  3 + */
  4 +package cn.iocoder.yudao.module.product.controller.app.property;
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java 0 → 100644
  1 +/**
  2 + * 占位符,无时间作用,避免 package 缩进
  3 + */
  4 +package cn.iocoder.yudao.module.product.controller.app.property.vo.property;
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.product.controller.app.property.vo.value;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +@ApiModel("用户 App - 商品属性值的明细 Response VO")
  8 +@Data
  9 +public class AppProductPropertyValueDetailRespVO {
  10 +
  11 + @ApiModelProperty(value = "属性的编号", required = true, example = "1")
  12 + private Long propertyId;
  13 +
  14 + @ApiModelProperty(value = "属性的名称", required = true, example = "颜色")
  15 + private String propertyName;
  16 +
  17 + @ApiModelProperty(value = "属性值的编号", required = true, example = "1024")
  18 + private Long valueId;
  19 +
  20 + @ApiModelProperty(value = "属性值的名称", required = true, example = "红色")
  21 + private String valueName;
  22 +
  23 +}
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http 0 → 100644
  1 +### 获得订单交易的分页 TODO
  2 +GET {{appApi}}/product/spu/page?pageNo=1&pageSize=10
  3 +Authorization: Bearer {{appToken}}
  4 +tenant-id: {{appTenentId}}
  5 +
  6 +### 获得商品 SPU 明细
  7 +GET {{appApi}}/product/spu/get-detail?id=4
  8 +tenant-id: {{appTenentId}}
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
1 1 package cn.iocoder.yudao.module.product.controller.app.spu;
2 2  
3   -import cn.hutool.core.bean.BeanUtil;
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6   -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO;
7   -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO;
8   -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuRespVO;
  6 +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
  7 +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
  8 +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
  9 +import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
  10 +import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
  11 +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
  12 +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
  13 +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
  14 +import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
  15 +import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
  16 +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
9 17 import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
10 18 import io.swagger.v3.oas.annotations.tags.Tag;
11 19 import io.swagger.v3.oas.annotations.Operation;
... ... @@ -17,28 +25,54 @@ import org.springframework.web.bind.annotation.RestController;
17 25  
18 26 import javax.annotation.Resource;
19 27 import javax.validation.Valid;
  28 +import java.util.List;
20 29  
  30 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
21 31 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  32 +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_ENABLE;
  33 +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
22 34  
23   -@Tag(name = "用户 APP - 商品spu")
  35 +@Tag(name = "用户 APP - 商品spu")
24 36 @RestController
25 37 @RequestMapping("/product/spu")
26 38 @Validated
27 39 public class AppProductSpuController {
28 40  
29 41 @Resource
30   - private ProductSpuService spuService;
  42 + private ProductSpuService productSpuService;
  43 + @Resource
  44 + private ProductSkuService productSkuService;
  45 + @Resource
  46 + private ProductPropertyValueService productPropertyValueService;
31 47  
32 48 @GetMapping("/page")
33   - @Operation(summary = "获得商品spu分页")
34   - public CommonResult<PageResult<AppSpuPageRespVO>> getSpuPage(@Valid AppSpuPageReqVO pageVO) {
35   - return success(spuService.getSpuPage(pageVO));
  49 + @Operation(summary = "获得商品 SPU 分页")
  50 + public CommonResult<PageResult<AppProductSpuPageItemRespVO>> getSpuPage(@Valid AppProductSpuPageReqVO pageVO) {
  51 + PageResult<ProductSpuDO> pageResult = productSpuService.getSpuPage(pageVO, ProductSpuStatusEnum.ENABLE.getStatus());
  52 + return success(ProductSpuConvert.INSTANCE.convertPage02(pageResult));
36 53 }
37 54  
38   - @GetMapping("/")
39   - @Operation(summary = "获取商品 - 通过商品id")
40   - public CommonResult<AppSpuRespVO> getSpu(@RequestParam("spuId") Long spuId) {
41   - AppSpuRespVO appSpuRespVO = BeanUtil.toBean(spuService.getSpu(spuId), AppSpuRespVO.class);
42   - return success(appSpuRespVO);
  55 + @GetMapping("/get-detail")
  56 + @Operation(summary = "获得商品 SPU 明细")
  57 + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
  58 + public CommonResult<AppProductSpuDetailRespVO> getSpuDetail(@RequestParam("id") Long id) {
  59 + // 获得商品 SPU
  60 + ProductSpuDO spu = productSpuService.getSpu(id);
  61 + if (spu == null) {
  62 + throw exception(SPU_NOT_EXISTS);
  63 + }
  64 + if (!ProductSpuStatusEnum.isEnable(spu.getStatus())) {
  65 + throw exception(SPU_NOT_ENABLE);
  66 + }
  67 +
  68 + // 查询商品 SKU
  69 + List<ProductSkuDO> skus = productSkuService.getSkuListBySpuIdAndStatus(spu.getId(),
  70 + CommonStatusEnum.ENABLE.getStatus());
  71 + // 查询商品属性
  72 + List<ProductPropertyValueDetailRespBO> propertyValues = productPropertyValueService
  73 + .getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus));
  74 + // 拼接
  75 + return success(ProductSpuConvert.INSTANCE.convert(spu, skus, propertyValues));
43 76 }
  77 +
44 78 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.product.controller.app.spu.vo;
  2 +
  3 +import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.Data;
  7 +
  8 +import java.util.List;
  9 +
  10 +@ApiModel("用户 App - 商品 SPU 明细 Response VO")
  11 +@Data
  12 +public class AppProductSpuDetailRespVO {
  13 +
  14 + @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1")
  15 + private Long id;
  16 +
  17 + // ========== 基本信息 =========
  18 +
  19 + @ApiModelProperty(value = "商品名称", required = true, example = "芋道")
  20 + private String name;
  21 +
  22 + @ApiModelProperty(value = "促销语", example = "好吃!")
  23 + private String sellPoint;
  24 +
  25 + @ApiModelProperty(value = "商品详情", required = true, example = "我是商品描述")
  26 + private String description;
  27 +
  28 + @ApiModelProperty(value = "商品分类编号", required = true, example = "1")
  29 + private Long categoryId;
  30 +
  31 + @ApiModelProperty(value = "商品图片的数组", required = true)
  32 + private List<String> picUrls;
  33 +
  34 + @ApiModelProperty(value = "商品视频", required = true)
  35 + private String videoUrl;
  36 +
  37 + // ========== SKU 相关字段 =========
  38 +
  39 + @ApiModelProperty(value = "规格类型", required = true, example = "1", notes = "参见 ProductSpuSpecTypeEnum 枚举类")
  40 + private Integer specType;
  41 +
  42 + @ApiModelProperty(value = "是否展示库存", required = true, example = "true")
  43 + private Boolean showStock;
  44 +
  45 + @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
  46 + private Integer minPrice;
  47 +
  48 + @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
  49 + private Integer maxPrice;
  50 +
  51 + /**
  52 + * SKU 数组
  53 + */
  54 + private List<Sku> skus;
  55 +
  56 + // ========== 统计相关字段 =========
  57 +
  58 + @ApiModelProperty(value = "商品销量", required = true, example = "1024")
  59 + private Integer salesCount;
  60 +
  61 + @ApiModel("用户 App - 商品 SPU 明细的 SKU 信息")
  62 + @Data
  63 + public static class Sku {
  64 +
  65 + @ApiModelProperty(value = "商品 SKU 编号", example = "1")
  66 + private Long id;
  67 +
  68 + /**
  69 + * 商品属性数组
  70 + */
  71 + private List<AppProductPropertyValueDetailRespVO> properties;
  72 +
  73 + @ApiModelProperty(value = "销售价格,单位:分", required = true, example = "1024", notes = "单位:分")
  74 + private Integer price;
  75 +
  76 + @ApiModelProperty(value = "市场价", example = "1024", notes = "单位:分")
  77 + private Integer marketPrice;
  78 +
  79 + @ApiModelProperty(value = "图片地址", required = true, example = "https://www.iocoder.cn/xx.png")
  80 + private String picUrl;
  81 +
  82 + @ApiModelProperty(value = "库存", required = true, example = "1")
  83 + private Integer stock;
  84 +
  85 + @ApiModelProperty(value = "商品重量", example = "1", notes = "单位:kg 千克")
  86 + private Double weight;
  87 +
  88 + @ApiModelProperty(value = "商品体积", example = "1024", notes = "单位:m^3 平米")
  89 + private Double volume;
  90 + }
  91 +
  92 +}
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageItemRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.product.controller.app.spu.vo;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import javax.validation.constraints.NotEmpty;
  8 +import javax.validation.constraints.NotNull;
  9 +import java.util.List;
  10 +
  11 +@ApiModel("用户 App - 商品 SPU 分页项 Response VO")
  12 +@Data
  13 +public class AppProductSpuPageItemRespVO {
  14 +
  15 + @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1")
  16 + private Long id;
  17 +
  18 + @ApiModelProperty(value = "商品名称", required = true, example = "芋道")
  19 + @NotEmpty(message = "商品名称不能为空")
  20 + private String name;
  21 +
  22 + @ApiModelProperty(value = "分类编号", required = true)
  23 + @NotNull(message = "分类编号不能为空")
  24 + private Long categoryId;
  25 +
  26 + @ApiModelProperty(value = "商品图片的数组", required = true)
  27 + private List<String> picUrls;
  28 +
  29 + @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
  30 + private Integer minPrice;
  31 +
  32 + @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
  33 + private Integer maxPrice;
  34 +
  35 + // ========== 统计相关字段 =========
  36 +
  37 + @ApiModelProperty(value = "商品销量", example = "1024")
  38 + private Integer salesCount;
  39 +
  40 +}
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.product.controller.app.spu.vo;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  5 +import com.fasterxml.jackson.annotation.JsonIgnore;
  6 +import io.swagger.annotations.ApiModel;
  7 +import io.swagger.annotations.ApiModelProperty;
  8 +import lombok.Data;
  9 +import lombok.EqualsAndHashCode;
  10 +import lombok.ToString;
  11 +
  12 +import javax.validation.constraints.AssertTrue;
  13 +
  14 +@ApiModel("用户 App - 商品 SPU 分页 Request VO")
  15 +@Data
  16 +@EqualsAndHashCode(callSuper = true)
  17 +@ToString(callSuper = true)
  18 +public class AppProductSpuPageReqVO extends PageParam {
  19 +
  20 + public static final String SORT_FIELD_PRICE = "price";
  21 + public static final String SORT_FIELD_SALES_COUNT = "salesCount";
  22 +
  23 + @ApiModelProperty(value = "分类编号", example = "1")
  24 + private Long categoryId;
  25 +
  26 + @ApiModelProperty(value = "关键字", example = "好看")
  27 + private String keyword;
  28 +
  29 + @ApiModelProperty(value = "排序字段", example = "price", notes = "参见 AppSpuPageReqVO.SORT_FIELD_XXX 常量")
  30 + private String sortField;
  31 +
  32 + @ApiModelProperty(value = "排序方式", example = "true", notes = "true - 升序;false - 降序")
  33 + private Boolean sortAsc;
  34 +
  35 + @AssertTrue(message = "排序字段不合法")
  36 + @JsonIgnore
  37 + public boolean isSortFieldValid() {
  38 + if (StrUtil.isEmpty(sortField)) {
  39 + return true;
  40 + }
  41 + return StrUtil.equalsAny(sortField, SORT_FIELD_PRICE, SORT_FIELD_SALES_COUNT);
  42 + }
  43 +
  44 +}
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageReqVO.java
1   -package cn.iocoder.yudao.module.product.controller.app.spu.vo;
2   -
3   -import cn.iocoder.yudao.framework.common.pojo.PageParam;
4   -import io.swagger.v3.oas.annotations.media.Schema;
5   -import lombok.Data;
6   -import lombok.EqualsAndHashCode;
7   -import lombok.ToString;
8   -
9   -@Schema(description = "App - 商品spu分页 Request VO")
10   -@Data
11   -@EqualsAndHashCode(callSuper = true)
12   -@ToString(callSuper = true)
13   -public class AppSpuPageReqVO extends PageParam {
14   -
15   - @Schema(description = "分类id")
16   - private Long categoryId;
17   -}
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageRespVO.java
1   -package cn.iocoder.yudao.module.product.controller.app.spu.vo;
2   -
3   -import io.swagger.v3.oas.annotations.media.Schema;
4   -import lombok.Data;
5   -
6   -import javax.validation.constraints.NotNull;
7   -import java.util.List;
8   -
9   -@Schema(description = "App - 商品spu分页 Request VO")
10   -@Data
11   -public class AppSpuPageRespVO {
12   -
13   - @Schema(description = "主键", required = true, example = "1")
14   - private Long id;
15   -
16   - @Schema(description = "商品名称")
17   - private String name;
18   -
19   - @Schema(description = "卖点", required = true)
20   - @NotNull(message = "卖点不能为空")
21   - private String sellPoint;
22   -
23   - @Schema(description = "描述", required = true)
24   - @NotNull(message = "描述不能为空")
25   - private String description;
26   -
27   - @Schema(description = "分类id", required = true)
28   - @NotNull(message = "分类id不能为空")
29   - private Long categoryId;
30   -
31   - @Schema(description = "商品主图地址,* 数组,以逗号分隔,最多上传15张", required = true)
32   - @NotNull(message = "商品主图地址,* 数组,以逗号分隔,最多上传15张不能为空")
33   - private List<String> picUrls;
34   -
35   - @Schema(description = "排序字段", required = true)
36   - @NotNull(message = "排序字段不能为空")
37   - private Integer sort;
38   -
39   - @Schema(description = "点赞初始人数")
40   - private Integer likeCount;
41   -
42   - @Schema(description = "价格 单位使用:分")
43   - private Integer price;
44   -
45   - @Schema(description = "库存数量")
46   - private Integer quantity;
47   -
48   - @Schema(description = "上下架状态: 0 上架(开启) 1 下架(禁用)")
49   - private Integer status;
50   -
51   -}
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuRespVO.java
1   -package cn.iocoder.yudao.module.product.controller.app.spu.vo;
2   -
3   -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO;
4   -import io.swagger.v3.oas.annotations.media.Schema;
5   -import lombok.Data;
6   -import lombok.EqualsAndHashCode;
7   -
8   -/**
9   - * <p>
10   - *
11   - * </p>
12   - *
13   - * @author LuoWenFeng
14   - */
15   -@Schema(description = "App - 商品spu Response VO")
16   -@Data
17   -@EqualsAndHashCode(callSuper = true)
18   -public class AppSpuRespVO extends ProductSpuRespVO {
19   -
20   -
21   -}
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java
1 1 package cn.iocoder.yudao.module.product.convert.property;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
4 5 import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO;
5 6 import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyCreateReqVO;
6 7 import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO;
7 8 import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyUpdateReqVO;
8   -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
9 9 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
10 10 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
11 11 import org.mapstruct.Mapper;
12 12 import org.mapstruct.factory.Mappers;
13 13  
14 14 import java.util.List;
  15 +import java.util.Map;
15 16  
16 17 /**
17   - * 规格名称 Convert
  18 + * 属性项 Convert
18 19 *
19 20 * @author 芋道源码
20 21 */
... ... @@ -27,12 +28,21 @@ public interface ProductPropertyConvert {
27 28  
28 29 ProductPropertyDO convert(ProductPropertyUpdateReqVO bean);
29 30  
30   - ProductPropertyAndValueRespVO convert(ProductPropertyRespVO bean);
31   -
32 31 ProductPropertyRespVO convert(ProductPropertyDO bean);
33 32  
34 33 List<ProductPropertyRespVO> convertList(List<ProductPropertyDO> list);
35 34  
36 35 PageResult<ProductPropertyRespVO> convertPage(PageResult<ProductPropertyDO> page);
37 36  
  37 + default List<ProductPropertyAndValueRespVO> convertList(List<ProductPropertyDO> keys, List<ProductPropertyValueDO> values) {
  38 + Map<Long, List<ProductPropertyValueDO>> valueMap = CollectionUtils.convertMultiMap(values, ProductPropertyValueDO::getPropertyId);
  39 + return CollectionUtils.convertList(keys, key -> {
  40 + ProductPropertyAndValueRespVO respVO = convert02(key);
  41 + respVO.setValues(convertList02(valueMap.get(key.getId())));
  42 + return respVO;
  43 + });
  44 + }
  45 + ProductPropertyAndValueRespVO convert02(ProductPropertyDO bean);
  46 + List<ProductPropertyAndValueRespVO.Value> convertList02(List<ProductPropertyValueDO> list);
  47 +
38 48 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java
1 1 package cn.iocoder.yudao.module.product.convert.propertyvalue;
2 2  
3   -import java.util.*;
4   -
5 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6   -
  4 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  5 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
  6 +import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
7 7 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
8 8 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
9 9 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
  10 +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
10 11 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
  12 +import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
11 13 import org.mapstruct.Mapper;
12 14 import org.mapstruct.factory.Mappers;
13 15  
  16 +import java.util.List;
  17 +import java.util.Map;
  18 +
  19 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  20 +
14 21 /**
15   - * 规格值 Convert
  22 + * 属性值 Convert
16 23 *
17 24 * @author 芋道源码
18 25 */
... ... @@ -31,6 +38,18 @@ public interface ProductPropertyValueConvert {
31 38  
32 39 PageResult<ProductPropertyValueRespVO> convertPage(PageResult<ProductPropertyValueDO> page);
33 40  
34   - List<ProductPropertyValueDO> convertList03(List<ProductPropertyValueCreateReqVO> list);
  41 + default List<ProductPropertyValueDetailRespBO> convertList(List<ProductPropertyValueDO> values, List<ProductPropertyDO> keys) {
  42 + Map<Long, ProductPropertyDO> keyMap = convertMap(keys, ProductPropertyDO::getId);
  43 + return CollectionUtils.convertList(values, value -> {
  44 + ProductPropertyValueDetailRespBO valueDetail = new ProductPropertyValueDetailRespBO()
  45 + .setValueId(value.getId()).setValueName(value.getName());
  46 + // 设置属性项
  47 + MapUtils.findAndThen(keyMap, value.getPropertyId(),
  48 + key -> valueDetail.setPropertyId(key.getId()).setPropertyName(key.getName()));
  49 + return valueDetail;
  50 + });
  51 + }
  52 +
  53 + List<ProductPropertyValueDetailRespDTO> convertList02(List<ProductPropertyValueDetailRespBO> list);
35 54  
36 55 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java
1 1 package cn.iocoder.yudao.module.product.convert.sku;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.StrUtil;
3 5 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
4 6 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
5 7 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
... ... @@ -10,9 +12,8 @@ import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
10 12 import org.mapstruct.Mapper;
11 13 import org.mapstruct.factory.Mappers;
12 14  
13   -import java.util.HashMap;
14   -import java.util.List;
15   -import java.util.Map;
  15 +import java.util.*;
  16 +import java.util.stream.Collectors;
16 17  
17 18 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
18 19  
... ... @@ -32,11 +33,15 @@ public interface ProductSkuConvert {
32 33  
33 34 List<ProductSkuRespVO> convertList(List<ProductSkuDO> list);
34 35  
35   - List<ProductSkuDO> convertSkuDOList(List<ProductSkuCreateOrUpdateReqVO> list);
  36 + List<ProductSkuDO> convertList06(List<ProductSkuCreateOrUpdateReqVO> list);
36 37  
37   - ProductSkuRespDTO convert02(ProductSkuDO bean);
  38 + default List<ProductSkuDO> convertList06(List<ProductSkuCreateOrUpdateReqVO> list, Long spuId, String spuName) {
  39 + List<ProductSkuDO> result = convertList06(list);
  40 + result.forEach(item -> item.setSpuId(spuId).setSpuName(spuName));
  41 + return result;
  42 + }
38 43  
39   - List<ProductSkuRespDTO> convertList02(List<ProductSkuDO> list);
  44 + ProductSkuRespDTO convert02(ProductSkuDO bean);
40 45  
41 46 List<ProductSpuDetailRespVO.Sku> convertList03(List<ProductSkuDO> list);
42 47  
... ... @@ -66,4 +71,23 @@ public interface ProductSkuConvert {
66 71 return spuIdAndStockMap;
67 72 }
68 73  
  74 + default Collection<Long> convertPropertyValueIds(List<ProductSkuDO> list) {
  75 + if (CollUtil.isEmpty(list)) {
  76 + return new HashSet<>();
  77 + }
  78 + return list.stream().filter(item -> item.getProperties() != null)
  79 + .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
  80 + .map(ProductSkuDO.Property::getValueId) // 将每个 Property 转换成对应的 propertyId,最后形成集合
  81 + .collect(Collectors.toSet());
  82 + }
  83 +
  84 + default String buildPropertyKey(ProductSkuDO bean) {
  85 + if (CollUtil.isEmpty(bean.getProperties())) {
  86 + return StrUtil.EMPTY;
  87 + }
  88 + List<ProductSkuDO.Property> properties = new ArrayList<>(bean.getProperties());
  89 + properties.sort(Comparator.comparing(ProductSkuDO.Property::getValueId));
  90 + return properties.stream().map(m -> String.valueOf(m.getValueId())).collect(Collectors.joining());
  91 + }
  92 +
69 93 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
1 1 package cn.iocoder.yudao.module.product.convert.spu;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 5 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
  6 +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueDetailRespVO;
5 7 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
6   -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO;
7   -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO;
  8 +import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
  9 +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
  10 +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
  11 +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
  12 +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
8 13 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
  14 +import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
9 15 import org.mapstruct.Mapper;
10 16 import org.mapstruct.factory.Mappers;
11 17  
  18 +import java.util.ArrayList;
12 19 import java.util.List;
  20 +import java.util.Map;
  21 +
  22 +import static cn.hutool.core.util.ObjectUtil.defaultIfNull;
  23 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
13 24  
14 25 /**
15   - * 商品spu Convert
  26 + * 商品 SPU Convert
16 27 *
17 28 * @author 芋道源码
18 29 */
... ... @@ -25,18 +36,73 @@ public interface ProductSpuConvert {
25 36  
26 37 ProductSpuDO convert(ProductSpuUpdateReqVO bean);
27 38  
28   - ProductSpuRespVO convert(ProductSpuDO bean);
29   -
30   - List<ProductSpuRespVO> convertList(List<ProductSpuDO> list);
  39 + List<ProductSpuDO> convertList(List<ProductSpuDO> list);
31 40  
32 41 PageResult<ProductSpuRespVO> convertPage(PageResult<ProductSpuDO> page);
33 42  
34   - ProductSpuPageReqVO convert(AppSpuPageReqVO bean);
35   -
36   - AppSpuPageRespVO convertAppResp(ProductSpuDO list);
  43 + ProductSpuPageReqVO convert(AppProductSpuPageReqVO bean);
37 44  
38 45 List<ProductSpuRespDTO> convertList2(List<ProductSpuDO> list);
39 46  
40 47 List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list);
41 48  
  49 + default AppProductSpuDetailRespVO convert(ProductSpuDO spu, List<ProductSkuDO> skus,
  50 + List<ProductPropertyValueDetailRespBO> propertyValues) {
  51 + AppProductSpuDetailRespVO spuVO = convert02(spu)
  52 + .setSalesCount(spu.getSalesCount() + defaultIfNull(spu.getVirtualSalesCount(), 0));
  53 + spuVO.setSkus(convertList03(skus));
  54 + // 处理商品属性
  55 + Map<Long, ProductPropertyValueDetailRespBO> propertyValueMap = convertMap(propertyValues, ProductPropertyValueDetailRespBO::getValueId);
  56 + for (int i = 0; i < skus.size(); i++) {
  57 + List<ProductSkuDO.Property> properties = skus.get(i).getProperties();
  58 + if (CollUtil.isEmpty(properties)) {
  59 + continue;
  60 + }
  61 + AppProductSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i);
  62 + sku.setProperties(new ArrayList<>(properties.size()));
  63 + // 遍历每个 properties,设置到 AppSpuDetailRespVO.Sku 中
  64 + properties.forEach(property -> {
  65 + ProductPropertyValueDetailRespBO propertyValue = propertyValueMap.get(property.getValueId());
  66 + if (propertyValue == null) {
  67 + return;
  68 + }
  69 + sku.getProperties().add(convert03(propertyValue));
  70 + });
  71 + }
  72 + return spuVO;
  73 + }
  74 + AppProductSpuDetailRespVO convert02(ProductSpuDO spu);
  75 + List<AppProductSpuDetailRespVO.Sku> convertList03(List<ProductSkuDO> skus);
  76 + AppProductPropertyValueDetailRespVO convert03(ProductPropertyValueDetailRespBO propertyValue);
  77 +
  78 + PageResult<AppProductSpuPageItemRespVO> convertPage02(PageResult<ProductSpuDO> page);
  79 +
  80 + default ProductSpuDetailRespVO convert03(ProductSpuDO spu, List<ProductSkuDO> skus,
  81 + List<ProductPropertyValueDetailRespBO> propertyValues) {
  82 + ProductSpuDetailRespVO spuVO = convert03(spu);
  83 + spuVO.setSkus(convertList04(skus));
  84 + // 处理商品属性
  85 + Map<Long, ProductPropertyValueDetailRespBO> propertyValueMap = convertMap(propertyValues, ProductPropertyValueDetailRespBO::getValueId);
  86 + for (int i = 0; i < skus.size(); i++) {
  87 + List<ProductSkuDO.Property> properties = skus.get(i).getProperties();
  88 + if (CollUtil.isEmpty(properties)) {
  89 + continue;
  90 + }
  91 + ProductSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i);
  92 + sku.setProperties(new ArrayList<>(properties.size()));
  93 + // 遍历每个 properties,设置到 AppSpuDetailRespVO.Sku 中
  94 + properties.forEach(property -> {
  95 + ProductPropertyValueDetailRespBO propertyValue = propertyValueMap.get(property.getValueId());
  96 + if (propertyValue == null) {
  97 + return;
  98 + }
  99 + sku.getProperties().add(convert04(propertyValue));
  100 + });
  101 + }
  102 + return spuVO;
  103 + }
  104 + ProductSpuDetailRespVO convert03(ProductSpuDO spu);
  105 + List<ProductSpuDetailRespVO.Sku> convertList04(List<ProductSkuDO> skus);
  106 + ProductPropertyValueDetailRespVO convert04(ProductPropertyValueDetailRespBO propertyValue);
  107 +
42 108 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java
1 1 package cn.iocoder.yudao.module.product.dal.dataobject.property;
2 2  
3   -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
5 4 import com.baomidou.mybatisplus.annotation.KeySequence;
6 5 import com.baomidou.mybatisplus.annotation.TableId;
... ... @@ -8,7 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
8 7 import lombok.*;
9 8  
10 9 /**
11   - * 规格名称 DO
  10 + * 商品属性项 DO
12 11 *
13 12 * @author 芋道源码
14 13 */
... ... @@ -28,20 +27,12 @@ public class ProductPropertyDO extends BaseDO {
28 27 @TableId
29 28 private Long id;
30 29 /**
31   - * 规格名称
  30 + * 名称
32 31 */
33 32 private String name;
34 33 /**
35   - * 状态
36   - *
37   - * 枚举 {@link CommonStatusEnum}
38   - */
39   - private Integer status;
40   - /**
41 34 * 备注
42 35 */
43 36 private String remark;
44 37  
45   - // TODO 芋艿:rule;规格属性 (发布商品时,和 SKU 关联);规格参数(搜索商品时,与 Category 关联搜索)
46   -
47 38 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java
1 1 package cn.iocoder.yudao.module.product.dal.dataobject.property;
2 2  
3   -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
5 4 import com.baomidou.mybatisplus.annotation.KeySequence;
6 5 import com.baomidou.mybatisplus.annotation.TableId;
... ... @@ -9,7 +8,7 @@ import lombok.*;
9 8  
10 9  
11 10 /**
12   - * 规格值 DO
  11 + * 商品属性值 DO
13 12 *
14 13 * @author 芋道源码
15 14 */
... ... @@ -29,22 +28,16 @@ public class ProductPropertyValueDO extends BaseDO {
29 28 @TableId
30 29 private Long id;
31 30 /**
32   - * 规格键编号
  31 + * 属性项的编号
33 32 *
34 33 * 关联 {@link ProductPropertyDO#getId()}
35 34 */
36 35 private Long propertyId;
37 36 /**
38   - * 规格值名字
  37 + * 名称
39 38 */
40 39 private String name;
41 40 /**
42   - * 状态
43   - *
44   - * 枚举 {@link CommonStatusEnum}
45   - */
46   - private Integer status;
47   - /**
48 41 * 备注
49 42 *
50 43 */
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java
... ... @@ -36,17 +36,19 @@ public class ProductSkuDO extends BaseDO {
36 36 @TableId
37 37 private Long id;
38 38 /**
39   - * 商品 SKU 名字
40   - */
41   - private String name;
42   - /**
43 39 * SPU 编号
44 40 * <p>
45 41 * 关联 {@link ProductSpuDO#getId()}
46 42 */
47 43 private Long spuId;
48 44 /**
49   - * 规格值数组,JSON 格式
  45 + * SPU 名字
  46 + *
  47 + * 冗余 {@link ProductSkuDO#getSpuName()}
  48 + */
  49 + private String spuName;
  50 + /**
  51 + * 属性数组,JSON 格式
50 52 */
51 53 @TableField(typeHandler = PropertyTypeHandler.class)
52 54 private List<Property> properties;
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java
... ... @@ -3,31 +3,30 @@ package cn.iocoder.yudao.module.product.dal.mysql.property;
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  6 +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyListReqVO;
6 7 import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO;
7 8 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
8 9 import org.apache.ibatis.annotations.Mapper;
9 10  
10 11 import java.util.List;
11 12  
12   -/**
13   - * 规格名称 Mapper
14   - *
15   - * @author 芋道源码
16   - */
17 13 @Mapper
18 14 public interface ProductPropertyMapper extends BaseMapperX<ProductPropertyDO> {
19 15  
20 16 default PageResult<ProductPropertyDO> selectPage(ProductPropertyPageReqVO reqVO) {
21 17 return selectPage(reqVO, new LambdaQueryWrapperX<ProductPropertyDO>()
22 18 .likeIfPresent(ProductPropertyDO::getName, reqVO.getName())
23   - .eqIfPresent(ProductPropertyDO::getStatus, reqVO.getStatus())
24 19 .betweenIfPresent(ProductPropertyDO::getCreateTime, reqVO.getCreateTime())
25 20 .orderByDesc(ProductPropertyDO::getId));
26 21 }
27 22  
28 23 default ProductPropertyDO selectByName(String name) {
29   - return selectOne(new LambdaQueryWrapperX<ProductPropertyDO>()
30   - .eqIfPresent(ProductPropertyDO::getName, name));
  24 + return selectOne(ProductPropertyDO::getName, name);
  25 + }
  26 +
  27 + default List<ProductPropertyDO> selectList(ProductPropertyListReqVO listReqVO) {
  28 + return selectList(new LambdaQueryWrapperX<ProductPropertyDO>()
  29 + .eqIfPresent(ProductPropertyDO::getName, listReqVO.getName()));
31 30 }
32 31  
33 32 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java
... ... @@ -7,17 +7,13 @@ import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.Produc
7 7 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
8 8 import org.apache.ibatis.annotations.Mapper;
9 9  
  10 +import java.util.Collection;
10 11 import java.util.List;
11 12  
12   -/**
13   - * 规格值 Mapper
14   - *
15   - * @author 芋道源码
16   - */
17 13 @Mapper
18 14 public interface ProductPropertyValueMapper extends BaseMapperX<ProductPropertyValueDO> {
19 15  
20   - default List<ProductPropertyValueDO> selectListByPropertyId(List<Long> propertyIds) {
  16 + default List<ProductPropertyValueDO> selectListByPropertyId(Collection<Long> propertyIds) {
21 17 return selectList(new LambdaQueryWrapperX<ProductPropertyValueDO>()
22 18 .inIfPresent(ProductPropertyValueDO::getPropertyId, propertyIds));
23 19 }
... ... @@ -28,17 +24,20 @@ public interface ProductPropertyValueMapper extends BaseMapperX&lt;ProductPropertyV
28 24 .eq(ProductPropertyValueDO::getName, name));
29 25 }
30 26  
31   - default void deletePropertyValueByPropertyId(Long propertyId) {
32   - delete(new LambdaQueryWrapperX<ProductPropertyValueDO>().eq(ProductPropertyValueDO::getPropertyId, propertyId)
33   - .eq(ProductPropertyValueDO::getDeleted, false));
  27 + default void deleteByPropertyId(Long propertyId) {
  28 + delete(new LambdaQueryWrapperX<ProductPropertyValueDO>()
  29 + .eq(ProductPropertyValueDO::getPropertyId, propertyId));
34 30 }
35 31  
36 32 default PageResult<ProductPropertyValueDO> selectPage(ProductPropertyValuePageReqVO reqVO) {
37 33 return selectPage(reqVO, new LambdaQueryWrapperX<ProductPropertyValueDO>()
38 34 .eqIfPresent(ProductPropertyValueDO::getPropertyId, reqVO.getPropertyId())
39 35 .likeIfPresent(ProductPropertyValueDO::getName, reqVO.getName())
40   - .eqIfPresent(ProductPropertyValueDO::getStatus, reqVO.getStatus())
41 36 .orderByDesc(ProductPropertyValueDO::getId));
42 37 }
43 38  
  39 + default Integer selectCountByPropertyId(Long propertyId) {
  40 + return selectCount(ProductPropertyValueDO::getPropertyId, propertyId).intValue();
  41 + }
  42 +
44 43 }
... ...