# Conflicts:
#	src/components/DiyEditor/components/ComponentContainer.vue
This commit is contained in:
YunaiV committed 2023-11-18 20:39:31 +08:00
commit 7c5ae17d04
59 files changed
+5154 -238

No files matched your search

+3 -2
View File
@@ -21,7 +21,7 @@ module.exports = defineConfig({
'plugin:vue/vue3-recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
'plugin:prettier/recommended',
'plugin:prettier/recommended',
'@unocss'
],
rules: {
@@ -67,6 +67,7 @@ module.exports = defineConfig({
}
],
'vue/multi-word-component-names': 'off',
'vue/no-v-html': 'off'
'vue/no-v-html': 'off',
'prettier/prettier': 'off' // 芋艿:默认关闭 prettier 的 ESLint 校验,因为我们使用的是 IDE 的 Prettier 插件
}
})
+6 -6
View File
@@ -38,15 +38,15 @@
| 框架 | 说明 | 版本 |
|----------------------------------------------------------------------|------------------|--------|
| [Vue](https://staging-cn.vuejs.org/) | Vue 框架 | 3.3.4 |
| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 4.4.11 |
| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.4.0 |
| [Vue](https://staging-cn.vuejs.org/) | Vue 框架 | 3.3.8 |
| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 4.5.0 |
| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.4.2 |
| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 的超集 | 5.2.2 |
| [pinia](https://pinia.vuejs.org/) | Vue 存储库 替代 vuex5 | 2.1.7 |
| [vueuse](https://vueuse.org/) | 常用工具集 | 10.5.0 |
| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.5.0 |
| [vueuse](https://vueuse.org/) | 常用工具集 | 10.6.1 |
| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.6.5 |
| [vue-router](https://router.vuejs.org/) | Vue 路由 | 4.2.5 |
| [unocss](https://uno.antfu.me/) | 原子 css | 0.56.5 |
| [unocss](https://uno.antfu.me/) | 原子 css | 0.57.4 |
| [iconify](https://icon-sets.iconify.design/) | 在线图标库 | 3.1.1 |
| [wangeditor](https://www.wangeditor.com/) | 富文本编辑器 | 5.1.23 |
+28 -28
View File
@@ -31,23 +31,23 @@
"@form-create/element-ui": "^3.1.24",
"@iconify/iconify": "^3.1.1",
"@videojs-player/vue": "^1.0.0",
"@vueuse/core": "^10.5.0",
"@vueuse/core": "^10.6.1",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.10",
"@zxcvbn-ts/core": "^3.0.4",
"animate.css": "^4.1.1",
"axios": "^1.6.0",
"axios": "^1.6.1",
"benz-amr-recorder": "^1.1.5",
"bpmn-js-token-simulation": "^0.10.0",
"camunda-bpmn-moddle": "^7.0.1",
"cropperjs": "^1.6.1",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.10",
"diagram-js": "^12.6.0",
"driver.js": "^1.3.0",
"diagram-js": "^12.8.0",
"driver.js": "^1.3.1",
"echarts": "^5.4.3",
"echarts-wordcloud": "^2.1.0",
"element-plus": "2.4.1",
"element-plus": "2.4.2",
"fast-xml-parser": "^4.3.2",
"highlight.js": "^11.9.0",
"jsencrypt": "^3.3.2",
@@ -62,9 +62,9 @@
"steady-xml": "^0.1.0",
"url": "^0.11.3",
"video.js": "^7.21.5",
"vue": "^3.3.7",
"vue": "^3.3.8",
"vue-dompurify-html": "^4.1.4",
"vue-i18n": "^9.6.2",
"vue-i18n": "^9.6.5",
"vue-router": "^4.2.5",
"vue-types": "^5.1.1",
"vuedraggable": "^4.1.0",
@@ -72,49 +72,49 @@
"xml-js": "^1.6.11"
},
"devDependencies": {
"@commitlint/cli": "^18.2.0",
"@commitlint/config-conventional": "^18.1.0",
"@iconify/json": "^2.2.135",
"@intlify/unplugin-vue-i18n": "^1.4.0",
"@commitlint/cli": "^18.4.1",
"@commitlint/config-conventional": "^18.4.0",
"@iconify/json": "^2.2.142",
"@intlify/unplugin-vue-i18n": "^1.5.0",
"@purge-icons/generated": "^0.9.0",
"@types/lodash-es": "^4.17.10",
"@types/node": "^20.8.9",
"@types/nprogress": "^0.2.2",
"@types/qrcode": "^1.5.4",
"@types/qs": "^6.9.9",
"@types/sortablejs": "^1.15.4",
"@typescript-eslint/eslint-plugin": "^6.9.1",
"@typescript-eslint/parser": "^6.9.1",
"@unocss/transformer-variant-group": "^0.57.1",
"@unocss/eslint-config": "^0.57.1",
"@types/lodash-es": "^4.17.11",
"@types/node": "^20.9.0",
"@types/nprogress": "^0.2.3",
"@types/qrcode": "^1.5.5",
"@types/qs": "^6.9.10",
"@types/sortablejs": "^1.15.5",
"@typescript-eslint/eslint-plugin": "^6.11.0",
"@typescript-eslint/parser": "^6.11.0",
"@unocss/transformer-variant-group": "^0.57.4",
"@unocss/eslint-config": "^0.57.4",
"@vitejs/plugin-legacy": "^4.1.1",
"@vitejs/plugin-vue": "^4.4.0",
"@vitejs/plugin-vue": "^4.4.1",
"@vitejs/plugin-vue-jsx": "^3.0.2",
"autoprefixer": "^10.4.16",
"bpmn-js": "8.9.0",
"bpmn-js-properties-panel": "0.46.0",
"consola": "^3.2.3",
"eslint": "^8.52.0",
"eslint": "^8.53.0",
"eslint-config-prettier": "^9.0.0",
"eslint-define-config": "^1.24.1",
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-vue": "^9.18.1",
"lint-staged": "^15.0.2",
"lint-staged": "^15.1.0",
"postcss": "^8.4.31",
"postcss-html": "^1.5.0",
"postcss-scss": "^4.0.9",
"prettier": "^3.0.3",
"prettier": "^3.1.0",
"rimraf": "^5.0.5",
"rollup": "^4.1.5",
"rollup": "^4.4.1",
"sass": "^1.69.5",
"stylelint": "^15.11.0",
"stylelint-config-html": "^1.1.0",
"stylelint-config-recommended": "^13.0.0",
"stylelint-config-standard": "^34.0.0",
"stylelint-order": "^6.0.3",
"terser": "^5.23.0",
"terser": "^5.24.0",
"typescript": "5.2.2",
"unocss": "^0.57.1",
"unocss": "^0.57.4",
"unplugin-auto-import": "^0.16.7",
"unplugin-element-plus": "^0.8.0",
"unplugin-vue-components": "^0.25.2",
+65
View File
@@ -0,0 +1,65 @@
/*
* @Author: zyna
* @Date: 2023-11-05 13:34:41
* @LastEditTime: 2023-11-11 16:20:19
* @FilePath: \yudao-ui-admin-vue3\src\api\crm\contact\index.ts
* @Description:
*/
import request from '@/config/axios'
export interface ContactVO {
name: string
nextTime: Date
mobile: string
telephone: string
email: string
post: string
customerId: number
address: string
remark: string
ownerUserId: string
lastTime: Date
id: number
parentId: number
qq: number
webchat: string
sex: number
policyMakers: boolean
creatorName: string
updateTime?: Date
createTime?: Date
customerName: string
}
// 查询crm联系人列表
export const getContactPage = async (params) => {
return await request.get({ url: `/crm/contact/page`, params })
}
// 查询crm联系人详情
export const getContact = async (id: number) => {
return await request.get({ url: `/crm/contact/get?id=` + id })
}
// 新增crm联系人
export const createContact = async (data: ContactVO) => {
return await request.post({ url: `/crm/contact/create`, data })
}
// 修改crm联系人
export const updateContact = async (data: ContactVO) => {
return await request.put({ url: `/crm/contact/update`, data })
}
// 删除crm联系人
export const deleteContact = async (id: number) => {
return await request.delete({ url: `/crm/contact/delete?id=` + id })
}
// 导出crm联系人 Excel
export const exportContact = async (params) => {
return await request.download({ url: `/crm/contact/export-excel`, params })
}
export const simpleAlllist = async () => {
return await request.get({ url: `/crm/contact/simpleAlllist` })
}
+5 -5
View File
@@ -67,6 +67,11 @@ export type CodegenCreateListReqVO = {
tableNames: string[]
}
// 查询列表代码生成表定义
export const getCodegenTableList = (dataSourceConfigId: number) => {
return request.get({ url: '/infra/codegen/table/list?dataSourceConfigId=' + dataSourceConfigId })
}
// 查询列表代码生成表定义
export const getCodegenTablePage = (params: PageParam) => {
return request.get({ url: '/infra/codegen/table/page', params })
@@ -92,11 +97,6 @@ export const syncCodegenFromDB = (id: number) => {
return request.put({ url: '/infra/codegen/sync-from-db?tableId=' + id })
}
// 基于 SQL 建表语句,同步数据库的表和字段定义
export const syncCodegenFromSQL = (id: number, sql: string) => {
return request.put({ url: '/infra/codegen/sync-from-sql?tableId=' + id + '&sql=' + sql })
}
// 预览生成代码
export const previewCodegen = (id: number) => {
return request.get({ url: '/infra/codegen/preview?tableId=' + id })
+40
View File
@@ -0,0 +1,40 @@
import request from '@/config/axios'
export interface Demo01ContactVO {
id: number
name: string
sex: number
birthday: Date
description: string
avatar: string
}
// 查询示例联系人分页
export const getDemo01ContactPage = async (params) => {
return await request.get({ url: `/infra/demo01-contact/page`, params })
}
// 查询示例联系人详情
export const getDemo01Contact = async (id: number) => {
return await request.get({ url: `/infra/demo01-contact/get?id=` + id })
}
// 新增示例联系人
export const createDemo01Contact = async (data: Demo01ContactVO) => {
return await request.post({ url: `/infra/demo01-contact/create`, data })
}
// 修改示例联系人
export const updateDemo01Contact = async (data: Demo01ContactVO) => {
return await request.put({ url: `/infra/demo01-contact/update`, data })
}
// 删除示例联系人
export const deleteDemo01Contact = async (id: number) => {
return await request.delete({ url: `/infra/demo01-contact/delete?id=` + id })
}
// 导出示例联系人 Excel
export const exportDemo01Contact = async (params) => {
return await request.download({ url: `/infra/demo01-contact/export-excel`, params })
}
+37
View File
@@ -0,0 +1,37 @@
import request from '@/config/axios'
export interface Demo02CategoryVO {
id: number
name: string
parentId: number
}
// 查询示例分类列表
export const getDemo02CategoryList = async (params) => {
return await request.get({ url: `/infra/demo02-category/list`, params })
}
// 查询示例分类详情
export const getDemo02Category = async (id: number) => {
return await request.get({ url: `/infra/demo02-category/get?id=` + id })
}
// 新增示例分类
export const createDemo02Category = async (data: Demo02CategoryVO) => {
return await request.post({ url: `/infra/demo02-category/create`, data })
}
// 修改示例分类
export const updateDemo02Category = async (data: Demo02CategoryVO) => {
return await request.put({ url: `/infra/demo02-category/update`, data })
}
// 删除示例分类
export const deleteDemo02Category = async (id: number) => {
return await request.delete({ url: `/infra/demo02-category/delete?id=` + id })
}
// 导出示例分类 Excel
export const exportDemo02Category = async (params) => {
return await request.download({ url: `/infra/demo02-category/export-excel`, params })
}
+91
View File
@@ -0,0 +1,91 @@
import request from '@/config/axios'
export interface Demo03StudentVO {
id: number
name: string
sex: number
birthday: Date
description: string
}
// 查询学生分页
export const getDemo03StudentPage = async (params) => {
return await request.get({ url: `/infra/demo03-student/page`, params })
}
// 查询学生详情
export const getDemo03Student = async (id: number) => {
return await request.get({ url: `/infra/demo03-student/get?id=` + id })
}
// 新增学生
export const createDemo03Student = async (data: Demo03StudentVO) => {
return await request.post({ url: `/infra/demo03-student/create`, data })
}
// 修改学生
export const updateDemo03Student = async (data: Demo03StudentVO) => {
return await request.put({ url: `/infra/demo03-student/update`, data })
}
// 删除学生
export const deleteDemo03Student = async (id: number) => {
return await request.delete({ url: `/infra/demo03-student/delete?id=` + id })
}
// 导出学生 Excel
export const exportDemo03Student = async (params) => {
return await request.download({ url: `/infra/demo03-student/export-excel`, params })
}
// ==================== 子表(学生课程) ====================
// 获得学生课程分页
export const getDemo03CoursePage = async (params) => {
return await request.get({ url: `/infra/demo03-student/demo03-course/page`, params })
}
// 新增学生课程
export const createDemo03Course = async (data) => {
return await request.post({ url: `/infra/demo03-student/demo03-course/create`, data })
}
// 修改学生课程
export const updateDemo03Course = async (data) => {
return await request.put({ url: `/infra/demo03-student/demo03-course/update`, data })
}
// 删除学生课程
export const deleteDemo03Course = async (id: number) => {
return await request.delete({ url: `/infra/demo03-student/demo03-course/delete?id=` + id })
}
// 获得学生课程
export const getDemo03Course = async (id: number) => {
return await request.get({ url: `/infra/demo03-student/demo03-course/get?id=` + id })
}
// ==================== 子表(学生班级) ====================
// 获得学生班级分页
export const getDemo03GradePage = async (params) => {
return await request.get({ url: `/infra/demo03-student/demo03-grade/page`, params })
}
// 新增学生班级
export const createDemo03Grade = async (data) => {
return await request.post({ url: `/infra/demo03-student/demo03-grade/create`, data })
}
// 修改学生班级
export const updateDemo03Grade = async (data) => {
return await request.put({ url: `/infra/demo03-student/demo03-grade/update`, data })
}
// 删除学生班级
export const deleteDemo03Grade = async (id: number) => {
return await request.delete({ url: `/infra/demo03-student/demo03-grade/delete?id=` + id })
}
// 获得学生班级
export const getDemo03Grade = async (id: number) => {
return await request.get({ url: `/infra/demo03-student/demo03-grade/get?id=` + id })
}
+53
View File
@@ -0,0 +1,53 @@
import request from '@/config/axios'
export interface Demo03StudentVO {
id: number
name: string
sex: number
birthday: Date
description: string
}
// 查询学生分页
export const getDemo03StudentPage = async (params) => {
return await request.get({ url: `/infra/demo03-student/page`, params })
}
// 查询学生详情
export const getDemo03Student = async (id: number) => {
return await request.get({ url: `/infra/demo03-student/get?id=` + id })
}
// 新增学生
export const createDemo03Student = async (data: Demo03StudentVO) => {
return await request.post({ url: `/infra/demo03-student/create`, data })
}
// 修改学生
export const updateDemo03Student = async (data: Demo03StudentVO) => {
return await request.put({ url: `/infra/demo03-student/update`, data })
}
// 删除学生
export const deleteDemo03Student = async (id: number) => {
return await request.delete({ url: `/infra/demo03-student/delete?id=` + id })
}
// 导出学生 Excel
export const exportDemo03Student = async (params) => {
return await request.download({ url: `/infra/demo03-student/export-excel`, params })
}
// ==================== 子表(学生课程) ====================
// 获得学生课程列表
export const getDemo03CourseListByStudentId = async (studentId) => {
return await request.get({ url: `/infra/demo03-student/demo03-course/list-by-student-id?studentId=` + studentId })
}
// ==================== 子表(学生班级) ====================
// 获得学生班级
export const getDemo03GradeByStudentId = async (studentId) => {
return await request.get({ url: `/infra/demo03-student/demo03-grade/get-by-student-id?studentId=` + studentId })
}
+53
View File
@@ -0,0 +1,53 @@
import request from '@/config/axios'
export interface Demo03StudentVO {
id: number
name: string
sex: number
birthday: Date
description: string
}
// 查询学生分页
export const getDemo03StudentPage = async (params) => {
return await request.get({ url: `/infra/demo03-student/page`, params })
}
// 查询学生详情
export const getDemo03Student = async (id: number) => {
return await request.get({ url: `/infra/demo03-student/get?id=` + id })
}
// 新增学生
export const createDemo03Student = async (data: Demo03StudentVO) => {
return await request.post({ url: `/infra/demo03-student/create`, data })
}
// 修改学生
export const updateDemo03Student = async (data: Demo03StudentVO) => {
return await request.put({ url: `/infra/demo03-student/update`, data })
}
// 删除学生
export const deleteDemo03Student = async (id: number) => {
return await request.delete({ url: `/infra/demo03-student/delete?id=` + id })
}
// 导出学生 Excel
export const exportDemo03Student = async (params) => {
return await request.download({ url: `/infra/demo03-student/export-excel`, params })
}
// ==================== 子表(学生课程) ====================
// 获得学生课程列表
export const getDemo03CourseListByStudentId = async (studentId) => {
return await request.get({ url: `/infra/demo03-student/demo03-course/list-by-student-id?studentId=` + studentId })
}
// ==================== 子表(学生班级) ====================
// 获得学生班级
export const getDemo03GradeByStudentId = async (studentId) => {
return await request.get({ url: `/infra/demo03-student/demo03-grade/get-by-student-id?studentId=` + studentId })
}
@@ -57,7 +57,7 @@ export const updateCombinationActivity = async (data: CombinationActivityVO) =>
// 关闭拼团活动
export const closeCombinationActivity = async (id: number) => {
return await request.put({ url: '/promotion/bargain-combination/close?id=' + id })
return await request.put({ url: '/promotion/combination-activity/close?id=' + id })
}
// 删除拼团活动
+856 -1
View File
@@ -1 +1,856 @@
{"type":"FeatureCollection","features":[{"type":"Feature","id":"710000","properties":{"id":"710000","cp":[121.509062,24.044332],"name":"台湾","childNum":6},"geometry":{"type":"MultiPolygon","coordinates":[["@@°Ü¯Û"],["@@ƛĴÕƊÉɼģºðʀ\\ƎsÆNŌÔĚäœnÜƤɊĂǀĆĴžĤNJŨxĚĮǂƺòƌ‚–âÔ®ĮXŦţƸZûЋƕƑGđ¨ĭMó·ęcëƝɉlÝƯֹÅŃ^Ó·śŃNjƏďíåɛGɉ™¿@ăƑŽ¥ĘWǬÏĶŁâ"],["@@\\p|WoYG¿¥I†j@¢"],["@@…¡‰@ˆV^RqˆBbAŒnTXeRz¤Lž«³I"],["@@ÆEE—„kWqë @œ"],["@@fced"],["@@„¯ɜÄèaì¯ØǓIġĽ"],["@@çûĖ롖hòř "]],"encodeOffsets":[[[122886,24033]],[[123335,22980]],[[122375,24193]],[[122518,24117]],[[124427,22618]],[[124862,26043]],[[126259,26318]],[[127671,26683]]]}},{"type":"Feature","id":"130000","properties":{"id":"130000","cp":[114.502461,38.045474],"name":"河北","childNum":3},"geometry":{"type":"MultiPolygon","coordinates":[["@@o~†Z]‚ªr‰ºc_ħ²G¼s`jΟnüsœłNX_“M`ǽÓnUK…Ĝēs¤­©yrý§uģŒc†JŠ›e"],["@@U`Ts¿m‚"],["@@oºƋÄd–eVŽDJj£€J|Ådz•Ft~žKŨ¸IÆv|”‡¢r}膎onb˜}`RÎÄn°ÒdÞ²„^®’lnÐèĄlðӜ×]ªÆ}LiĂ±Ö`^°Ç¶p®đDcœŋ`–ZÔ’¶êqvFƚ†N®ĆTH®¦O’¾ŠIbÐã´BĐɢŴÆíȦp–ĐÞXR€·nndOž¤’OÀĈƒ­Qg˜µFo|gȒęSWb©osx|hYh•gŃfmÖĩnº€T̒Sp›¢dYĤ¶UĈjl’ǐpäìë|³kÛfw²Xjz~ÂqbTŠÑ„ěŨ@|oM‡’zv¢ZrÃVw¬ŧˏfŒ°ÐT€ªqŽs{Sž¯r æÝlNd®²Ğ džiGʂJ™¼lr}~K¨ŸƐÌWö€™ÆŠzRš¤lêmĞL΄’@¡|q]SvK€ÑcwpÏρ†ĿćènĪWlĄkT}ˆJ”¤~ƒÈT„d„™pddʾĬŠ”ŽBVt„EÀ¢ôPĎƗè@~‚k–ü\\rÊĔÖæW_§¼F˜†´©òDòj’ˆYÈrbĞāøŀG{ƀ|¦ðrb|ÀH`pʞkv‚GpuARhÞÆǶgƊTǼƹS£¨¡ù³ŘÍ]¿Ây™ôEP xX¶¹܇O¡“gÚ¡IwÃ鑦ÅB‡Ï|ǰ…N«úmH¯‹âŸDùŽyŜžŲIÄuШDž•¸dɂ‡‚FŸƒ•›Oh‡đ©OŸ›iÃ`ww^ƒÌkŸ‘ÑH«ƇǤŗĺtFu…{Z}Ö@U‡´…ʚLg®¯Oı°ÃwŸ ^˜—€VbÉs‡ˆmA…ê]]w„§›RRl£‡ȭµu¯b{ÍDěïÿȧŽuT£ġƒěŗƃĝ“Q¨fV†Ƌ•ƅn­a@‘³@šď„yýIĹÊKšŭfċŰóŒxV@tˆƯŒJ”]eƒR¾fe|rHA˜|h~Ėƍl§ÏŠlTíb ØoˆÅbbx³^zÃ͚¶Sj®A”yÂhðk`š«P€”ˈµEF†Û¬Y¨Ļrõqi¼‰Wi°§’б´°^[ˆÀ|ĠO@ÆxO\\tŽa\\tĕtû{ġŒȧXýĪÓjùÎRb›š^ΛfK[ݏděYfíÙTyŽuUSyŌŏů@Oi½’éŅ­aVcř§ax¹XŻác‡žWU£ôãºQ¨÷Ñws¥qEH‰Ù|‰›šYQoŕÇyáĂ£MðoťÊ‰P¡mšWO¡€v†{ôvîēÜISpÌhp¨ ‘j†deŔQÖj˜X³à™Ĉ[n`Yp@Už–cM`’RKhŒEbœ”pŞlNut®Etq‚nsÁŠgA‹iú‹oH‡qCX‡”hfgu“~ϋWP½¢G^}¯ÅīGCŸÑ^ãziMáļMTÃƘrMc|O_ž¯Ŏ´|‡morDkO\\mĆJfl@c̬¢aĦtRıҙ¾ùƀ^juųœK­ƒUFy™—Ɲ…›īÛ÷ąV×qƥV¿aȉd³B›qPBm›aËđŻģm“Å®Vйd^K‡KoŸnYg“¯Xhqa”Ldu¥•ÍpDž¡KąÅƒkĝęěhq‡}HyÓ]¹ǧ£…Í÷¿qáµ§š™g‘¤o^á¾ZE‡¤i`ij{n•ƒOl»ŸWÝĔįhg›F[¿¡—ßkOüš_‰€ū‹i„DZàUtėGylƒ}ŒÓM}€jpEC~¡FtoQi‘šHkk{Ãmï‚"]],"encodeOffsets":[[[119712,40641]],[[121616,39981]],[[116462,37237]]]}},{"type":"Feature","id":"140000","properties":{"id":"140000","cp":[111.849248,36.857014],"name":"山西","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@Þĩ҃S‰ra}Á€yWix±Üe´lè“ßÓǏok‘ćiµVZģ¡coœ‘TS˹ĪmnÕńe–hZg{gtwªpXaĚThȑp{¶Eh—®RćƑP¿£‘Pmc¸mQÝW•ďȥoÅîɡųAďä³aωJ‘½¥PG­ąSM­™…EÅruµé€‘Yӎ•Ō_d›ĒCo­Èµ]¯_²ÕjāŽK~©ÅØ^ԛkïçămϑk]­±ƒcݯÑÃmQÍ~_a—pm…~ç¡q“ˆu{JÅŧ·Ls}–EyÁÆcI{¤IiCfUc•ƌÃp§]웫vD@¡SÀ‘µM‚ÅwuŽYY‡¡DbÑc¡hƒ×]nkoQdaMç~eD•ÛtT‰©±@¥ù@É¡‰ZcW|WqOJmĩl«ħşvOÓ«IqăV—¥ŸD[mI~Ó¢cehiÍ]Ɠ~ĥqXŠ·eƷœn±“}v•[ěďŽŕ]_‘œ•`‰¹ƒ§ÕōI™o©b­s^}Ét±ū«³p£ÿ·Wµ|¡¥ăFÏs׌¥ŅxŸÊdÒ{ºvĴÎêÌɊ²¶€ü¨|ÞƸµȲ‘LLúÉƎ¤ϊęĔV`„_bª‹S^|ŸdŠzY|dz¥p†ZbÆ£¶ÒK}tĦÔņƠ‚PYzn€ÍvX¶Ěn ĠÔ„zý¦ª˜÷žÑĸَUȌ¸‚dòÜJð´’ìúNM¬ŒXZ´‘¤ŊǸ_tldIš{¦ƀðĠȤ¥NehXnYG‚‡R° ƬDj¬¸|CĞ„Kq‚ºfƐiĺ©ª~ĆOQª ¤@ìǦɌ²æBŒÊ”TœŸ˜ʂōĖ’šĴŞ–ȀœÆÿȄlŤĒö„t”νî¼ĨXhŒ‘˜|ªM¤Ðz"],"encodeOffsets":[[116874,41716]]}},{"type":"Feature","id":"150000","properties":{"id":"150000","cp":[111.670801,41.818311],"name":"内蒙古","childNum":2},"geometry":{"type":"MultiPolygon","coordinates":[["@@¯PqƒFB…‰|S•³C|kñ•H‹d‘iÄ¥sˆʼnő…PóÑÑE^‘ÅPpy_YtS™hQ·aHwsOnʼnÚs©iqj›‰€USiº]ïWš‰«gW¡A–Rë¥_ŽsgÁnUI«m‰…„‹]j‡vV¼euhwqA„aW˜ƒ_µj…»çjioQR¹ēÃßt@r³[ÛlćË^ÍÉáG“›OUۗOB±•XŸkŇ¹£k|e]ol™ŸkVͼÕqtaÏõjgÁ£§U^Œ”RLˆËnX°Ç’Bz†^~wfvˆypV ¯„ƫĉ˭ȫƗŷɿÿĿƑ˃ĝÿÃǃßËőó©ǐȍŒĖM×ÍEyx‹þp]Évïè‘vƀnÂĴÖ@‚‰†V~Ĉv¦wĖt—ējyÄDXÄxGQuv_›i¦aBçw‘˛wD™©{ŸtāmQ€{EJ§KPśƘƿ¥@‰sCT•É}ɃwˆƇy±ŸgÑ“}T[÷kÐ禫…SÒ¥¸ëBX½‰HáŵÀğtSÝÂa[ƣ°¯¦P]£ġ“–“Òk®G²„èQ°óMq}EŠLine truncated
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"id": "710000",
"properties": {
"id": "710000",
"cp": [121.509062, 24.044332],
"name": "台湾",
"childNum": 6
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
["@@°Ü¯Û"],
[
"@@ƛĴÕƊÉɼģºðʀ\\ƎsÆNŌÔĚäœnÜƤɊĂǀĆĴžĤNJŨxĚĮǂƺòƌ‚–âÔ®ĮXŦţƸZûЋƕƑGđ¨ĭMó·ęcëƝɉlÝƯֹÅŃ^Ó·śŃNjƏďíåɛGɉ™¿@ăƑŽ¥ĘWǬÏĶŁâ"
],
["@@\\p|WoYG¿¥I†j@¢"],
["@@…¡‰@ˆV^RqˆBbAŒnTXeRz¤Lž«³I"],
["@@ÆEE—„kWqë @œ"],
["@@fced"],
["@@„¯ɜÄèaì¯ØǓIġĽ"],
["@@çûĖ롖hòř "]
],
"encodeOffsets": [
[[122886, 24033]],
[[123335, 22980]],
[[122375, 24193]],
[[122518, 24117]],
[[124427, 22618]],
[[124862, 26043]],
[[126259, 26318]],
[[127671, 26683]]
]
}
},
{
"type": "Feature",
"id": "130000",
"properties": {
"id": "130000",
"cp": [114.502461, 38.045474],
"name": "河北",
"childNum": 3
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
["@@o~†Z]‚ªr‰ºc_ħ²G¼s`jΟnüsœłNX_“M`ǽÓnUK…Ĝēs¤­©yrý§uģŒc†JŠ›e"],
["@@U`Ts¿m‚"],
[
"@@oºƋÄd–eVŽDJj£€J|Ådz•Ft~žKŨ¸IÆv|”‡¢r}膎onb˜}`RÎÄn°ÒdÞ²„^®’lnÐèĄlðӜ×]ªÆ}LiĂ±Ö`^°Ç¶p®đDcœŋ`–ZÔ’¶êqvFƚ†N®ĆTH®¦O’¾ŠIbÐã´BĐɢŴÆíȦp–ĐÞXR€·nndOž¤’OÀĈƒ­Qg˜µFo|gȒęSWb©osx|hYh•gŃfmÖĩnº€T̒Sp›¢dYĤ¶UĈjl’ǐpäìë|³kÛfw²Xjz~ÂqbTŠÑ„ěŨ@|oM‡’zv¢ZrÃVw¬ŧˏfŒ°ÐT€ªqŽs{Sž¯r æÝlNd®²Ğ džiGʂJ™¼lr}~K¨ŸƐÌWö€™ÆŠzRš¤lêmĞL΄’@¡|q]SvK€ÑcwpÏρ†ĿćènĪWlĄkT}ˆJ”¤~ƒÈT„d„™pddʾĬŠ”ŽBVt„EÀ¢ôPĎƗè@~‚k–ü\\rÊĔÖæW_§¼F˜†´©òDòj’ˆYÈrbĞāøŀG{ƀ|¦ðrb|ÀH`pʞkv‚GpuARhÞÆǶgƊTǼƹS£¨¡ù³ŘÍ]¿Ây™ôEP xX¶¹܇O¡“gÚ¡IwÃ鑦ÅB‡Ï|ǰ…N«úmH¯‹âŸDùŽyŜžŲIÄuШDž•¸dɂ‡‚FŸƒ•›Oh‡đ©OŸ›iÃ`ww^ƒÌkŸ‘ÑH«ƇǤŗĺtFu…{Z}Ö@U‡´…ʚLg®¯Oı°ÃwŸ ^˜—€VbÉs‡ˆmA…ê]]w„§›RRl£‡ȭµu¯b{ÍDěïÿȧŽuT£ġƒěŗƃĝ“Q¨fV†Ƌ•ƅn­a@‘³@šď„yýIĹÊKšŭfċŰóŒxV@tˆƯŒJ”]eƒR¾fe|rHA˜|h~Ėƍl§ÏŠlTíb ØoˆÅbbx³^zÃ͚¶Sj®A”yÂhðk`š«P€”ˈµEF†Û¬Y¨Ļrõqi¼‰Wi°§’б´°^[ˆÀ|ĠO@ÆxO\\tŽa\\tĕtû{ġŒȧXýĪÓjùÎRb›š^ΛfK[ݏděYfíÙTyŽuUSyŌŏů@Oi½’éŅ­aVcř§ax¹XŻác‡žWU£ôãºQ¨÷Ñws¥qEH‰Ù|‰›šYQoŕÇyáĂ£MðoťÊ‰P¡mšWO¡€v†{ôvîēÜISpÌhp¨ ‘j†deŔQÖj˜X³à™Ĉ[n`Yp@Už–cM`’RKhŒEbœ”pŞlNut®Etq‚nsÁŠgA‹iú‹oH‡qCX‡”hfgu“~ϋWP½¢G^}¯ÅīGCŸÑ^ãziMáļMTÃƘrMc|O_ž¯Ŏ´|‡morDkO\\mĆJfl@c̬¢aĦtRıҙ¾ùƀ^juųœK­ƒUFy™—Ɲ…›īÛ÷ąV×qƥV¿aȉd³B›qPBm›aËđŻģm“Å®Vйd^K‡KoŸnYg“¯Xhqa”Ldu¥•ÍpDž¡KąÅƒkĝęěhq‡}HyÓ]¹ǧ£…Í÷¿qáµ§š™g‘¤o^á¾ZE‡¤i`ij{n•ƒOl»ŸWÝĔįhg›F[¿¡—ßkOüš_‰€ū‹i„DZàUtėGylƒ}ŒÓM}€jpEC~¡FtoQi‘šHkk{Ãmï‚"
]
],
"encodeOffsets": [[[119712, 40641]], [[121616, 39981]], [[116462, 37237]]]
}
},
{
"type": "Feature",
"id": "140000",
"properties": {
"id": "140000",
"cp": [111.849248, 36.857014],
"name": "山西",
"childNum": 1
},
"geometry": {
"type": "Polygon",
"coordinates": [
"@@Þĩ҃S‰ra}Á€yWix±Üe´lè“ßÓǏok‘ćiµVZģ¡coœ‘TS˹ĪmnÕńe–hZg{gtwªpXaĚThȑp{¶Eh—®RćƑP¿£‘Pmc¸mQÝW•ďȥoÅîɡųAďä³aωJ‘½¥PG­ąSM­™…EÅruµé€‘Yӎ•Ō_d›ĒCo­Èµ]¯_²ÕjāŽK~©ÅØ^ԛkïçămϑk]­±ƒcݯÑÃmQÍ~_a—pm…~ç¡q“ˆu{JÅŧ·Ls}–EyÁÆcI{¤IiCfUc•ƌÃp§]웫vD@¡SÀ‘µM‚ÅwuŽYY‡¡DbÑc¡hƒ×]nkoQdaMç~eD•ÛtT‰©±@¥ù@É¡‰ZcW|WqOJmĩl«ħşvOÓ«IqăV—¥ŸD[mI~Ó¢cehiÍ]Ɠ~ĥqXŠ·eƷœn±“}v•[ěďŽŕ]_‘œ•`‰¹ƒ§ÕōI™o©b­s^}Ét±ū«³p£ÿ·Wµ|¡¥ăFÏs׌¥ŅxŸÊdÒ{ºvĴÎêÌɊ²¶€ü¨|ÞƸµȲ‘LLúÉƎ¤ϊęĔV`„_bª‹S^|ŸdŠzY|dz¥p†ZbÆ£¶ÒK}tĦÔņƠ‚PYzn€ÍvX¶Ěn ĠÔ„zý¦ª˜÷žÑĸَUȌ¸‚dòÜJð´’ìúNM¬ŒXZ´‘¤ŊǸ_tldIš{¦ƀðĠȤ¥NehXnYG‚‡R° ƬDj¬¸|CĞ„Kq‚ºfƐiĺ©ª~ĆOQª ¤@ìǦɌ²æBŒÊ”TœŸ˜ʂōĖ’šĴŞ–ȀœÆÿȄlŤĒö„t”νî¼ĨXhŒ‘˜|ªM¤Ðz"
],
"encodeOffsets": [[116874, 41716]]
}
},
{
"type": "Feature",
"id": "150000",
"properties": {
"id": "150000",
"cp": [111.670801, 41.818311],
"name": "内蒙古",
"childNum": 2
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
"@@¯PqƒFB…‰|S•³C|kñ•H‹d‘iÄ¥sˆʼnő…PóÑÑE^‘ÅPpy_YtS™hQ·aHwsOnʼnÚs©iqj›‰€USiº]ïWš‰«gW¡A–Rë¥_ŽsgÁnUI«m‰…„‹]j‡vV¼euhwqA„aW˜ƒ_µj…»çjioQR¹ēÃßt@r³[ÛlćË^ÍÉáG“›OUۗOB±•XŸkŇ¹£k|e]ol™ŸkVͼÕqtaÏõjgÁ£§U^Œ”RLˆËnX°Ç’Bz†^~wfvˆypV ¯„ƫĉ˭ȫƗŷɿÿĿƑ˃ĝÿÃǃßËőó©ǐȍŒĖM×ÍEyx‹þp]Évïè‘vƀnÂĴÖ@‚‰†V~Ĉv¦wĖt—ējyÄDXÄxGQuv_›i¦aBçw‘˛wD™©{ŸtāmQ€{EJ§KPśƘƿ¥@‰sCT•É}ɃwˆƇy±ŸgÑ“}T[÷kÐ禫…SÒ¥¸ëBX½‰HáŵÀğtSÝÂa[ƣ°¯¦P]£ġ“–“Òk®G²„èQ°óMq}EŠóƐÇ\\ƒ‡@áügQ͋u¥Fƒ“T՛¿Jû‡]|mvāÎYua^WoÀa·­ząÒot×¶CLƗi¯¤mƎHNJ¤îìɾŊìTdåwsRÖgĒųúÍġäÕ}Q¶—ˆ¿A•†‹[¡Œ{d×uQAƒ›M•xV‹vMOmăl«ct[wº_šÇʊŽŸjb£ĦS_é“QZ“_lwgOiýe`YYLq§IÁˆdz£ÙË[ÕªuƏ³ÍT—s·bÁĽäė[›b[ˆŗfãcn¥îC¿÷µ[ŏÀQ­ōšĉm¿Á^£mJVm‡—L[{Ï_£›F¥Ö{ŹA}…×Wu©ÅaųijƳhB{·TQqÙIķˑZđ©Yc|M¡…L•eVUóK_QWk’_ĥ‘¿ãZ•»X\\ĴuUƒè‡lG®ěłTĠğDєOrÍd‚ÆÍz]‹±…ŭ©ŸÅ’]ŒÅÐ}UË¥©Tċ™ïxgckfWgi\\ÏĒ¥HkµE˜ë{»ÏetcG±ahUiñiWsɁˆ·c–C‚Õk]wȑ|ća}w…VaĚ᠞ŒG°ùnM¬¯†{ÈˆÐÆA’¥ÄêJxÙ¢”hP¢Ûˆº€µwWOŸóFŽšÁz^ÀŗÎú´§¢T¤ǻƺSė‰ǵhÝÅQgvBHouʝl_o¿Ga{ïq{¥|ſĿHĂ÷aĝÇq‡Z‘ñiñC³ª—…»E`¨åXēÕqÉû[l•}ç@čƘóO¿¡ƒFUsA‰“ʽīccšocƒ‚ƒÇS}„“£‡IS~ălkĩXçmĈ…ŀЂoÐdxÒuL^T{r@¢‘žÍƒĝKén£kQ™‰yšÅõËXŷƏL§~}kqš»IHėDžjĝŸ»ÑÞoŸå°qTt|r©ÏS‹¯·eŨĕx«È[eMˆ¿yuˆ‘pN~¹ÏyN£{©’—g‹ħWí»Í¾s“əšDž_ÃĀɗ±ą™ijĉʍŌŷ—S›É“A‹±åǥɋ@럣R©ąP©}ĹªƏj¹erƒLDĝ·{i«ƫC£µsKCš…GS|úþX”gp›{ÁX¿Ÿć{ƱȏñZáĔyoÁhA™}ŅĆfdʼn„_¹„Y°ėǩÑ¡H¯¶oMQqð¡Ë™|‘Ñ`ƭŁX½·óۓxğįÅcQ‡ˆ“ƒs«tȋDžF“Ÿù^i‘t«Č¯[›hAi©á¥ÇĚ×l|¹y¯YȵƓ‹ñǙµï‚ċ™Ļ|Dœ™üȭ¶¡˜›oŽäÕG\\ďT¿Òõr¯œŸLguÏYęRƩšɷŌO\\İТæ^Ŋ IJȶȆbÜGŽĝ¬¿ĚVĎgª^íu½jÿĕęjık@Ľƒ]ėl¥Ë‡ĭûÁ„ƒėéV©±ćn©­ȇžÍq¯½•YÃÔʼn“ÉNѝÅÝy¹NqáʅDǡËñ­ƁYÅy̱os§ȋµʽǘǏƬɱà‘ưN¢ƔÊuľýľώȪƺɂļžxœZĈ}ÌʼnŪ˜ĺœŽĭFЛĽ̅ȣͽÒŵìƩÇϋÿȮǡŏçƑůĕ~Ǎ›¼ȳÐUf†dIxÿ\\G ˆzâɏÙOº·pqy£†@ŒŠqþ@Ǟ˽IBäƣzsÂZ†ÁàĻdñ°ŕzéØűzșCìDȐĴĺf®ŽÀľưø@ɜÖÞKĊŇƄ§‚͑těï͡VAġÑÑ»d³öǍÝXĉĕÖ{þĉu¸ËʅğU̎éhɹƆ̗̮ȘNJ֥ड़ࡰţાíϲäʮW¬®ҌeרūȠkɬɻ̼ãüfƠSצɩςåȈHϚÎKdzͲOðÏȆƘ¼CϚǚ࢚˼ФԂ¤ƌžĞ̪Qʤ´¼mȠJˀŸƲÀɠmǐnǔĎȆÞǠN~€ʢĜ‚¶ƌĆĘźʆȬ˪ĚǏĞGȖƴƀj`ĢçĶāàŃºē̃ĖćšYŒÀŎüôQÐÂŎŞdžŞêƖš˜oˆDĤÕºÑǘÛˤ³̀gńƘĔÀ^žªƂ`ªt¾äƚêĦĀ¼Ð€Ĕǎ¨Ȕ»͠^ˮÊȦƤøxRrŜH¤¸ÂxDĝŒ|ø˂˜ƮÐ¬ɚwɲFjĔ²Äw°dždÀɞ_ĸdîàŎjʜêTĞªŌ‡ŜWÈ|tqĢUB~´°ÎFC•ŽU¼pĀēƄN¦¾O¶ŠłKĊOj“Ě”j´ĜYp˜{¦„ˆSĚÍ\\Tš×ªV–÷Ší¨ÅDK°ßtŇĔKš¨ǵÂcḷ̌ĚǣȄĽF‡lġUĵœŇ‹ȣFʉɁƒMğįʏƶɷØŭOǽ«ƽū¹Ʊő̝Ȩ§ȞʘĖiɜɶʦ}¨֪ࠜ̀ƇǬ¹ǨE˦ĥªÔêFŽxúQ„Er´W„rh¤Ɛ \\talĈDJ˜Ü|[Pll̚¸ƎGú´Pž¬W¦†^¦–H]prR“n|or¾wLVnÇIujkmon£cX^Bh`¥V”„¦U¤¸}€xRj–[^xN[~ªŠxQ„‚[`ªHÆÂExx^wšN¶Ê˜|¨ì†˜€MrœdYp‚oRzNy˜ÀDs~€bcfÌ`L–¾n‹|¾T‚°c¨È¢a‚r¤–`[|òDŞĔöxElÖdH„ÀI`„Ď\\Àì~ƎR¼tf•¦^¢ķ¶e”ÐÚMŒptgj–„ɡČÅyġLû™ŇV®ŠÄÈƀ†Ď°P|ªVV†ªj–¬ĚÒêp¬–E|ŬÂc|ÀtƐK fˆ{ĘFǜƌXƲąo½Ę‘\\¥–o}›Ûu£ç­kX‘{uĩ«āíÓUŅßŢq€Ť¥lyň[€oi{¦‹L‡ń‡ðFȪȖ”ĒL„¿Ì‹ˆfŒ£K£ʺ™oqNŸƒwğc`ue—tOj×°KJ±qƒÆġm‰Ěŗos¬…qehqsuœƒH{¸kH¡Š…ÊRǪÇƌbȆ¢´ä܍¢NìÉʖ¦â©Ġu¦öČ^â£Ăh–šĖMÈÄw‚\\fŦ°W ¢¾luŸD„wŠ\\̀ʉÌÛM…Ā[bӞEn}¶Vc…ê“sƒ"
]
],
"encodeOffsets": [[[129102, 52189]]]
}
},
{
"type": "Feature",
"id": "210000",
"properties": {
"id": "210000",
"cp": [123.429096, 41.796767],
"name": "辽宁",
"childNum": 16
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
["@@L–Ž@@s™a"],
["@@MnNm"],
["@@d‚c"],
["@@eÀ‚C@b‚“‰"],
["@@f‡…Xwkbr–Ä`qg"],
["@@^jtW‘Q"],
["@@~ Y]c"],
["@@G`ĔN^_¿Z‚ÃM"],
["@@iX¶B‹Y"],
["@@„YƒZ"],
["@@L_{Epf"],
["@@^WqCT\\"],
["@@\\[“‹§t|”¤_"],
["@@m`n_"],
["@@Ïxnj{q_×^Giip"],
[
"@@@œé^B†‡ntˆaÊU—˜Ÿ]x ¯ÄPIJ­°h€ʙK³†VˆÕ@Y~†|EvĹsDŽ¦­L^p²ŸÒG ’Ël]„xxÄ_˜fT¤Ď¤cŽœP„–C¨¸TVjbgH²sdÎdHt`Bˆ—²¬GJję¶[ÐhjeXdlwhšðSȦªVÊπ‹Æ‘Z˜ÆŶ®²†^ŒÎyÅÎcPqń“ĚDMħĜŁH­ˆk„çvV[ij¼W–‚YÀäĦ’‘`XlžR`žôLUVžfK–¢†{NZdĒª’YĸÌÚJRr¸SA|ƴgŴĴÆbvªØX~†źBŽ|¦ÕœEž¤Ð`\\|Kˆ˜UnnI]¤ÀÂĊnŎ™R®Ő¿¶\\ÀøíDm¦ÎbŨab‰œaĘ\\ľã‚¸a˜tÎSƐ´©v\\ÖÚÌǴ¤Â‡¨JKr€Z_Z€fjþhPkx€`Y”’RIŒjJcVf~sCN¤ ˆE‚œhæm‰–sHy¨SðÑÌ\\\\ŸĐRZk°IS§fqŒßýáЍÙÉÖ[^¯ǤŲ„ê´\\¦¬ĆPM¯£Ÿˆ»uïpùzEx€žanµyoluqe¦W^£ÊL}ñrkqWňûP™‰UP¡ôJŠoo·ŒU}£Œ„[·¨@XŒĸŸ“‹‹DXm­Ûݏº‡›GU‹CÁª½{íĂ^cj‡k“¶Ã[q¤“LÉö³cux«zZfƒ²BWÇ®Yß½ve±ÃC•ý£W{Ú^’q^sÑ·¨‹ÍOt“¹·C¥‡GD›rí@wÕKţ݋˜Ÿ«V·i}xËÍ÷‘i©ĝ‡ɝǡ]ƒˆ{c™±OW‹³Ya±Ÿ‰_穂Hžĕoƫ€Ňqƒr³‰Lys[„ñ³¯OS–ďOMisZ†±ÅFC¥Pq{‚Ã[Pg}\\—¿ghćO…•k^ģÁFıĉĥM­oEqqZûěʼn³F‘¦oĵ—hŸÕP{¯~TÍlª‰N‰ßY“Ð{Ps{ÃVU™™eĎwk±ʼnVÓ½ŽJãÇÇ»Jm°dhcÀff‘dF~ˆ€ĀeĖ€d`sx² šƒ®EżĀdQ‹Âd^~ăÔHˆ¦\\›LKpĄVez¤NP ǹӗR™ÆąJSh­a[¦´Âghwm€BÐ¨źhI|žVVŽ—Ž|p] Â¼èNä¶ÜBÖ¼“L`‚¼bØæŒKV”ŸpoœúNZÞÒKxpw|ÊEMnzEQšŽIZ”ŽZ‡NBˆčÚFÜçmĩ‚WĪñt‘ÞĵÇñZ«uD‚±|Əlij¥ãn·±PmÍa‰–da‡ CL‡Ǒkùó¡³Ï«QaċϑOÃ¥ÕđQȥċƭy‹³ÃA"
]
],
"encodeOffsets": [
[[123686, 41445]],
[[126019, 40435]],
[[124393, 40128]],
[[126117, 39963]],
[[125322, 40140]],
[[126686, 40700]],
[[126041, 40374]],
[[125584, 40168]],
[[125453, 40165]],
[[125362, 40214]],
[[125280, 40291]],
[[125774, 39997]],
[[125976, 40496]],
[[125822, 39993]],
[[125509, 40217]],
[[122731, 40949]]
]
}
},
{
"type": "Feature",
"id": "220000",
"properties": { "id": "220000", "cp": [125.3245, 43.886841], "name": "吉林", "childNum": 1 },
"geometry": {
"type": "Polygon",
"coordinates": [
"@@‘p䔳PClƒFbbÍzš€wBG’ĭ€Z„Åi“»ƒlY­ċ²SgŽkÇ£—^S‰“qd¯•‹R…©éŽ£¯S†\\cZ¹iűƏCuƍÓX‡oR}“M^o•£…R}oªU­F…uuXHlEŕ‡€Ï©¤ÛmTŽþ¤D–²ÄufàÀ­XXȱAe„yYw¬dvõ´KÊ£”\\rµÄl”iˆdā]|DÂVŒœH¹ˆÞ®ÜWnŒC”Œķ W‹§@\\¸‹ƒ~¤‹Vp¸‰póIO¢ŠVOšŇürXql~òÉK]¤¥Xrfkvzpm¶bwyFoúvð‡¼¤ N°ąO¥«³[ƒéǡű_°Õ\\ÚÊĝŽþâőàerR¨­JYlďQ[ ÏYëЧTGz•tnŠß¡gFkMŸāGÁ¤ia É‰™È¹`\\xs€¬dĆkNnuNUŠ–užP@‚vRY¾•–\\¢…ŒGªóĄ~RãÖÎĢù‚đŴÕhQŽxtcæëSɽʼníëlj£ƍG£nj°KƘµDsØÑpyƸ®¿bXp‚]vbÍZuĂ{nˆ^IüœÀSք”¦EŒvRÎûh@℈[‚Əȉô~FNr¯ôçR±ƒ­HÑl•’Ģ–^¤¢‚OðŸŒævxsŒ]ÞÁTĠs¶¿âƊGW¾ìA¦·TѬ†è¥€ÏÐJ¨¼ÒÖ¼ƒƦɄxÊ~S–tD@ŠĂ¼Ŵ¡jlºWžvЉˆzƦZЎ²CH— „Axiukd‹ŒGgetqmcžÛ£Ozy¥cE}|…¾cZ…k‚‰¿uŐã[oxGikfeäT@…šSUwpiÚFM©’£è^ڟ‚`@v¶eň†f h˜eP¶žt“äOlÔUgƒÞzŸU`lœ}ÔÆUvØ_Ō¬Öi^ĉi§²ÃŠB~¡Ĉ™ÚEgc|DC_Ȧm²rBx¼MÔ¦ŮdĨÃâYx‘ƘDVÇĺĿg¿cwÅ\\¹˜¥Yĭlœ¤žOv†šLjM_a W`zļMž·\\swqÝSA‡š—q‰Śij¯Š‘°kŠRē°wx^Đkǂғ„œž“œŽ„‹\\]˜nrĂ}²ĊŲÒøãh·M{yMzysěnĒġV·°“G³¼XÀ““™¤¹i´o¤ŃšŸÈ`̃DzÄUĞd\\i֚ŒˆmÈBĤÜɲDEh LG¾ƀľ{WaŒYÍȏĢĘÔRîĐj‹}Ǟ“ccj‡oUb½š{“h§Ǿ{K‹ƖµÎ÷žGĀÖŠåưÎs­l›•yiē«‹`姝H¥Ae^§„GK}iã\\c]v©ģZ“mÃ|“[M}ģTɟĵ‘Â`À–çm‰‘FK¥ÚíÁbXš³ÌQґHof{‰]e€pt·GŋĜYünĎųVY^’˜ydõkÅZW„«WUa~U·Sb•wGçǑ‚“iW^q‹F‚“›uNĝ—·Ew„‹UtW·Ýďæ©PuqEzwAV•—XR‰ãQ`­©GŒM‡ehc›c”ďϝd‡©ÑW_ϗYƅŒ»…é\\ƒɹ~ǙG³mØ©BšuT§Ĥ½¢Ã_ý‘L¡‘ýŸqT^rme™\\Pp•ZZbƒyŸ’uybQ—efµ]UhĿDCmûvašÙNSkCwn‰cćfv~…Y‹„ÇG"
],
"encodeOffsets": [[130196, 42528]]
}
},
{
"type": "Feature",
"id": "230000",
"properties": {
"id": "230000",
"cp": [128.642464, 46.756967],
"name": "黑龙江",
"childNum": 2
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
"@@UƒµNÿ¥īè灋•HÍøƕ¶LŒǽ|g¨|”™Ža¾pViˆdd”~ÈiŒíďÓQġėǐZ΋ŽXb½|ſÃH½ŸKFgɱCģÛÇA‡n™‹jÕc[VĝDZÃ˄Ç_™ £ń³pŽj£º”š¿”»WH´¯”U¸đĢmžtĜyzzNN|g¸÷äűѱĉā~mq^—Œ[ƒ”››”ƒǁÑďlw]¯xQĔ‰¯l‰’€°řĴrŠ™˜BˆÞTxr[tޏĻN_yŸX`biN™Ku…P›£k‚ZĮ—¦[ºxÆÀdhŽĹŀUÈƗCw’áZħÄŭcÓ¥»NAw±qȥnD`{ChdÙFćš}¢‰A±Äj¨]ĊÕjŋ«×`VuÓś~_kŷVÝyh„“VkÄãPs”Oµ—fŸge‚Ň…µf@u_Ù ÙcŸªNªÙEojVx™T@†ãSefjlwH\\pŏäÀvŠŽlY†½d{†F~¦dyz¤PÜndsrhf‹HcŒvlwjFœ£G˜±DύƥY‡yϊu¹XikĿ¦ÏqƗǀOŜ¨LI|FRĂn sª|Cš˜zxAè¥bœfudTrFWÁ¹Am|˜ĔĕsķÆF‡´Nš‰}ć…UŠÕ@Áijſmužç’uð^ÊýowŒFzØÎĕNőžǏȎôªÌŒDŽàĀÄ˄ĞŀƒʀĀƘŸˮȬƬĊ°ƒUŸzou‡xe]}Ž…AyȑW¯ÌmK‡“Q]‹Īºif¸ÄX|sZt|½ÚUΠlkš^p{f¤lˆºlÆW –€A²˜PVܜPH”Êâ]ÎĈÌÜk´\\@qàsĔÄQºpRij¼èi†`¶—„bXƒrBgxfv»ŽuUiˆŒ^v~”J¬mVp´£Œ´VWrnP½ì¢BX‚¬h™ŠðX¹^TjVœŠriªj™tŊÄm€tPGx¸bgRšŽsT`ZozÆO]’ÒFô҆Oƒ‡ŊŒvŞ”p’cGŒêŠsx´DR–Œ{A†„EOr°Œ•žx|íœbˆ³Wm~DVjºéNN†Ëܲɶ­GƒxŷCStŸ}]ûō•SmtuÇÃĕN•™āg»šíT«u}ç½BĵÞʣ¥ëÊ¡Mێ³ãȅ¡ƋaǩÈÉQ‰†G¢·lG|›„tvgrrf«†ptęŘnŠÅĢr„I²¯LiØsPf˜_vĠd„xM prʹšL¤‹¤‡eˌƒÀđK“žïÙVY§]I‡óáĥ]ķ†Kˆ¥Œj|pŇ\\kzţ¦šnņäÔVĂîά|vW’®l¤èØr‚˜•xm¶ă~lÄƯĄ̈́öȄEÔ¤ØQĄ–Ą»ƢjȦOǺ¨ìSŖÆƬy”Qœv`–cwƒZSÌ®ü±DŽ]ŀç¬B¬©ńzƺŷɄeeOĨS’Œfm Ċ‚ƀP̎ēz©Ċ‚ÄÕÊmgŸÇsJ¥ƔˆŊśæ’΁Ñqv¿íUOµª‰ÂnĦÁ_½ä@ê텣P}Ġ[@gġ}g“ɊדûÏWXá¢užƻÌsNͽƎÁ§č՛AēeL³àydl›¦ĘVçŁpśdžĽĺſʃQíÜçÛġԏsĕ¬—Ǹ¯YßċġHµ ¡eå`ļƒrĉŘóƢFì“ĎWøxÊk†”ƈdƬv|–I|·©NqńRŀƒ¤é”eŊœŀ›ˆàŀU²ŕƀB‚Q£Ď}L¹Îk@©ĈuǰųǨ”Ú§ƈnTËÇéƟÊcfčŤ^Xm‡—HĊĕË«W·ċëx³ǔķÐċJā‚wİ_ĸ˜Ȁ^ôWr­°oú¬Ħ…ŨK~”ȰCĐ´Ƕ£’fNÎèâw¢XnŮeÂÆĶŽ¾¾xäLĴĘlļO¤ÒĨA¢Êɚ¨®‚ØCÔ ŬGƠ”ƦYĜ‡ĘÜƬDJ—g_ͥœ@čŅĻA“¶¯@wÎqC½Ĉ»NŸăëK™ďÍQ“Ùƫ[«Ãí•gßÔÇOÝáW‘ñuZ“¯ĥ€Ÿŕā¡ÑķJu¤E Ÿå¯°WKɱ_d_}}vyŸõu¬ï¹ÓU±½@gÏ¿rýD‰†g…Cd‰µ—°MFYxw¿CG£‹Rƛ½Õ{]L§{qqąš¿BÇƻğëšܭNJË|c²}Fµ}›ÙRsÓpg±ŠQNqǫŋRwŕnéÑÉKŸ†«SeYR…ŋ‹@{¤SJ}šD Ûǖ֍Ÿ]gr¡µŷjqWÛham³~S«“„›Þ]"
]
],
"encodeOffsets": [[[134456, 44547]]]
}
},
{
"type": "Feature",
"id": "320000",
"properties": {
"id": "320000",
"cp": [119.767413, 33.041544],
"name": "江苏",
"childNum": 1
},
"geometry": {
"type": "Polygon",
"coordinates": [
"@@cþÅPiŠ`ZŸRu¥É\\]~°ŽY`µ†Óƒ^phÁbnÀşúŽòa–ĬºTÖŒb‚˜e¦¦€{¸ZâćNpŒ©žHr|^ˆmjhŠSEb\\afv`sz^lkŽlj‹Ätg‹¤D˜­¾Xš¿À’|ДiZ„ȀåB·î}GL¢õcßjaŸyBFµÏC^ĭ•cÙt¿sğH]j{s©HM¢ƒQnDÀ©DaÜތ·jgàiDbPufjDk`dPOîƒhw¡ĥ‡¥šG˜ŸP²ĐobºrY†„î¶aHŢ´ ]´‚rılw³r_{£DB_Ûdåuk|ˆŨ¯F Cºyr{XFy™e³Þċ‡¿Â™kĭB¿„MvÛpm`rÚã”@ƹhågËÖƿxnlč¶Åì½Ot¾dJlŠVJʜǀœŞqvnOŠ^ŸJ”Z‘ż·Q}ê͎ÅmµÒ]Žƍ¦Dq}¬R^èĂ´ŀĻĊIԒtžIJyQŐĠMNtœR®òLh‰›Ěs©»œ}OӌGZz¶A\\jĨFˆäOĤ˜HYš†JvÞHNiÜaϚɖnFQlšNM¤ˆB´ĄNöɂtp–Ŭdf先‹qm¿QûŠùއÚb¤uŃJŴu»¹Ą•lȖħŴw̌ŵ²ǹǠ͛hĭłƕrçü±Y™xci‡tğ®jű¢KOķ•Coy`å®VTa­_Ā]ŐÝɞï²ʯÊ^]afYǸÃĆēĪȣJđ͍ôƋĝÄ͎ī‰çÛɈǥ£­ÛmY`ó£Z«§°Ó³QafusNıDž_k}¢m[ÝóDµ—¡RLčiXy‡ÅNïă¡¸iĔϑNÌŕoēdōîåŤûHcs}~Ûwbù¹£¦ÓCt‹OPrƒE^ÒoŠg™ĉIµžÛÅʹK…¤½phMŠü`o怆ŀ"
],
"encodeOffsets": [[121740, 32276]]
}
},
{
"type": "Feature",
"id": "330000",
"properties": {
"id": "330000",
"cp": [120.153576, 29.287459],
"name": "浙江",
"childNum": 45
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
["@@E^dQ]K"],
["@@jX^j‡"],
["@@sfŠbU‡"],
["@@qP\\xz[ck"],
["@@‘Rƒ¢‚FX}°[s_"],
["@@Cbœ\\—}"],
["@@e|v\\la{u"],
["@@v~u}"],
["@@QxÂF¯}"],
["@@¹nŒvÞs¯o"],
["@@rSkUEj"],
["@@bi­ZŒP"],
["@@p[}INf"],
["@@À¿€"],
["@@¹dnbŒ…"],
["@@rSŸBnR"],
["@@g~h}"],
["@@FlEk"],
["@@OdPc"],
["@@v[u\\"],
["@@FjâL~wyoo~›sµL–\\"],
["@@¬e¹aNˆ"],
["@@\\nÔ¡q]L³ë\\ÿ®ŒQ֎"],
["@@ÊA­©[¬"],
["@@KxŒv­"],
["@@@hlIk]"],
["@@pW{o||j"],
["@@Md|_mC"],
["@@¢…X£ÏylD¼XˆtH"],
["@@hlÜ[LykAvyfw^Ež›¤"],
["@@fp¤Mus“R"],
["@@®_ma~•LÁ¬šZ"],
["@@iM„xZ"],
["@@ZcYd"],
["@@Z~dOSo|A¿qZv"],
["@@@`”EN¡v"],
["@@|–TY{"],
["@@@n@m"],
["@@XWkCT\\"],
["@@ºwšZRkĕWO¢"],
["@@™X®±Grƪ\\ÔáXq{‹"],
["@@ůTG°ĄLHm°UC‹"],
[
"@@¤Ž€aÜx~}dtüGæţŎíĔcŖpMËВj碷ðĄÆMzˆjWKĎ¢Q¶˜À_꒔_Bı€i«pZ€gf€¤Nrq]§ĂN®«H±‡yƳí¾×ŸīàLłčŴǝĂíÀBŖÕªˆŠÁŖHŗʼnåqûõi¨hÜ·ƒñt»¹ýv_[«¸m‰YL¯‰Qª…mĉÅdMˆ•gÇjcº«•ęœ¬­K­´ƒB«Âącoċ\\xKd¡gěŧ«®á’[~ıxu·Å”KsËɏc¢Ù\\ĭƛëbf¹­ģSƒĜkáƉÔ­ĈZB{ŠaM‘µ‰fzʼnfåÂŧįƋǝÊĕġć£g³ne­ą»@­¦S®‚\\ßðCšh™iqªĭiAu‡A­µ”_W¥ƣO\\lċĢttC¨£t`ˆ™PZäuXßBs‡Ļyek€OđġĵHuXBšµ]׌‡­­\\›°®¬F¢¾pµ¼kŘó¬Wät’¸|@ž•L¨¸µr“ºù³Ù~§WI‹ŸZWŽ®’±Ð¨ÒÉx€`‰²pĜ•rOògtÁZ}þÙ]„’¡ŒŸFK‚wsPlU[}¦Rvn`hq¬\\”nQ´ĘRWb”‚_ rtČFI֊kŠŠĦPJ¶ÖÀÖJĈĄTĚòžC ²@Pú…Øzœ©PœCÈÚœĒ±„hŖ‡l¬â~nm¨f©–iļ«m‡nt–u†ÖZÜÄj“ŠLŽ®E̜Fª²iÊxبžIÈhhst"
],
["@@o\\V’zRZ}y"],
["@@†@°¡mۛGĕ¨§Ianá[ýƤjfæ‡ØL–•äGr™"]
],
"encodeOffsets": [
[[125592, 31553]],
[[125785, 31436]],
[[125729, 31431]],
[[125513, 31380]],
[[125223, 30438]],
[[125115, 30114]],
[[124815, 29155]],
[[124419, 28746]],
[[124095, 28635]],
[[124005, 28609]],
[[125000, 30713]],
[[125111, 30698]],
[[125078, 30682]],
[[125150, 30684]],
[[124014, 28103]],
[[125008, 31331]],
[[125411, 31468]],
[[125329, 31479]],
[[125626, 30916]],
[[125417, 30956]],
[[125254, 30976]],
[[125199, 30997]],
[[125095, 31058]],
[[125083, 30915]],
[[124885, 31015]],
[[125218, 30798]],
[[124867, 30838]],
[[124755, 30788]],
[[124802, 30809]],
[[125267, 30657]],
[[125218, 30578]],
[[125200, 30562]],
[[124968, 30474]],
[[125167, 30396]],
[[124955, 29879]],
[[124714, 29781]],
[[124762, 29462]],
[[124325, 28754]],
[[123990, 28459]],
[[125366, 31477]],
[[125115, 30363]],
[[125369, 31139]],
[[122495, 31878]],
[[125329, 30690]],
[[125192, 30787]]
]
}
},
{
"type": "Feature",
"id": "340000",
"properties": { "id": "340000", "cp": [117.283042, 31.26119], "name": "安徽", "childNum": 3 },
"geometry": {
"type": "MultiPolygon",
"coordinates": [
["@@^iuLX^"],
["@@‚e©Ehl"],
[
"@@°ZÆëϵmkǀwÌÕæhºgBĝâqÙĊz›ÖgņtÀÁÊÆá’hEz|WzqD¹€Ÿ°E‡ŧl{ævÜcA`¤C`|´qžxIJkq^³³ŸGšµbƒíZ…¹qpa±ď OH—¦™Ħˆx¢„gPícOl_iCveaOjCh߸i݋bÛªCC¿€m„RV§¢A|t^iĠGÀtÚs–d]ĮÐDE¶zAb àiödK¡~H¸íæAžǿYƒ“j{ď¿‘™À½W—®£ChŒÃsiŒkkly]_teu[bFa‰Tig‡n{]Gqªo‹ĈMYá|·¥f¥—őaSÕė™NµñĞ«ImŒ_m¿Âa]uĜp …Z_§{Cƒäg¤°r[_Yj‰ÆOdý“[ŽI[á·¥“Q_n‡ùgL¾mv™ˊBÜÆ¶ĊJhšp“c¹˜O]iŠ]œ¥ jtsggJǧw×jÉ©±›EFˍ­‰Ki”ÛÃÕYv…s•ˆm¬njĻª•§emná}k«ŕˆƒgđ²Ù›DǤ›í¡ªOy›†×Où±@DŸñSęćăÕIÕ¿IµĥO‰‰jNÕËT¡¿tNæŇàåyķrĕq§ÄĩsWÆßŽF¶žX®¿‰mŒ™w…RIޓfßoG‘³¾©uyH‘į{Ɓħ¯AFnuP…ÍÔzšŒV—dàôº^Ðæd´€‡oG¤{S‰¬ćxã}›ŧ×Kǥĩ«žÕOEзÖdÖsƘѨ[’Û^Xr¢¼˜§xvěƵ`K”§ tÒ´Cvlo¸fzŨð¾NY´ı~ÉĔē…ßúLÃϖ_ÈÏ|]ÂÏFl”g`bšežž€n¾¢pU‚h~ƴ˶_‚r sĄ~cž”ƈ]|r c~`¼{À{ȒiJjz`îÀT¥Û³…]’u}›f…ïQl{skl“oNdŸjŸäËzDvčoQŠďHI¦rb“tHĔ~BmlRš—V_„ħTLnñH±’DžœL‘¼L˜ªl§Ťa¸ŒĚlK²€\\RòvDcÎJbt[¤€D@®hh~kt°ǾzÖ@¾ªdb„YhüóZ ň¶vHrľ\\ʗJuxAT|dmÀO„‹[ÃԋG·ĚąĐlŪÚpSJ¨ĸˆLvÞcPæķŨŽ®mАˆálŸwKhïgA¢ųƩޖ¤OȜm’°ŒK´"
]
],
"encodeOffsets": [[[121722, 32278]], [[119475, 30423]], [[119168, 35472]]]
}
},
{
"type": "Feature",
"id": "350000",
"properties": {
"id": "350000",
"cp": [118.306239, 26.075302],
"name": "福建",
"childNum": 18
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
["@@“zht´‡]"],
["@@aj^~ĆG—©O"],
["@@ed¨„C}}i"],
["@@@vˆPGsQ"],
["@@‰sBz‚ddW]Q"],
["@@SލQ“{"],
["@@NŽVucW"],
["@@qptBAq"],
["@@‰’¸[mu"],
["@@Q\\pD]_"],
["@@jSwUadpF"],
["@@eXª~ƒ•"],
["@@AjvFso"],
["@@fT–›_Çí\\Ÿ™—v|ba¦jZÆy€°"],
["@@IjJi"],
["@@wJI€ˆxš«¼AoNe{M­"],
["@@K‰±¡Óˆ”ČäeZ"],
[
"@@k¡¹Eh~c®wBk‹UplÀ¡I•~Māe£bN¨gZý¡a±Öcp©PhžI”Ÿ¢Qq…ÇGj‹|¥U™ g[Ky¬ŏ–v@OpˆtÉEŸF„\\@ åA¬ˆV{Xģ‰ĐBy…cpě…¼³Ăp·¤ƒ¥o“hqqÚ¡ŅLsƒ^ᗞ§qlŸÀhH¨MCe»åÇGD¥zPO£čÙkJA¼ß–ėu›ĕeûҍiÁŧSW¥˜QŠûŗ½ùěcݧSùĩąSWó«íęACµ›eR—åǃRCÒÇZÍ¢‹ź±^dlsŒtjD¸•‚ZpužÔâÒH¾oLUêÃÔjjēò´ĄW‚ƛ…^Ñ¥‹ĦŸ@Çò–ŠmŒƒOw¡õyJ†yD}¢ďÑÈġfŠZd–a©º²z£šN–ƒjD°Ötj¶¬ZSÎ~¾c°¶Ðm˜x‚O¸¢Pl´žSL|¥žA†ȪĖM’ņIJg®áIJČĒü` ŽQF‡¬h|ÓJ@zµ |ê³È ¸UÖŬŬÀEttĸr‚]€˜ðŽM¤ĶIJHtÏ A’†žĬkvsq‡^aÎbvŒd–™fÊòSD€´Z^’xPsÞrv‹ƞŀ˜jJd×ŘÉ ®A–ΦĤd€xĆqAŒ†ZR”ÀMźŒnĊ»ŒİÐZ— YX–æJŠyĊ²ˆ·¶q§·–K@·{s‘Xãô«lŗ¶»o½E¡­«¢±¨Yˆ®Ø‹¶^A™vWĶGĒĢžPlzfˆļŽtàAvWYãšO_‡¤sD§ssČġ[kƤPX¦Ž`¶“ž®ˆBBvĪjv©šjx[L¥àï[F…¼ÍË»ğV`«•Ip™}ccÅĥZE‹ãoP…´B@ŠD—¸m±“z«Ƴ—¿å³BRضˆœWlâþäą`“]Z£Tc— ĹGµ¶H™m@_©—kŒ‰¾xĨ‡ôȉðX«½đCIbćqK³Á‹Äš¬OAwã»aLʼn‡ËĥW[“ÂGI—ÂNxij¤D¢ŽîĎÎB§°_JœGsƒ¥E@…¤uć…P‘å†cuMuw¢BI¿‡]zG¹guĮck\\_"
]
],
"encodeOffsets": [
[[123250, 27563]],
[[122541, 27268]],
[[123020, 27189]],
[[122916, 27125]],
[[122887, 26845]],
[[122808, 26762]],
[[122568, 25912]],
[[122778, 26197]],
[[122515, 26757]],
[[122816, 26587]],
[[123388, 27005]],
[[122450, 26243]],
[[122578, 25962]],
[[121255, 25103]],
[[120987, 24903]],
[[122339, 25802]],
[[121042, 25093]],
[[122439, 26024]]
]
}
},
{
"type": "Feature",
"id": "360000",
"properties": {
"id": "360000",
"cp": [115.592151, 27.676493],
"name": "江西",
"childNum": 1
},
"geometry": {
"type": "Polygon",
"coordinates": [
"@@ĢĨƐgÂMD~ņªe^\\^§„ý©j׍cZ†Ø¨zdÒa¶ˆlҍJŒìõ`oz÷@¤u޸´†ôęöY¼‰HČƶajlÞƩ¥éZ[”|h}^U Œ ¥p„ĄžƦO lt¸Æ €Q\\€ŠaÆ|CnÂOjt­ĚĤd’ÈŒF`’¶„@Ð딠¦ōҞ¨Sêv†HĢûXD®…QgėWiØPÞìºr¤dž€NĠ¢l–•ĄtZoœCƞÔºCxrpĠV®Ê{f_Y`_ƒeq’’®Aot`@o‚DXfkp¨|Šs¬\\D‘ÄSfè©Hn¬…^DhÆyøJh“ØxĢĀLʈ„ƠPżċĄwȠ̦G®ǒĤäTŠÆ~ĦwŠ«|TF¡Šn€c³Ïå¹]ĉđxe{ÎӐ†vOEm°BƂĨİ|G’vz½ª´€H’àp”eJ݆Qšxn‹ÀŠW­žEµàXÅĪt¨ÃĖrÄwÀFÎ|ňÓMå¼ibµ¯»åDT±m[“r«_gŽmQu~¥V\\OkxtL E¢‹ƒ‘Ú^~ýê‹Pó–qo슱_Êw§ÑªåƗ⼋mĉŹ‹¿NQ“…YB‹ąrwģcÍ¥B•Ÿ­ŗÊcØiI—žƝĿuŒqtāwO]‘³YCñTeɕš‹caub͈]trlu€ī…B‘ПGsĵıN£ï—^ķqss¿FūūV՟·´Ç{éĈý‰ÿ›OEˆR_ŸđûIċâJh­ŅıN‘ȩĕB…¦K{Tk³¡OP·wn—µÏd¯}½TÍ«YiµÕsC¯„iM•¤™­•¦¯P|ÿUHv“he¥oFTu‰õ\\ŽOSs‹MòđƇiaºćXŸĊĵà·çhƃ÷ǜ{‘ígu^›đg’m[×zkKN‘¶Õ»lčÓ{XSƉv©_ÈëJbVk„ĔVÀ¤P¾ºÈMÖxlò~ªÚàGĂ¢B„±’ÌŒK˜y’áV‡¼Ã~­…`g›ŸsÙfI›Ƌlę¹e|–~udjˆuTlXµf`¿JdŠ[\\˜„L‚‘²"
],
"encodeOffsets": [[116689, 26234]]
}
},
{
"type": "Feature",
"id": "370000",
"properties": {
"id": "370000",
"cp": [118.000923, 36.275807],
"name": "山东",
"childNum": 13
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
["@@Xjd]{K"],
["@@itbFHy"],
["@@HlGk"],
["@@T‚ŒGŸy"],
["@@K¬˜•‹U"],
["@@WdXc"],
["@@PtOs"],
["@@•LnXhc"],
["@@ppVƒu]Or"],
["@@cdzAUa"],
["@@udRhnCI‡"],
["@@ˆoIƒpR„"],
[
"@@Ľč{fzƤî’Kš–ÎMĮ]†—ZFˆ½Y]â£ph’™š¶¨râøÀ†ÎǨ¤^ºÄ”Gzˆ~grĚĜlĞÆ„LĆdž¢Îo¦–cv“Kb€gr°Wh”mZp ˆL]LºcU‰Æ­n”żĤÌǜbAnrOAœ´žȊcÀbƦUØrĆUÜøœĬƞ†š˜Ez„VL®öØBkŖÝĐ˹ŧ̄±ÀbÎɜnb²ĦhņBĖ›žįĦåXćì@L¯´ywƕCéõė ƿ¸‘lµ¾Z|†ZWyFYŸ¨Mf~C¿`€à_RÇzwƌfQnny´INoƬˆèôº|sT„JUš›‚L„îVj„ǎ¾Ē؍‚Dz²XPn±ŴPè¸ŔLƔÜƺ_T‘üÃĤBBċȉöA´fa„˜M¨{«M`‡¶d¡ô‰Ö°šmȰBÔjjŒ´PM|”c^d¤u•ƒ¤Û´Œä«ƢfPk¶Môlˆ]Lb„}su^ke{lC‘…M•rDŠÇ­]NÑFsmoõľH‰yGă{{çrnÓE‰‹ƕZGª¹Fj¢ïW…uøCǷ돡ąuhÛ¡^Kx•C`C\\bÅxì²ĝÝ¿_N‰īCȽĿåB¥¢·IŖÕy\\‡¹kx‡Ã£Č×GDyÕ¤ÁçFQ¡„KtŵƋ]CgÏAùSed‡cÚź—ŠuYfƒyMmhUWpSyGwMPqŀ—›Á¼zK›¶†G•­Y§Ëƒ@–´śÇµƕBmœ@Io‚g——Z¯u‹TMx}C‘‰VK‚ï{éƵP—™_K«™pÛÙqċtkkù]gŽ‹Tğwo•ɁsMõ³ă‡AN£™MRkmEʕč™ÛbMjÝGu…IZ™—GPģ‡ãħE[iµBEuŸDPԛ~ª¼ętŠœ]ŒûG§€¡QMsğNPŏįzs£Ug{đJĿļā³]ç«Qr~¥CƎÑ^n¶ÆéÎR~ݏY’I“] P‰umŝrƿ›‰›Iā‹[x‰edz‹L‘¯v¯s¬ÁY…~}…ťuٌg›ƋpÝĄ_ņī¶ÏSR´ÁP~ž¿Cyžċßdwk´Ss•X|t‰`Ä Èð€AªìÎT°¦Dd–€a^lĎDĶÚY°Ž`ĪŴǒˆ”àŠv\\ebŒZH„ŖR¬ŢƱùęO•ÑM­³FۃWp[ƒ"
]
],
"encodeOffsets": [
[[123806, 39303]],
[[123821, 39266]],
[[123742, 39256]],
[[123702, 39203]],
[[123649, 39066]],
[[123847, 38933]],
[[123580, 38839]],
[[123894, 37288]],
[[123043, 36624]],
[[123344, 38676]],
[[123522, 38857]],
[[123628, 38858]],
[[118260, 36742]]
]
}
},
{
"type": "Feature",
"id": "410000",
"properties": {
"id": "410000",
"cp": [113.665412, 33.757975],
"name": "河南",
"childNum": 1
},
"geometry": {
"type": "Polygon",
"coordinates": [
"@@•ýL™ùµP³swIÓxcŢĞð†´E®žÚPt†ĴXØx¶˜@«ŕŕQGƒ‹Yfa[şu“ßǩ™đš_X³ijÕčC]kbc•¥CS¯ëÍB©÷‹–³­Siˆ_}m˜YTtž³xlàcȂzÀD}ÂOQ³ÐTĨ¯†ƗòËŖ[hœł‹Ŧv~††}ÂZž«¤lPǕ£ªÝŴÅR§ØnhcŒtâk‡nύ­ľŹUÓÝdKuķ‡I§oTũÙďkęĆH¸ÓŒ\\ăŒ¿PcnS{wBIvɘĽ[GqµuŸŇôYgûƒZcaŽ©@½Õǽys¯}lgg@­C\\£as€IdÍuCQñ[L±ęk·‹ţb¨©kK—’»›KC²‘òGKmĨS`ƒ˜UQ™nk}AGē”sqaJ¥ĐGR‰ĎpCuÌy ã iMc”plk|tRk†ðœev~^‘´†¦ÜŽSí¿_iyjI|ȑ|¿_»d}qŸ^{“Ƈdă}Ÿtqµ`Ƴĕg}V¡om½fa™Ço³TTj¥„tĠ—Ry”K{ùÓjuµ{t}uËR‘iŸvGŠçJFjµŠÍyqΘàQÂFewixGw½Yŷpµú³XU›½ġy™łå‰kÚwZXˆ·l„¢Á¢K”zO„Λ΀jc¼htoDHr…|­J“½}JZ_¯iPq{tę½ĕ¦Zpĵø«kQ…Ťƒ]MÛfaQpě±ǽ¾]u­Fu‹÷nƒ™čįADp}AjmcEǒaª³o³ÆÍSƇĈÙDIzˑ赟^ˆKLœ—i—Þñ€[œƒaA²zz‰Ì÷Dœ|[šíijgf‚ÕÞd®|`ƒĆ~„oĠƑô³Ŋ‘D×°¯CsŠøÀ«ì‰UMhTº¨¸ǡîS–Ô„DruÂÇZ•ÖEŽ’vPZ„žW”~؋ÐtĄE¢¦Ðy¸bŠô´oŬ¬Ž²Ês~€€]®tªašpŎJ¨Öº„_ŠŔ–`’Ŗ^Ѝ\\Ĝu–”~m²Ƹ›¸fW‰ĦrƔ}Î^gjdfÔ¡J}\\n C˜¦þWxªJRÔŠu¬ĨĨmF†dM{\\d\\ŠYÊ¢ú@@¦ª²SŠÜsC–}fNècbpRmlØ^g„d¢aÒ¢CZˆZxvÆ¶N¿’¢T@€uCœ¬^ĊðÄn|žlGl’™Rjsp¢ED}€Fio~ÔNŽ‹„~zkĘHVsDzßjƒŬŒŠŢ`Pûàl¢˜\\ÀœEhŽİgÞē X¼Pk–„|m"
],
"encodeOffsets": [[118256, 37017]]
}
},
{
"type": "Feature",
"id": "420000",
"properties": {
"id": "420000",
"cp": [113.298572, 30.684355],
"name": "湖北",
"childNum": 3
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
["@@AB‚"],
["@@lskt"],
[
"@@¾«}{ra®pîÃ\\™›{øCŠËyyB±„b\\›ò˜Ý˜jK›‡L ]ĎĽÌ’JyÚCƈćÎT´Å´pb©È‘dFin~BCo°BĎĚømvŒ®E^vǾ½Ĝ²Ro‚bÜeNŽ„^ĺ£R†¬lĶ÷YoĖ¥Ě¾|sOr°jY`~I”¾®I†{GqpCgyl{‡£œÍƒÍyPL“¡ƒ¡¸kW‡xYlÙæŠšŁĢzœ¾žV´W¶ùŸo¾ZHxjwfx„GNÁ•³Xéæl¶‰EièIH‰ u’jÌQ~v|sv¶Ôi|ú¢Fh˜Qsğ¦ƒSiŠBg™ÐE^ÁÐ{–čnOÂȞUÎóĔ†ÊēIJ}Z³½Mŧïeyp·uk³DsѨŸL“¶_œÅuèw»—€¡WqÜ]\\‘Ò§tƗcÕ¸ÕFÏǝĉăxŻČƟO‡ƒKÉġÿ×wg”÷IÅzCg†]m«ªGeçÃTC’«[‰t§{loWeC@ps_Bp‘­r‘„f_``Z|ei¡—oċMqow€¹DƝӛDYpûs•–‹Ykıǃ}s¥ç³[§ŸcYЧHK„«Qy‰]¢“wwö€¸ïx¼ņ¾Xv®ÇÀµRĠЋžHMž±cÏd„ƒǍũȅȷ±DSyúĝ£ŤĀàtÖÿï[îb\\}pĭÉI±Ñy…¿³x¯N‰o‰|¹H™ÏÛm‹júË~Tš•u˜ęjCöAwě¬R’đl¯ Ñb­‰ŇT†Ŀ_[Œ‘IčĄʿnM¦ğ\\É[T·™k¹œ©oĕ@A¾w•ya¥Y\\¥Âaz¯ãÁ¡k¥ne£Ûw†E©Êō¶˓uoj_Uƒ¡cF¹­[Wv“P©w—huÕyBF“ƒ`R‹qJUw\\i¡{jŸŸEPïÿ½fć…QÑÀQ{ž‚°‡fLԁ~wXg—ītêݾ–ĺ‘Hdˆ³fJd]‹HJ²…E€ƒoU¥†HhwQsƐ»Xmg±çve›]Dm͂PˆoCc¾‹_h”–høYrŊU¶eD°Č_N~øĹĚ·`z’]Äþp¼…äÌQŒv\\rCŒé¾TnkžŐڀÜa‡“¼ÝƆ̶Ûo…d…ĔňТJq’Pb ¾|JŒ¾fXŠƐîĨ_Z¯À}úƲ‹N_ĒĊ^„‘ĈaŐyp»CÇĕKŠšñL³ŠġMŒ²wrIÒŭxjb[œžn«øœ˜—æˆàƒ ^²­h¯Ú€ŐªÞ¸€Y²ĒVø}Ā^İ™´‚LŠÚm„¥ÀJÞ{JVŒųÞŃx×sxxƈē ģMř–ÚðòIf–Ċ“Œ\\Ʈ±ŒdʧĘD†vČ_Àæ~DŒċ´A®µ†¨ØLV¦êHÒ¤"
]
],
"encodeOffsets": [[[113712, 34000]], [[115612, 30507]], [[113649, 34054]]]
}
},
{
"type": "Feature",
"id": "430000",
"properties": { "id": "430000", "cp": [111.782279, 28.09409], "name": "湖南", "childNum": 3 },
"geometry": {
"type": "MultiPolygon",
"coordinates": [
["@@—n„FTs"],
["@@ßÅÆá‰½ÔXr—†CO™“…ËR‘ïÿĩ­TooQyšÓ[‹ŅBE¬–ÎÓXa„į§Ã¸G °ITxp‰úxÚij¥Ïš–̾ŠedžÄ©ĸG…œàGh‚€M¤–Â_U}Ċ}¢pczfŠþg¤€”ÇòAV‘‹M"],
[
"@@©K—ƒA·³CQ±Á«³BUŠƑ¹AŠtćOw™D]ŒJiØSm¯b£‘ylƒ›X…HËѱH•«–‘C^õľA–Å§¤É¥„ïyuǙuA¢^{ÌC´­¦ŷJ£^[†“ª¿‡ĕ~•Ƈ…•N… skóā‡¹¿€ï]ă~÷O§­@—Vm¡‹Qđ¦¢Ĥ{ºjԏŽŒª¥nf´•~ÕoŸž×Ûą‹MąıuZœmZcÒ IJβSÊDŽŶ¨ƚƒ’CÖŎªQؼrŭŽ­«}NÏürʬŒmjr€@ĘrTW ­SsdHzƓ^ÇÂyUi¯DÅYlŹu{hTœ}mĉ–¹¥ě‰Dÿë©ıÓ[Oº£ž“¥ót€ł¹MՄžƪƒ`Pš…Di–ÛUоÅ‌ìˆU’ñB“È£ýhe‰dy¡oċ€`pfmjP~‚kZa…ZsÐd°wj§ƒ@€Ĵ®w~^‚kÀÅKvNmX\\¨a“”сqvíó¿F„¤¡@ũÑVw}S@j}¾«pĂr–ªg àÀ²NJ¶¶Dô…K‚|^ª†Ž°LX¾ŴäPᜣEXd›”^¶›IJÞܓ~‘u¸ǔ˜Ž›MRhsR…e†`ÄofIÔ\\Ø  i”ćymnú¨cj ¢»–GČìƊÿШXeĈ¾Oð Fi ¢|[jVxrIQŒ„_E”zAN¦zLU`œcªx”OTu RLÄ¢dV„i`p˔vŎµªÉžF~ƒØ€d¢ºgİàw¸Áb[¦Zb¦–z½xBĖ@ªpº›šlS¸Ö\\Ĕ[N¥ˀmĎă’J\\‹ŀ`€…ňSڊĖÁĐiO“Ĝ«BxDõĚiv—ž–S™Ì}iùŒžÜnšÐºGŠ{Šp°M´w†ÀÒzJ²ò¨ oTçüöoÛÿñŽőФ‚ùTz²CȆȸǎۃƑÐc°dPÎŸğ˶[Ƚu¯½WM¡­Éž“’B·rížnZŸÒ `‡¨GA¾\\pē˜XhÆRC­üWGġu…T靧Ŏѝ©ò³I±³}_‘‹EÃħg®ęisÁPDmÅ{‰b[Rşs·€kPŸŽƥƒóRo”O‹ŸVŸ~]{g\\“êYƪ¦kÝbiċƵŠGZ»Ěõ…ó·³vŝž£ø@pyö_‹ëŽIkѵ‡bcѧy…×dY؎ªiþž¨ƒ[]f]Ņ©C}ÁN‡»hĻħƏ’ĩ"
]
],
"encodeOffsets": [[[115640, 30489]], [[112543, 27312]], [[116690, 26230]]]
}
},
{
"type": "Feature",
"id": "440000",
"properties": {
"id": "440000",
"cp": [113.280637, 23.125178],
"name": "广东",
"childNum": 24
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
["@@QdˆAua"],
["@@ƒlxDLo"],
["@@sbhNLo"],
["@@Ă āŸ"],
["@@WltO[["],
["@@Krœ]S"],
["@@e„„I]y"],
["@@I|„Mym"],
["@@ƒÛ³LSŒž¼Y"],
["@@nvºB–ëui©`¾"],
["@@zdšÛ›Jw®"],
["@@†°…¯"],
["@@a yAª¸ËJIx،@€ĀHAmßV¡o•fu•o"],
["@@šs‰ŗÃÔėAƁ›ZšÄ ~°ČP‚‹äh"],
["@@‹¶Ý’Ì‚vmĞh­ı‡Q"],
["@@HœŠdSjĒ¢D}war…“u«ZqadYM"],
["@@elŒ\\LqqU"],
["@@~rMo\\"],
["@@f„^ƒC"],
["@@øPªoj÷ÍÝħXČx”°Q¨ıXNv"],
["@@gÇƳˆŽˆ”oˆŠˆ[~tly"],
["@@E–ÆC¿‘"],
["@@OŽP"],
[
"@@w‹†đóg‰™ĝ—[³‹¡VÙæÅöM̳¹pÁaËýý©D©Ü“JŹƕģGą¤{Ùū…ǘO²«BƱéA—Ò‰ĥ‡¡«BhlmtÃPµyU¯uc“d·w_bŝcīímGOŽ|KP’ȏ‡ŹãŝIŕŭŕ@Óoo¿ē‹±ß}Ž…ŭ‚ŸIJWÈCőâUâǙI›ğʼn©I›ijEׅÁ”³Aó›wXJþ±ÌŒÜӔĨ£L]ĈÙƺZǾĆĖMĸĤfŒÎĵl•ŨnȈ‘ĐtF”Š–FĤ–‚êk¶œ^k°f¶gŠŽœ}®Fa˜f`vXŲxl˜„¦–ÔÁ²¬ÐŸ¦pqÊ̲ˆi€XŸØRDÎ}†Ä@ZĠ’s„x®AR~®ETtĄZ†–ƈfŠŠHâÒÐA†µ\\S¸„^wĖkRzŠalŽŜ|E¨ÈNĀňZTŒ’pBh£\\ŒĎƀuXĖtKL–¶G|Ž»ĺEļĞ~ÜĢÛĊrˆO˜Ùîvd]nˆ¬VœÊĜ°R֟pM††–‚ƂªFbwžEÀˆ˜©Œž\\…¤]ŸI®¥D³|ˎ]CöAŤ¦…æ’´¥¸Lv¼€•¢ĽBaô–F~—š®²GÌҐEY„„œzk¤’°ahlV՞I^‹šCxĈPŽsB‰ƒºV‰¸@¾ªR²ĨN]´_eavSi‡vc•}p}Đ¼ƌkJœÚe thœ†_¸ ºx±ò_xN›Ë‹²‘@ƒă¡ßH©Ùñ}wkNÕ¹ÇO½¿£ĕ]ly_WìIžÇª`ŠuTÅxYĒÖ¼k֞’µ‚MžjJÚwn\\h‘œĒv]îh|’È›Ƅøègž¸Ķß ĉĈWb¹ƀdéƌNTtP[ŠöSvrCZžžaGuœbo´ŖÒÇА~¡zCI…özx¢„Pn‹•‰Èñ @ŒĥÒ¦†]ƞŠV}³ăĔñiiÄÓVépKG½Ä‘ÓávYo–C·sit‹iaÀy„ŧΡÈYDÑům}‰ý|m[węõĉZÅxUO}÷N¹³ĉo_qtă“qwµŁYلǝŕ¹tïÛUïmRCº…ˆĭ|µ›ÕÊK™½R‘ē ó]‘–GªęAx–»HO£|ām‡¡diď×YïYWªʼnOeÚtĐ«zđ¹T…ā‡úE™á²\\‹ķÍ}jYàÙÆſ¿Çdğ·ùTßÇţʄ¡XgWÀLJğ·¿ÃˆOj YÇ÷Qě‹i"
]
],
"encodeOffsets": [
[[117381, 22988]],
[[116552, 22934]],
[[116790, 22617]],
[[116973, 22545]],
[[116444, 22536]],
[[116931, 22515]],
[[116496, 22490]],
[[116453, 22449]],
[[113301, 21439]],
[[118726, 21604]],
[[118709, 21486]],
[[113210, 20816]],
[[115482, 22082]],
[[113171, 21585]],
[[113199, 21590]],
[[115232, 22102]],
[[115739, 22373]],
[[115134, 22184]],
[[113056, 21175]],
[[119573, 21271]],
[[119957, 24020]],
[[115859, 22356]],
[[116561, 22649]],
[[116285, 22746]]
]
}
},
{
"type": "Feature",
"id": "450000",
"properties": { "id": "450000", "cp": [108.320004, 22.82402], "name": "广西", "childNum": 2 },
"geometry": {
"type": "MultiPolygon",
"coordinates": [
["@@H– TQ§•A"],
[
"@@ĨʪƒLƒƊDÎĹĐCǦė¸zÚGn£¾›rªŀÜt¬@֛ڈSx~øOŒ˜ŶÐÂæȠ\\„ÈÜObĖw^oބLf¬°bI lTØB̈F£Ć¹gñĤaY“t¿¤VSñœK¸¤nM†¼‚JE±„½¸šŠño‹ÜCƆæĪ^ŠĚQÖ¦^‡ˆˆf´Q†üÜʝz¯šlzUĺš@쇀p¶n]sxtx¶@„~ÒĂJb©gk‚{°‚~c°`ԙ¬rV\\“la¼¤ôá`¯¹LC†ÆbŒxEræO‚v[H­˜„[~|aB£ÖsºdAĐzNÂðsŽÞƔ…Ĥªbƒ–ab`ho¡³F«èVloޤ™ÔRzpp®SŽĪº¨ÖƒºN…ij„d`’a”¦¤F³ºDÎńĀìŠCžĜº¦Ċ•~nS›|gźvZkCÆj°zVÈÁƔ]LÊFZg…čP­kini«‹qǀcz͔Y®¬Ů»qR×ō©DՄ‘§ƙǃŵTÉĩ±ŸıdÑnYY›IJvNĆÌØÜ Öp–}e³¦m‹©iÓ|¹Ÿħņ›|ª¦QF¢Â¬ʖovg¿em‡^ucà÷gՎuŒíÙćĝ}FϼĹ{µHK•sLSđƃr‹č¤[Ag‘oS‹ŇYMÿ§Ç{Fśbky‰lQxĕƒ]T·¶[B…ÑÏGáşşƇe€…•ăYSs­FQ}­Bƒw‘tYğÃ@~…C̀Q ×W‡j˱rÉ¥oÏ ±«ÓÂ¥•ƒ€k—ŽwWűŒmcih³K›~‰µh¯e]lµ›él•E쉕E“ďs‡’mǖŧē`ãògK_ÛsUʝ“ćğ¶hŒöŒO¤Ǜn³Žc‘`¡y‹¦C‘ez€YŠwa™–‘[ďĵűMę§]X˜Î_‚훘Û]é’ÛUćİÕBƣ±…dƒy¹T^džûÅÑŦ·‡PĻþÙ`K€¦˜…¢ÍeœĥR¿Œ³£[~Œäu¼dl‰t‚†W¸oRM¢ď\\zœ}Æzdvň–{ÎXF¶°Â_„ÒÂÏL©Ö•TmuŸ¼ãl‰›īkiqéfA„·Êµ\\őDc¥ÝF“y›Ôć˜c€űH_hL܋êĺШc}rn`½„Ì@¸¶ªVLŒŠhŒ‹\\•Ţĺk~ŽĠið°|gŒtTĭĸ^x‘vK˜VGréAé‘bUu›MJ‰VÃO¡…qĂXËS‰ģãlýàŸ_ju‡YÛÒB†œG^˜é֊¶§ŽƒEG”ÅzěƒƯ¤Ek‡N[kdåucé¬dnYpAyČ{`]þ¯T’bÜÈk‚¡Ġ•vŒàh„ÂƄ¢Jî¶²"
]
],
"encodeOffsets": [[[111707, 21520]], [[107619, 25527]]]
}
},
{
"type": "Feature",
"id": "460000",
"properties": { "id": "460000", "cp": [109.83119, 19.031971], "name": "海南", "childNum": 1 },
"geometry": {
"type": "Polygon",
"coordinates": [
"@@š¦Ŝil¢”XƦ‘ƞò–ïè§ŞCêɕrŧůÇąĻõ™·ĉ³œ̅kÇm@ċȧƒŧĥ‰Ľʉ­ƅſ“ȓÒ˦ŝE}ºƑ[ÍĜȋ gÎfǐÏĤ¨êƺ\\Ɔ¸ĠĎvʄȀœÐ¾jNðĀÒRŒšZdž™zÐŘΰH¨Ƣb²_Ġ "
],
"encodeOffsets": [[112750, 20508]]
}
},
{
"type": "Feature",
"id": "510000",
"properties": {
"id": "510000",
"cp": [104.065735, 30.659462],
"name": "四川",
"childNum": 2
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
["@@LqKr"],
[
"@@Š[ĻéV£ž_ţġñpG •réÏ·~ąSfy×͂·ºſƽiÍıƣıĻmHH}siaX@iǰÁÃ×t«ƒ­Tƒ¤J–JJŒyJ•ÈŠ`Ohߦ¡uËhIyCjmÿw…ZG……Ti‹SˆsO‰žB²ŸfNmsPaˆ{M{ŠõE‘^Hj}gYpaeuž¯‘oáwHjÁ½M¡pM“–uå‡mni{fk”\\oƒÎqCw†EZ¼K›ĝŠƒAy{m÷L‡wO×SimRI¯rK™õBS«sFe‡]fµ¢óY_ÆPRcue°Cbo׌bd£ŌIHgtrnyPt¦foaXďx›lBowz‹_{ÊéWiêE„GhܸºuFĈIxf®Ž•Y½ĀǙ]¤EyŸF²ċ’w¸¿@g¢§RGv»–áŸW`ÃĵJwi]t¥wO­½a[׈]`Ãi­üL€¦LabbTÀå’c}Íh™Æhˆ‹®BH€î|Ék­¤S†y£„ia©taį·Ɖ`ō¥Uh“O…ƒĝLk}©Fos‰´›Jm„µlŁu—…ø–nÑJWΪ–YÀïAetTžŅ‚ӍG™Ë«bo‰{ıwodƟ½ƒžOġܑµxàNÖ¾P²§HKv¾–]|•B‡ÆåoZ`¡Ø`ÀmºĠ~ÌЧnDž¿¤]wğ@sƒ‰rğu‰~‘Io”[é±¹ ¿žſđӉ@q‹gˆ¹zƱřaí°KtǤV»Ã[ĩǭƑ^ÇÓ@ỗs›Zϕ‹œÅĭ€Ƌ•ěpwDóÖሯneQˌq·•GCœýS]xŸ·ý‹q³•O՜Œ¶Qzßti{ř‰áÍÇWŝŭñzÇW‹pç¿JŒ™‚Xœĩè½cŒF–ÂLiVjx}\\N†ŇĖ¥Ge–“JA¼ÄHfÈu~¸Æ«dE³ÉMA|b˜Ò…˜ćhG¬CM‚õŠ„ƤąAvƒüV€éŀ‰_V̳ĐwQj´·ZeÈÁ¨X´Æ¡Qu·»Ÿ“˜ÕZ³ġqDo‰y`L¬gdp°şŠp¦ėìÅĮZްIä”h‚‘ˆzŠĵœf²å ›ĚрKp‹IN|‹„Ñz]ń……·FU×é»R³™MƒÉ»GM«€ki€™ér™}Ã`¹ăÞmȝnÁîRǀ³ĜoİzŔwǶVÚ£À]ɜ»ĆlƂ²Ġ…þTº·àUȞÏʦ¶†I’«dĽĢdĬ¿–»Ĕ׊h\\c¬†ä²GêëĤł¥ÀǿżÃÆMº}BÕĢyFVvw–ˆxBèĻĒ©Ĉ“tCĢɽŠȣ¦āæ·HĽî“ôNԓ~^¤Ɗœu„œ^s¼{TA¼ø°¢İªDè¾Ň¶ÝJ‘®Z´ğ~Sn|ªWÚ©òzPOȸ‚bð¢|‹øĞŠŒœŒQìÛÐ@Ğ™ǎRS¤Á§d…i“´ezÝúØã]Hq„kIŸþËQǦÃsǤ[E¬ÉŪÍxXƒ·ÖƁİlƞ¹ª¹|XÊwn‘ÆƄmÀêErĒtD®ċæcQƒ”E®³^ĭ¥©l}äQto˜ŖÜqƎkµ–„ªÔĻĴ¡@Ċ°B²Èw^^RsºT£ڿœQP‘JvÄz„^Đ¹Æ¯fLà´GC²‘dt˜­ĀRt¼¤ĦOðğfÔðDŨŁĞƘïžPȆ®âbMüÀXZ ¸£@Ś›»»QÉ­™]d“sÖ×_͖_ÌêŮPrĔĐÕGĂeZÜîĘqBhtO ¤tE[h|Y‹Ô‚ZśÎs´xº±UŒ’ñˆt|O’ĩĠºNbgþŠJy^dÂY Į„]Řz¦gC‚³€R`Šz’¢AjŒ¸CL„¤RÆ»@­Ŏk\\Ç´£YW}z@Z}‰Ã¶“oû¶]´^N‡Ò}èN‚ª–P˜Íy¹`S°´†ATe€VamdUĐwʄvĮÕ\\ƒu‹Æŗ¨Yp¹àZÂm™Wh{á„}WØǍ•Éüw™ga§áCNęÎ[ĀÕĪgÖɪX˜øx¬½Ů¦¦[€—„NΆL€ÜUÖ´òrÙŠxR^–†J˜k„ijnDX{Uƒ~ET{ļº¦PZc”jF²Ė@Žp˜g€ˆ¨“B{ƒu¨ŦyhoÚD®¯¢˜ WòàFΤ¨GDäz¦kŮPœġq˚¥À]€Ÿ˜eŽâÚ´ªKxī„Pˆ—Ö|æ[xäJÞĥ‚s’NÖ½ž€I†¬nĨY´®Ð—ƐŠ€mD™ŝuäđđEb…e’e_™v¡}ìęNJē}q”É埁T¯µRs¡M@}ůa†a­¯wvƉåZwž\\Z{åû^›"
]
],
"encodeOffsets": [[[108815, 30935]], [[110617, 31811]]]
}
},
{
"type": "Feature",
"id": "520000",
"properties": {
"id": "520000",
"cp": [106.713478, 26.578343],
"name": "贵州",
"childNum": 3
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
["@@†G\\†lY£‘in"],
["@@q‚|ˆ‚mc¯tχVSÎ"],
[
"@@hÑ£Is‡NgßH†›HªķÃh_¹ƒ¡ĝħń¦uيùŽgS¯JHŸ|sÝÅtÁïyMDč»eÕtA¤{b\\}—ƒG®u\\åPFq‹wÅaD…žK°ºâ_£ùbµ”mÁ‹ÛœĹM[q|hlaªāI}тƒµ@swtwm^oµˆD鼊yV™ky°ÉžûÛR…³‚‡eˆ‡¥]RՋěħ[ƅåÛDpŒ”J„iV™™‰ÂF²I…»mN·£›LbÒYb—WsÀbŽ™pki™TZĄă¶HŒq`……ĥ_JŸ¯ae«ƒKpÝx]aĕÛPƒÇȟ[ÁåŵÏő—÷Pw}‡TœÙ@Õs«ĿÛq©½œm¤ÙH·yǥĘĉBµĨÕnđ]K„©„œá‹ŸG纍§Õßg‡ǗĦTèƤƺ{¶ÉHÎd¾ŚÊ·OÐjXWrãLyzÉAL¾ę¢bĶėy_qMĔąro¼hĊžw¶øV¤w”²Ĉ]ʚKx|`ź¦ÂÈdr„cȁbe¸›`I¼čTF´¼Óýȃr¹ÍJ©k_șl³´_pН`oÒh޶pa‚^ÓĔ}D»^Xyœ`d˜[Kv…JPhèhCrĂĚÂ^Êƌ wˆZL­Ġ£šÁbrzOIl’MM”ĪŐžËr×ÎeŦŽtw|Œ¢mKjSǘňĂStÎŦEtqFT†¾†E쬬ôxÌO¢Ÿ KгŀºäY†„”PVgŎ¦Ŋm޼VZwVlŒ„z¤…ž£Tl®ctĽÚó{G­A‡ŒÇgeš~Αd¿æaSba¥KKûj®_ć^\\ؾbP®¦x^sxjĶI_Ä X‚⼕Hu¨Qh¡À@Ëô}ޱžGNìĎlT¸ˆ…`V~R°tbÕĊ`¸úÛtπFDu€[ƒMfqGH·¥yA‰ztMFe|R‚_Gk†ChZeÚ°to˜v`x‹b„ŒDnÐ{E}šZ˜è€x—†NEފREn˜[Pv@{~rĆAB§‚EO¿|UZ~ì„Uf¨J²ĂÝÆ€‚sª–B`„s¶œfvö¦ŠÕ~dÔq¨¸º»uù[[§´sb¤¢zþFœ¢Æ…Àhˆ™ÂˆW\\ıŽËI݊o±ĭŠ£þˆÊs}¡R]ŒěƒD‚g´VG¢‚j±®è†ºÃmpU[Á›‘Œëº°r›ÜbNu¸}Žº¼‡`ni”ºÔXĄ¤¼Ôdaµ€Á_À…†ftQQgœR—‘·Ǔ’v”}Ýלĵ]µœ“Wc¤F²›OĩųãW½¯K‚©…]€{†LóµCIµ±Mß¿hŸ•©āq¬o‚½ž~@i~TUxŪÒ¢@ƒ£ÀEîôruń‚”“‚b[§nWuMÆLl¿]x}ij­€½"
]
],
"encodeOffsets": [[[112158, 27383]], [[112105, 27474]], [[112095, 27476]]]
}
},
{
"type": "Feature",
"id": "530000",
"properties": {
"id": "530000",
"cp": [101.512251, 24.740609],
"name": "云南",
"childNum": 1
},
"geometry": {
"type": "Polygon",
"coordinates": [
"@@[„ùx½}ÑRH‘YīĺûsÍn‘iEoã½Ya²ė{c¬ĝg•ĂsA•ØÅwď‚õzFjw}—«Dx¿}UũlŸê™@•HÅ­F‰¨ÇoJ´Ónũuą¡Ã¢pÒŌ“Ø TF²‚xa²ËX€‚cʋlHîAßËŁkŻƑŷÉ©h™W­æßU‡“Ës¡¦}•teèÆ¶StǀÇ}Fd£j‹ĈZĆÆ‹¤T‚č\\Dƒ}O÷š£Uˆ§~ŃG™‚åŃDĝ¸œTsd¶¶Bªš¤u¢ŌĎo~t¾ÍŶÒtD¦Ú„iôö‰€z›ØX²ghįh½Û±¯€ÿm·zR¦Ɵ`ªŊÃh¢rOԍ´£Ym¼èêf¯ŪĽn„†cÚbŒw\\zlvWžªâˆ ¦g–mĿBş£¢ƹřbĥkǫßeeZkÙIKueT»sVesb‘aĕ  ¶®dNœĄÄpªyސ¼—„³BE˜®l‡ŽGœŭCœǶwêżĔÂe„pÍÀQƞpC„–¼ŲÈ­AÎô¶R„ä’Q^Øu¬°š_Èôc´¹ò¨P΢hlϦ´Ħ“Æ´sâDŽŲPnÊD^¯°’Upv†}®BP̪–jǬx–Söwlfòªv€qĸ|`H€­viļ€ndĜ­Ćhň•‚em·FyށqóžSᝑ³X_ĞçêtryvL¤§z„¦c¦¥jnŞk˜ˆlD¤øz½ĜàžĂŧMÅ|áƆàÊcðÂF܎‚áŢ¥\\\\º™İøÒÐJĴ‡„îD¦zK²ǏÎEh~’CD­hMn^ÌöÄ©ČZÀžaü„fɭyœpį´ěFűk]Ôě¢qlÅĆÙa¶~Äqššê€ljN¬¼H„ÊšNQ´ê¼VظE††^ŃÒyŒƒM{ŒJLoÒœęæŸe±Ķ›y‰’‡gã“¯JYÆĭĘëo¥Š‰o¯hcK«z_pŠrC´ĢÖY”—¼ v¸¢RŽÅW³Â§fǸYi³xR´ďUˊ`êĿU„û€uĆBƒƣö‰N€DH«Ĉg†——Ñ‚aB{ÊNF´¬c·Åv}eÇÃGB»”If•¦HňĕM…~[iwjUÁKE•Ž‹¾dĪçW›šI‹èÀŒoÈXòyŞŮÈXâÎŚŠj|àsRy‹µÖ›–Pr´þŒ ¸^wþTDŔ–Hr¸‹žRÌmf‡żÕâCôox–ĜƌÆĮŒ›Ð–œY˜tâŦÔ@]ÈǮƒ\\μģUsȯLbîƲŚºyh‡rŒŠ@ĒԝƀŸÀ²º\\êp“’JŠ}ĠvŠqt„Ġ@^xÀ£È†¨mËÏğ}n¹_¿¢×Y_æpˆÅ–A^{½•Lu¨GO±Õ½ßM¶w’ÁĢۂP‚›Ƣ¼pcIJxŠ|ap̬HšÐŒŊSfsðBZ¿©“XÏÒK•k†÷Eû¿‰S…rEFsÕūk”óVǥʼniTL‚¡n{‹uxţÏh™ôŝ¬ğōN“‘NJkyPaq™Âğ¤K®‡YŸxÉƋÁ]āęDqçgOg†ILu—\\_gz—]W¼ž~CÔē]bµogpў_oď`´³Țkl`IªºÎȄqÔþž»E³ĎSJ»œ_f·‚adÇqƒÇc¥Á_Źw{™L^ɱćx“U£µ÷xgĉp»ĆqNē`rĘzaĵĚ¡K½ÊBzyäKXqiWPÏɸ½řÍcÊG|µƕƣG˛÷Ÿk°_^ý|_zċBZocmø¯hhcæ\\lˆMFlư£Ĝ„ÆyH“„F¨‰µêÕ]—›HA…àӄ^it `þßäkŠĤÎT~Wlÿ¨„ÔPzUC–NVv [jâôDôď[}ž‰z¿–msSh‹¯{jïğl}šĹ[–őŒ‰gK‹©U·µË@¾ƒm_~q¡f¹…ÅË^»‘f³ø}Q•„¡Ö˳gͱ^ǁ…\\ëÃA_—¿bW›Ï[¶ƛ鏝£F{īZgm@|kHǭƁć¦UĔťƒ×ë}ǝƒeďºȡȘÏíBə£āĘPªij¶“ʼnÿ‡y©n‰ď£G¹¡I›Š±LÉĺÑdĉ܇W¥˜‰}g˜Á†{aqÃ¥aŠıęÏZ—ï`"
],
"encodeOffsets": [[104636, 22969]]
}
},
{
"type": "Feature",
"id": "540000",
"properties": { "id": "540000", "cp": [89.132212, 30.860361], "name": "西藏", "childNum": 1 },
"geometry": {
"type": "Polygon",
"coordinates": [
"@@hžľxŽŖ‰xƒÒVކºÅâAĪÝȆµę¯Ňa±r_w~uSÕň‘qOj]ɄQ…£Z……UDûoY’»©M[‹L¼qãË{V͕çWViŽ]ë©Ä÷àyƛh›ÚU°ŒŒa”d„cQƒ~Mx¥™cc¡ÙaSyF—ցk­ŒuRýq¿Ôµ•QĽ³aG{¿FµëªéĜÿª@¬·–K‰·àariĕĀ«V»Ŷ™Ĵū˜gèLǴŇƶaf‹tŒèBŚ£^Šâ†ǐÝ®–šM¦ÁǞÿ¬LhŸŽJ¾óƾƺcxw‹f]Y…´ƒ¦|œQLn°aœdĊ…œ\\¨o’œǀÍŎœ´ĩĀd`tÊQŞŕ|‚¨C^©œĈ¦„¦ÎJĊ{ŽëĎjª²rЉšl`¼Ą[t|¦St辉PŒÜK¸€d˜Ƅı]s¤—î_v¹ÎVòŦj˜£Əsc—¬_Ğ´|٘¦Avަw`ăaÝaa­¢e¤ı²©ªSªšÈMĄwžÉØŔì@T‘¤—Ę™\\õª@”þo´­xA s”ÂtŎKzó´ÇĊµ¢rž^nĊ­Æ¬×üGž¢‚³ {âĊ]š™G‚~bÀgVjzlhǶf€žOšfdЉªB]pj„•TO–tĊ‚n¤}®¦ƒČ¥d¢¼»ddš”Y¼Žt—¢eȤJ¤}Ǿ¡°§¤AГlc@ĝ”sªćļđAç‡wx•UuzEÖġ~AN¹ÄÅȀݦ¿ģŁéì±H…ãd«g[؉¼ēÀ•cīľġ¬cJ‘µ…ÐʥVȝ¸ßS¹†ý±ğkƁ¼ą^ɛ¤Ûÿ‰b[}¬ōõÃ]ËNm®g@•Bg}ÍF±ǐyL¥íCˆƒIij€Ï÷њį[¹¦[⚍EÛïÁÉdƅß{âNÆāŨߝ¾ě÷yC£‡k­´ÓH@¹†TZ¥¢įƒ·ÌAЧ®—Zc…v½ŸZ­¹|ŕWZqgW“|ieZÅYVӁqdq•bc²R@†c‡¥Rã»Ge†ŸeƃīQ•}J[ғK…¬Ə|o’ėjġĠÑN¡ð¯EBčnwôɍėªƒ²•CλŹġǝʅįĭạ̃ūȹ]ΓͧgšsgȽóϧµǛ†ęgſ¶ҍć`ĘąŌJޚä¤rÅň¥ÖÁUětęuůÞiĊÄÀ\\Æs¦ÓRb|Â^řÌkÄŷ¶½÷‡f±iMݑ›‰@ĥ°G¬ÃM¥n£Øą‚ğ¯ß”§aëbéüÑOčœk£{\\‘eµª×M‘šÉfm«Ƒ{Å׃Gŏǩãy³©WÑăû‚··‘Q—òı}¯ã‰I•éÕÂZ¨īès¶ZÈsŽæĔTŘvŽgÌsN@îá¾ó@‰˜ÙwU±ÉT廣TđŸWxq¹Zo‘b‹s[׌¯cĩv‡Œėŧ³BM|¹k‰ªħ—¥TzNYnݍßpęrñĠĉRS~½ŠěVVе‚õ‡«ŒM££µB•ĉ¥áºae~³AuĐh`Ü³ç@BۘïĿa©|z²Ý¼D”£à貋ŸƒIƒû›I ā€óK¥}rÝ_Á´éMaň¨€~ªSĈ½Ž½KÙóĿeƃÆBŽ·¬ën×W|Uº}LJrƳ˜lŒµ`bÔ`QˆˆÐÓ@s¬ñIŒÍ@ûws¡åQÑßÁ`ŋĴ{Ī“T•ÚÅTSij‚‹Yo|Ç[ǾµMW¢ĭiÕØ¿@˜šMh…pÕ]j†éò¿OƇĆƇp€êĉâlØw–ěsˆǩ‚ĵ¸c…bU¹ř¨WavquSMzeo_^gsÏ·¥Ó@~¯¿RiīB™Š\\”qTGªÇĜçPoŠÿfñòą¦óQīÈáP•œābß{ƒZŗĸIæÅ„hnszÁCËìñšÏ·ąĚÝUm®ó­L·ăU›Èíoù´Êj°ŁŤ_uµ^‘°Œìǖ@tĶĒ¡Æ‡M³Ģ«˜İĨÅ®ğ†RŽāð“ggheÆ¢z‚Ê©Ô\\°ÝĎz~ź¤Pn–MĪÖB£Ÿk™n鄧żćŠ˜ĆK„ǰ¼L¶è‰âz¨u¦¥LDĘz¬ýÎmĘd¾ß”Fz“hg²™Fy¦ĝ¤ċņbΛ@y‚Ąæm°NĮZRÖíŽJ²öLĸÒ¨Y®ƌÐV‰à˜tt_ڀÂyĠzž]Ţh€zĎ{†ĢX”ˆc|šÐqŽšfO¢¤ög‚ÌHNŽ„PKŖœŽ˜Uú´xx[xˆvĐCûŠìÖT¬¸^}Ìsòd´_އKgžLĴ…ÀBon|H@–Êx˜—¦BpŰˆŌ¿fµƌA¾zLjRxжF”œkĄźRzŀˆ~¶[”´Hnª–VƞuĒ­È¨ƎcƽÌm¸ÁÈM¦x͊ëÀxdžB’šú^´W†£–d„kɾĬpœw‚˂ØɦļĬIŚœÊ•n›Ŕa¸™~J°î”lɌxĤÊÈðhÌ®‚g˜T´øŽàCˆŽÀ^ªerrƘdž¢İP|Ė ŸWœªĦ^¶´ÂL„aT±üWƜ˜ǀRšŶUńšĖ[QhlLüA†‹Ü\\†qR›Ą©"
],
"encodeOffsets": [[90849, 37210]]
}
},
{
"type": "Feature",
"id": "610000",
"properties": {
"id": "610000",
"cp": [108.948024, 34.263161],
"name": "陕西",
"childNum": 1
},
"geometry": {
"type": "Polygon",
"coordinates": [
"@@˜p¢—ȮµšûG™Ħ}Ħšðǚ¶òƄ€jɂz°{ºØkÈęâ¦jª‚Bg‚\\œċ°s¬Ž’]jžú ‚E”Ȍdž¬s„t‡”RˆÆdĠݎwܔ¸ôW¾ƮłÒ_{’Ìšû¼„jº¹¢GǪÒ¯ĘƒZ`ºŊƒecņąš~BÂgzpâēòYǠȰÌTΨÂWœ|fcŸă§uF—Œ@NŸ¢XLƒŠRMº[ğȣſï|¥J™kc`sʼnǷ’Y¹‹W@µ÷K…ãï³ÛIcñ·VȋڍÒķø©—þ¥ƒy‚ÓŸğęmWµÎumZyOŅƟĥÓ~sÑL¤µaŅY¦ocyZ{‰y c]{ŒTa©ƒ`U_Ěē£ωÊƍKù’K¶ȱÝƷ§{û»ÅÁȹÍéuij|¹cÑd‘ŠìUYƒŽO‘uF–ÕÈYvÁCqӃT•Ǣí§·S¹NgŠV¬ë÷Át‡°Dد’C´ʼnƒópģ}„ċcE˅FŸŸéGU¥×K…§­¶³B‹Č}C¿åċ`wġB·¤őcƭ²ő[Å^axwQO…ÿEËߌ•ĤNĔŸwƇˆÄŠńwĪ­Šo[„_KÓª³“ÙnK‰Çƒěœÿ]ď€ă_d©·©Ýŏ°Ù®g]±„Ÿ‡ß˜å›—¬÷m\\›iaǑkěX{¢|ZKlçhLt€Ňîŵ€œè[€É@ƉĄEœ‡tƇÏ˜³­ħZ«mJ…›×¾‘MtÝĦ£IwÄå\\Õ{‡˜ƒOwĬ©LÙ³ÙgBƕŀr̛ĢŭO¥lãyC§HÍ£ßEñŸX¡—­°ÙCgpťz‘ˆb`wI„vA|§”‡—hoĕ@E±“iYd¥OϹS|}F@¾oAO²{tfžÜ—¢Fǂ҈W²°BĤh^Wx{@„¬‚­F¸¡„ķn£P|ŸªĴ@^ĠĈæb–Ôc¶l˜Yi…–^Mi˜cϰÂ[ä€vï¶gv@À“Ĭ·lJ¸sn|¼u~a]’ÆÈtŌºJp’ƒþ£KKf~ЦUbyäIšĺãn‡Ô¿^­žŵMT–hĠܤko¼Ŏìąǜh`[tŒRd²IJ_œXPrɲ‰l‘‚XžiL§àƒ–¹ŽH˜°Ȧqº®QC—bA†„ŌJ¸ĕÚ³ĺ§ `d¨YjžiZvRĺ±öVKkjGȊĐePОZmļKÀ€‚[ŠŽ`ösìh†ïÎoĬdtKÞ{¬èÒÒBŒÔpIJÇĬJŊ¦±J«ˆY§‹@·pH€µàåVKe›pW†ftsAÅqC·¬ko«pHÆuK@oŸHĆۄķhx“e‘n›S³àǍrqƶRbzy€¸ËАl›¼EºpĤ¼Œx¼½~Ğ’”à@†ÚüdK^ˆmÌSj"
],
"encodeOffsets": [[110234, 38774]]
}
},
{
"type": "Feature",
"id": "620000",
"properties": {
"id": "620000",
"cp": [103.823557, 36.058039],
"name": "甘肃",
"childNum": 2
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
["@@VuUv"],
[
"@@ũ‹EĠtt~nkh`Q‰¦ÅÄÜdw˜Ab×ĠąJˆ¤DüègĺqBqœj°lI¡ĨÒ¤úSHbš‡ŠjΑBаaZˆ¢KJŽ’O[|A£žDx}Nì•HUnrk„ kp€¼Y kMJn[aG‚áÚÏ[½rc†}aQxOgsPMnUs‡nc‹Z…ž–sKúvA›t„Þġ’£®ĀYKdnFwš¢JE°”Latf`¼h¬we|€Æ‡šbj}GA€·~WŽ”—`†¢MC¤tL©IJ°qdf”O‚“bÞĬ¹ttu`^ZúE`Œ[@„Æsîz®¡’C„ƳƜG²“R‘¢R’m”fŽwĸg܃‚ą G@pzJM½mŠhVy¸uÈÔO±¨{LfæU¶ßGĂq\\ª¬‡²I‚¥IʼnÈīoı‹ÓÑAçÑ|«LÝcspīðÍg…të_õ‰\\ĉñLYnĝg’ŸRǡÁiHLlõUĹ²uQjYi§Z_c¨Ÿ´ĹĖÙ·ŋI…ƒaBD˜­R¹ȥr—¯G•ºß„K¨jWk’ɱŠOq›Wij\\a­‹Q\\sg_ĆǛōëp»£lğۀgS•ŶN®À]ˆÓäm™ĹãJaz¥V}‰Le¤L„ýo‘¹IsŋÅÇ^‘Žbz…³tmEÁ´aйcčecÇN•ĊãÁ\\蝗dNj•]j†—ZµkÓda•ćå]ğij@ ©O{¤ĸm¢ƒE·®ƒ«|@Xwg]A챝‡XǁÑdzªc›wQÚŝñsÕ³ÛV_ýƒ˜¥\\ů¥©¾÷w—Ž©WÕÊĩhÿÖÁRo¸V¬âDb¨šhûx–Ê×nj~Zâƒg|šXÁnßYoº§ZÅŘvŒ[„ĭÖʃuďxcVbnUSf…B¯³_Tzº—ΕO©çMÑ~Mˆ³]µ^püµ”ŠÄY~y@X~¤Z³€[Èōl@®Å¼£QKƒ·Di‹¡By‘ÿ‰Q_´D¥hŗyƒ^ŸĭÁZ]cIzý‰ah¹MĪğP‘s{ò‡‹‘²Vw¹t³Ŝˁ[ŽÑ}X\\gsFŸ£sPAgěp×ëfYHāďÖqēŭOÏë“dLü•\\iŒ”t^c®šRʺ¶—¢H°mˆ‘rYŸ£BŸ¹čIoľu¶uI]vģSQ{ƒUŻ”Å}QÂ|̋°ƅ¤ĩŪU ęĄžÌZҞ\\v˜²PĔ»ƢNHƒĂyAmƂwVmž`”]ȏb•”H`‰Ì¢²ILvĜ—H®¤Dlt_„¢JJÄämèÔDëþgºƫ™”aʎÌrêYi~ ÎݤNpÀA¾Ĕ¼b…ð÷’Žˆ‡®‚”üs”zMzÖĖQdȨý†v§Tè|ªH’þa¸|šÐ ƒwKĢx¦ivr^ÿ ¸l öæfƟĴ·PJv}n\\h¹¶v†·À|\\ƁĚN´Ĝ€çèÁz]ġ¤²¨QÒŨTIl‡ªťØ}¼˗ƦvÄùØE‹’«Fï˛Iq”ōŒTvāÜŏ‚íÛߜÛV—j³âwGăÂíNOŠˆŠPìyV³ʼnĖýZso§HіiYw[߆\\X¦¥c]ÔƩÜ·«j‡ÐqvÁ¦m^ċ±R™¦΋ƈťĚgÀ»IïĨʗƮްƝ˜ĻþÍAƉſ±tÍEÕÞāNU͗¡\\ſčåÒʻĘm ƭÌŹöʥ’ëQ¤µ­ÇcƕªoIýˆ‰Iɐ_mkl³ă‰Ɠ¦j—¡Yz•Ňi–}Msßõ–īʋ —}ƒÁVmŸ_[n}eı­Uĥ¼‘ª•I{ΧDӜƻėoj‘qYhĹT©oūĶ£]ďxĩ‹ǑMĝ‰q`B´ƃ˺Ч—ç~™²ņj@”¥@đ´ί}ĥtPńǾV¬ufӃÉC‹tÓ̻‰…¹£G³€]ƖƾŎĪŪĘ̖¨ʈĢƂlɘ۪üºňUðǜȢƢż̌ȦǼ‚ĤŊɲĖ­Kq´ï¦—ºĒDzņɾªǀÞĈĂD†½ĄĎÌŗĞrôñnŽœN¼â¾ʄľԆ|DŽŽ֦ज़ȗlj̘̭ɺƅêgV̍ʆĠ·ÌĊv|ýĖÕWĊǎÞ´õ¼cÒÒBĢ͢UĜð͒s¨ňƃLĉÕÝ@ɛƯ÷¿Ľ­ĹeȏijëCȚDŲyê×Ŗyò¯ļcÂßY…tÁƤyAã˾J@ǝrý‹‰@¤…rz¸oP¹ɐÚyᐇHŸĀ[Jw…cVeȴϜ»ÈŽĖ}ƒŰŐèȭǢόĀƪÈŶë;Ñ̆ȤМľĮEŔ—ĹŊũ~ËUă{ŸĻƹɁύȩþĽvĽƓÉ@ē„ĽɲßǐƫʾǗĒpäWÐxnsÀ^ƆwW©¦cÅ¡Ji§vúF¶Ž¨c~c¼īŒeXǚ‹\\đ¾JŽwÀďksãA‹fÕ¦L}wa‚o”Z’‹D½†Ml«]eÒÅaɲáo½FõÛ]ĻÒ¡wYR£¢rvÓ®y®LF‹LzĈ„ôe]gx}•|KK}xklL]c¦£fRtív¦†PĤoH{tK"
]
],
"encodeOffsets": [[[108619, 36299]], [[108589, 36341]]]
}
},
{
"type": "Feature",
"id": "630000",
"properties": { "id": "630000", "cp": [96.778916, 35.623178], "name": "青海", "childNum": 2 },
"geometry": {
"type": "MultiPolygon",
"coordinates": [
["@@InJm"],
[
"@@CƒÆ½OŃĦsΰ~dz¦@@“Ņiš±è}ؘƄ˹A³r_ĞŠǒNΌĐw¤^ŬĵªpĺSZg’rpiƼĘԛ¨C|͖J’©Ħ»®VIJ~f\\m `Un„˜~ʌŸ•ĬàöNt•~ňjy–¢Zi˜Ɣ¥ĄŠk´nl`JʇŠJþ©pdƖ®È£¶ìRʦ‘źõƮËnŸʼėæÑƀĎ[‚˜¢VÎĂMÖÝÎF²sƊƀÎBļýƞ—¯ʘƭðħ¼Jh¿ŦęΌƇš¥²Q]Č¥nuÂÏriˆ¸¬ƪÛ^Ó¦d€¥[Wà…x\\ZŽjҕ¨GtpþYŊĕ´€zUO뇉P‰îMĄÁxH´á˜iÜUà›îÜՁĂÛSuŎ‹r“œJð̬EŒ‘FÁú×uÃÎkr“Ē{V}İ«O_ÌËĬ©ŽÓŧSRѱ§Ģ£^ÂyèçěM³Ƃę{[¸¿u…ºµ[gt£¸OƤĿéYŸõ·kŸq]juw¥Dĩƍ€õÇPéĽG‘ž©ã‡¤G…uȧþRcÕĕNy“yût“ˆ­‡ø‘†ï»a½ē¿BMoᣟÍj}éZËqbʍš“Ƭh¹ìÿÓAçãnIáI`ƒks£CG­ě˜Uy×Cy•…’Ÿ@¶ʡÊBnāzG„ơMē¼±O÷õJËĚăVŸĪũƆ£Œ¯{ËL½Ìzż“„VR|ĠTbuvJvµhĻĖH”Aëáa…­OÇðñęNw‡…œľ·L›mI±íĠĩPÉ×®ÿs—’cB³±JKßĊ«`…ađ»·QAmO’‘Vţéÿ¤¹SQt]]Çx€±¯A@ĉij¢Ó祖•ƒl¶ÅÛr—ŕspãRk~¦ª]Į­´“FR„åd­ČsCqđéFn¿Åƃm’Éx{W©ºƝºįkÕƂƑ¸wWūЩÈFž£\\tÈ¥ÄRÈýÌJ ƒlGr^×äùyÞ³fj”c†€¨£ÂZ|ǓMĝšÏ@ëÜőR‹›ĝ‰Œ÷¡{aïȷPu°ËXÙ{©TmĠ}Y³’­ÞIňµç½©C¡į÷¯B»|St»›]vƒųƒs»”}MÓ ÿʪƟǭA¡fs˜»PY¼c¡»¦c„ċ­¥£~msĉP•–Siƒ^o©A‰Šec‚™PeǵŽkg‚yUi¿h}aH™šĉ^|ᴟ¡HØûÅ«ĉ®]m€¡qĉ¶³ÈyôōLÁst“BŸ®wn±ă¥HSò뚣˜S’ë@לÊăxÇN©™©T±ª£IJ¡fb®ÞbŽb_Ą¥xu¥B—ž{łĝ³«`d˜Ɛt—¤ťiñžÍUuºí`£˜^tƃIJc—·ÛLO‹½Šsç¥Ts{ă\\_»™kϊ±q©čiìĉ|ÍIƒ¥ć¥›€]ª§D{ŝŖÉR_sÿc³Īō›ƿΑ›§p›[ĉ†›c¯bKm›R¥{³„Z†e^ŽŒwx¹dƽŽôIg §Mĕ ƹĴ¿—ǣÜ̓]‹Ý–]snåA{‹eŒƭ`ǻŊĿ\\ijŬű”YÂÿ¬jĖqŽßbЏ•L«¸©@ěĀ©ê¶ìÀEH|´bRľž–Ó¶rÀQþ‹vl®Õ‚E˜TzÜdb ˜hw¤{LR„ƒd“c‹b¯‹ÙVgœ‚ƜßzÃô쮍^jUèXΖ|UäÌ»rKŽ\\ŒªN‘¼pZCü†VY††¤ɃRi^rPҒTÖ}|br°qňb̰ªiƶGQ¾²„x¦PœmlŜ‘[Ĥ¡ΞsĦŸÔÏâ\\ªÚŒU\\f…¢N²§x|¤§„xĔsZPòʛ²SÐqF`ª„VƒÞŜĶƨVZŒÌL`ˆ¢dŐIqr\\oäõ–F礻Ŷ×h¹]Clـ\\¦ďÌį¬řtTӺƙgQÇÓHţĒ”´ÃbEÄlbʔC”|CˆŮˆk„Ʈ[ʼ¬ňœ´KŮÈΰÌζƶlð”ļA†TUvdTŠG†º̼ŠÔ€ŒsÊDԄveOg"
]
],
"encodeOffsets": [[[105308, 37219]], [[95370, 40081]]]
}
},
{
"type": "Feature",
"id": "640000",
"properties": { "id": "640000", "cp": [106.278179, 37.26637], "name": "宁夏", "childNum": 2 },
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
"@@KëÀęĞ«OęȿȕŸı]ʼn¡åįÕÔ«Ǵõƪ™ĚQÐZhv K°›öqÀѐS[ÃÖHƖčË‡nL]ûc…Ùß@‚“ĝ‘¾}w»»‹oģF¹œ»kÌÏ·{zPƒ§B­¢íyÅt@ƒ@áš]Yv_ssģ¼i߁”ĻL¾ġsKD£¡N_…“˜X¸}B~Haiˆ™Åf{«x»ge_bs“KF¯¡Ix™mELcÿZ¤­Ģ‘ƒÝœsuBLù•t†ŒYdˆmVtNmtOPhRw~bd…¾qÐ\\âÙH\\bImlNZŸ»loƒŸqlVm–Gā§~QCw¤™{A\\‘PKŸNY‡¯bF‡kC¥’sk‹Šs_Ã\\ă«¢ħkJi¯r›rAhĹûç£CU‡ĕĊ_ԗBixÅُĄnªÑaM~ħpOu¥sîeQ¥¤^dkKwlL~{L~–hw^‚ófćƒKyEŒ­K­zuÔ¡qQ¤xZÑ¢^ļöܾEpž±âbÊÑÆ^fk¬…NC¾‘Œ“YpxbK~¥Že֎ŒäBlt¿Đx½I[ĒǙŒWž‹f»Ĭ}d§dµùEuj¨‚IÆ¢¥dXªƅx¿]mtÏwßR͌X¢͎vÆzƂZò®ǢÌʆCrâºMÞzžÆMҔÊÓŊZľ–r°Î®Ȉmª²ĈUªĚøºˆĮ¦ÌĘk„^FłĬhĚiĀ˾iİbjÕ"
],
["@@mfwěwMrŢªv@G‰"]
],
"encodeOffsets": [[[109366, 40242]], [[108600, 36303]]]
}
},
{
"type": "Feature",
"id": "650000",
"properties": { "id": "650000", "cp": [85.617733, 40.792818], "name": "新疆", "childNum": 1 },
"geometry": {
"type": "Polygon",
"coordinates": [
"@@QØĔ²X¨”~ǘBºjʐߨvK”ƔX¨vĊOžÃƒ·¢i@~c—‡ĝe_«”Eš“}QxgɪëÏÃ@sÅyXoŖ{ô«ŸuX…ê•Îf`œC‚¹ÂÿÐGĮÕĞXŪōŸMźÈƺQèĽôe|¿ƸJR¤ĘEjcUóº¯Ĩ_ŘÁMª÷Ð¥Oéȇ¿ÖğǤǷÂF҇zÉx[]­Ĥĝ‰œ¦EP}ûƥé¿İƷTėƫœŕƅ™ƱB»Đ±’ēO…¦E–•}‘`cȺrĦáŖuҞª«IJ‡πdƺÏØZƴwʄ¤ĖGЙǂZ̓èH¶}ÚZצʥĪï|ÇĦMŔ»İĝLj‹ì¥Βœba­¯¥ǕǚkĆŵĦɑĺƯxūД̵nơʃĽá½M»›òmqóŘĝč˾ăC…ćāƿÝɽ©DZŅ¹đ¥˜³ðLrÁ®ɱĕģʼnǻ̋ȥơŻǛȡVï¹Ň۩ûkɗġƁ§ʇė̕ĩũƽō^ƕŠUv£ƁQï“Ƶkŏ½ΉÃŭdzLқʻ«ƭ\\lƒ‡ŭD‡“{ʓDkaFÃÄa“³ŤđÔGRÈƚhSӹŚsİ«ĐË[¥ÚDkº^Øg¼ŵ¸£EÍö•€ůʼnT¡c_‡ËKY‹ƧUśĵ„݃U_©rETÏʜ±OñtYw獃{£¨uM³x½şL©Ùá[ÓÐĥ Νtģ¢\\‚ś’nkO›w¥±ƒT»ƷFɯàĩÞáB¹Æ…ÑUw„੍žĽw[“mG½Èå~‡Æ÷QyŠěCFmĭZī—ŵVÁ™ƿQƛ—ûXS²‰b½KϽĉS›©ŷXĕŸ{ŽĕK·¥Ɨcqq©f¿]‡ßDõU³h—­gËÇïģÉɋw“k¯í}I·šœbmœÉ–ř›īJɥĻˁ×xo›ɹī‡l•c…¤³Xù]‘™DžA¿w͉ì¥wÇN·ÂËnƾƍdǧđ®Ɲv•Um©³G\\“}µĿ‡QyŹl㓛µEw‰LJQ½yƋBe¶ŋÀů‡ož¥A—˜Éw@•{Gpm¿Aij†ŽKLhˆ³`ñcËtW‚±»ÕS‰ëüÿďD‡u\\wwwù³—V›LŕƒOMËGh£õP¡™er™Ïd{“‡ġWÁ…č|yšg^ğyÁzÙs`—s|ÉåªÇ}m¢Ń¨`x¥’ù^•}ƒÌ¥H«‰Yªƅ”Aйn~Ꝛf¤áÀz„gŠÇDIԝ´AňĀ҄¶ûEYospõD[{ù°]u›Jq•U•|Soċxţ[õÔĥkŋÞŭZ˺óYËüċrw €ÞkrťË¿XGÉbřaDü·Ē÷Aê[Ää€I®BÕИÞ_¢āĠpŠÛÄȉĖġDKwbm‡ÄNô‡ŠfœƫVÉvi†dz—H‘‹QµâFšù­Âœ³¦{YGžƒd¢ĚÜO „€{Ö¦ÞÍÀPŒ^b–ƾŠlŽ[„vt×ĈÍE˨¡Đ~´î¸ùÎh€uè`¸ŸHÕŔVºwĠââWò‡@{œÙNÝ´ə²ȕn{¿¥{l—÷eé^e’ďˆXj©î\\ªÑò˜Üìc\\üqˆÕ[Č¡xoÂċªbØ­Œø|€¶ȴZdÆÂšońéŒGš\\”¼C°ÌƁn´nxšÊOĨ’ہƴĸ¢¸òTxÊǪMīИÖŲÃɎOvˆʦƢ~FއRěò—¿ġ~åŊœú‰Nšžš¸qŽ’Ę[Ĕ¶ÂćnÒPĒÜvúĀÊbÖ{Äî¸~Ŕünp¤ÂH¾œĄYÒ©ÊfºmԈĘcDoĬMŬ’˜S¤„s²‚”ʘچžȂVŦ –ŽèW°ªB|IJXŔþÈJĦÆæFĚêŠYĂªĂ]øªŖNÞüA€’fɨJ€˜¯ÎrDDšĤ€`€mz\\„§~D¬{vJÂ˜«lµĂb–¤p€ŌŰNĄ¨ĊXW|ų ¿¾ɄĦƐMT”‡òP˜÷fØĶK¢ȝ˔Sô¹òEð­”`Ɩ½ǒÂň×äı–§ĤƝ§C~¡‚hlå‚ǺŦŞkâ’~}ŽFøàIJaĞ‚fƠ¥Ž„Ŕdž˜®U¸ˆźXœv¢aƆúŪtŠųƠjd•ƺŠƺÅìnrh\\ĺ¯äɝĦ]èpĄ¦´LƞĬŠ´ƤǬ˼Ēɸ¤rºǼ²¨zÌPðŀbþ¹ļD¢¹œ\\ĜÑŚŸ¶ZƄ³àjĨoâŠȴLʉȮŒĐ­ĚăŽÀêZǚŐ¤qȂ\\L¢ŌİfÆs|zºeªÙæ§΢{Ā´ƐÚ¬¨Ĵà²łhʺKÞºÖTŠiƢ¾ªì°`öøu®Ê¾ãØ"
],
"encodeOffsets": [[88824, 50096]]
}
},
{
"type": "Feature",
"id": "110000",
"properties": {
"id": "110000",
"cp": [116.405285, 39.904989],
"name": "北京",
"childNum": 1
},
"geometry": {
"type": "Polygon",
"coordinates": [
"@@ĽOÁ›ûtŷmiÍt_H»Ĩ±d`й­{bw…Yr“³S]§§o¹€qGtm_Sŧ€“oa›‹FLg‘QN_•dV€@Zom_ć\\ߚc±x¯oœRcfe…£’o§ËgToÛJíĔóu…|wP¤™XnO¢ÉˆŦ¯rNÄā¤zâŖÈRpŢZŠœÚ{GŠrFt¦Òx§ø¹RóäV¤XdˆżâºWbwڍUd®bêņ¾‘jnŎGŃŶŠnzÚSeîĜZczî¾i]͜™QaúÍÔiþĩȨWĢ‹ü|Ėu[qb[swP@ÅğP¿{\\‡¥A¨Ï‘Ѩj¯ŠX\\¯œMK‘pA³[H…īu}}"
],
"encodeOffsets": [[120023, 41045]]
}
},
{
"type": "Feature",
"id": "120000",
"properties": {
"id": "120000",
"cp": [117.190182, 39.125596],
"name": "天津",
"childNum": 1
},
"geometry": {
"type": "Polygon",
"coordinates": [
"@@ŬgX§Ü«E…¶Ḟ“¬O_™ïlÁg“z±AXe™µÄĵ{¶]gitgšIj·›¥îakS€‰¨ÐƎk}ĕ{gB—qGf{¿a†U^fI“ư‹³õ{YƒıëNĿžk©ïËZŏ‘R§òoY×Ógc…ĥs¡bġ«@dekąI[nlPqCnp{ˆō³°`{PNdƗqSÄĻNNâyj]äžÒD ĬH°Æ]~¡HO¾ŒX}ÐxŒgp“gWˆrDGˆŒpù‚Š^L‚ˆrzWxˆZ^¨´T\\|~@I‰zƒ–bĤ‹œjeĊªz£®Ĕvě€L†mV¾Ô_ȔNW~zbĬvG†²ZmDM~”~"
],
"encodeOffsets": [[120237, 41215]]
}
},
{
"type": "Feature",
"id": "310000",
"properties": {
"id": "310000",
"cp": [121.472644, 31.231706],
"name": "上海",
"childNum": 6
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
["@@ɧư¬EpƸÁxc‡"],
["@@©„ªƒ"],
["@@”MA‹‘š"],
["@@Qp݁E§ÉC¾"],
["@@bŝՕÕEȣÚƥêImɇǦèÜĠŒÚžÃƌÃ͎ó"],
["@@ǜûȬɋŠŭ™×^‰sYŒɍDŋ‘ŽąñCG²«ªč@h–_p¯A{‡oloY€¬j@IJ`•gQڛhr|ǀ^MIJvtbe´R¯Ô¬¨YŽô¤r]ì†Ƭį"]
],
"encodeOffsets": [
[[124702, 32062]],
[[124547, 32200]],
[[124808, 31991]],
[[124726, 32110]],
[[124903, 32376]],
[[124438, 32149]]
]
}
},
{
"type": "Feature",
"id": "500000",
"properties": {
"id": "500000",
"cp": [107.304962, 29.533155],
"name": "重庆",
"childNum": 2
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
"@@vjG~nGŘŬĶȂƀƾ¹¸ØÎezĆT¸}êЖqHŸðqĖ䒊¥^CƒIj–²p…\\_ æüY|[YxƊæuž°xb®…Űb@~¢NQt°¶‚S栓Ê~rljĔëĚ¢~šuf`‘‚†fa‚ĔJåĊ„nÖ]„jƎćÊ@Š£¾a®£Ű{ŶĕF‹ègLk{Y|¡ĜWƔtƬJÑxq‹±ĢN´‰òK‰™–LÈüD|s`ŋ’ć]ƒÃ‰`đŒMûƱ½~Y°ħ`ƏíW‰½eI‹½{aŸ‘OIrÏ¡ĕŇa†p†µÜƅġ‘œ^ÖÛbÙŽŏml½S‹êqDu[R‹ãË»†ÿw`»y‘¸_ĺę}÷`M¯ċfCVµqʼn÷Z•gg“Œ`d½pDO‡ÎCnœ^uf²ènh¼WtƏxRGg¦…pV„†FI±ŽG^ŒIc´ec‡’G•ĹÞ½sëĬ„h˜xW‚}Kӈe­Xsbk”F¦›L‘ØgTkïƵNï¶}Gy“w\\oñ¡nmĈzjŸ•@™Óc£»Wă¹Ój“_m»ˆ¹·~MvÛaqœ»­‰êœ’\\ÂoVnŽÓØÍ™²«‹bq¿efE „€‹Ĝ^Qž~ Évý‡ş¤²Į‰pEİ}zcĺƒL‹½‡š¿gņ›¡ýE¡ya£³t\\¨\\vú»¼§·Ñr_oÒý¥u‚•_n»_ƒ•At©Þűā§IVeëƒY}{VPÀFA¨ąB}q@|Ou—\\Fm‰QF݅Mw˜å}]•€|FmϋCaƒwŒu_p—¯sfÙgY…DHl`{QEfNysBЦzG¸rHe‚„N\\CvEsÐùÜ_·ÖĉsaQ¯€}_U‡†xÃđŠq›NH¬•Äd^ÝŰR¬ã°wećJEž·vÝ·Hgƒ‚éFXjÉê`|yŒpxkAwœWĐpb¥eOsmzwqChóUQl¥F^laf‹anòsr›EvfQdÁUVf—ÎvÜ^efˆtET¬ôA\\œ¢sJŽnQTjP؈xøK|nBz‰„œĞ»LY‚…FDxӄvr“[ehľš•vN”¢o¾NiÂxGp⬐z›bfZo~hGi’]öF|‰|Nb‡tOMn eA±ŠtPT‡LjpYQ|†SH††YĀxinzDJ€Ìg¢và¥Pg‰_–ÇzII‹€II•„£®S¬„Øs쐣ŒN"
],
["@@ifjN@s"]
],
"encodeOffsets": [[[109628, 30765]], [[111725, 31320]]]
}
},
{
"type": "Feature",
"id": "810000",
"properties": {
"id": "810000",
"cp": [114.173355, 22.320048],
"name": "香港",
"childNum": 5
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
["@@AlBk"],
["@@mŽn"],
["@@EpFo"],
["@@ea¢pl¸Eõ¹‡hj[ƒ]ÔCΖ@lj˜¡uBXŸ…•´‹AI¹…[‹yDUˆ]W`çwZkmc–…M›žp€Åv›}I‹oJlcaƒfёKްä¬XJmРđhI®æÔtSHn€Eˆ„ÒrÈc"],
["@@rMUw‡AS®€e"]
],
"encodeOffsets": [
[[117111, 23002]],
[[117072, 22876]],
[[117045, 22887]],
[[116975, 23082]],
[[116882, 22747]]
]
}
},
{
"type": "Feature",
"id": "820000",
"properties": { "id": "820000", "cp": [113.54909, 22.198951], "name": "澳门", "childNum": 1 },
"geometry": {
"type": "Polygon",
"coordinates": ["@@kÊd°å§s"],
"encodeOffsets": [[116279, 22639]]
}
}
],
"UTF8Encoding": true
}
@@ -1,7 +1,6 @@
<template>
<div :class="['component', { active: active }]">
<div
class="component-inner"
:style="{
...style
}"
@@ -127,114 +126,110 @@ $active-border-width: 2px;
$hover-border-width: 1px;
$name-position: -85px;
$toolbar-position: -55px;
/* 组件 */
.component {
position: relative;
cursor: move;
.component-inner {
position: relative;
z-index: 1;
}
/* 用于包裹组件,为组件提供 组件名称、工具栏、边框等样式 */
.component-wrap {
z-index: 0;
// 不可以被点击
// component-wrap会遮挡组件,导致组件不能触发鼠标事件,所以这里要先禁用,然后在组件名称、工具栏上开启。
pointer-events: none;
display: block;
position: absolute;
left: -$active-border-width;
top: 0;
left: -$active-border-width;
display: block;
width: 100%;
height: 100%;
/* 鼠标放到组件上时 */
&:hover {
border: $hover-border-width dashed var(--el-color-primary);
box-shadow: 0 0 5px 0 rgb(24 144 255 / 30%);
.component-name {
top: $hover-border-width;
/* 防止加了边框之后,位置移动 */
left: $name-position - $hover-border-width;
}
}
/* 左侧:组件名称 */
.component-name {
// 可以被点击
pointer-events: auto;
display: block;
position: absolute;
width: 80px;
text-align: center;
line-height: 25px;
height: 25px;
background: #fff;
font-size: 12px;
left: $name-position;
top: $active-border-width;
left: $name-position;
display: block;
width: 80px;
height: 25px;
font-size: 12px;
line-height: 25px;
text-align: center;
background: #fff;
box-shadow:
0 0 4px #00000014,
0 2px 6px #0000000f,
0 4px 8px 2px #0000000a;
/* 右侧小三角 */
&:after {
&::after {
position: absolute;
top: 7.5px;
right: -10px;
content: ' ';
height: 0;
width: 0;
height: 0;
border: 5px solid transparent;
border-left-color: #fff;
content: ' ';
}
}
/* 右侧:组件操作工具栏 */
.component-toolbar {
// 可以被点击
pointer-events: auto;
display: none;
position: absolute;
top: 0;
right: $toolbar-position;
display: none;
/* 左侧小三角 */
&:before {
&::before {
position: absolute;
top: 10px;
left: -10px;
content: ' ';
height: 0;
width: 0;
height: 0;
border: 5px solid transparent;
border-right-color: #2d8cf0;
content: ' ';
}
}
}
/* 组件选中时 */
&.active {
margin-bottom: 4px;
.component-wrap {
z-index: 2;
border: $active-border-width solid var(--el-color-primary) !important;
box-shadow: 0 0 10px 0 rgba(24, 144, 255, 0.3);
margin-bottom: $active-border-width + $active-border-width;
border: $active-border-width solid var(--el-color-primary) !important;
box-shadow: 0 0 10px 0 rgb(24 144 255 / 30%);
.component-name {
background: var(--el-color-primary);
color: #fff;
top: 0 !important;
/* 防止加了边框之后,位置移动 */
left: $name-position - $active-border-width !important;
top: 0 !important;
&:after {
color: #fff;
background: var(--el-color-primary);
&::after {
border-left-color: var(--el-color-primary);
}
}
.component-toolbar {
display: block;
}
}
}
/* 鼠标放到组件上时 */
&:hover {
.component-wrap {
z-index: 2;
border: $hover-border-width dashed var(--el-color-primary);
box-shadow: 0 0 5px 0 rgba(24, 144, 255, 0.3);
.component-name {
/* 防止加了边框之后,位置移动 */
left: $name-position - $hover-border-width;
top: $hover-border-width;
}
}
}
}
</style>
@@ -157,6 +157,7 @@ const handleSliderChange = (prop: string) => {
:deep(.el-slider__runway) {
margin-right: 16px;
}
:deep(.el-input-number) {
width: 50px;
}
@@ -90,23 +90,26 @@ const handleCloneComponent = (component: DiyComponent<any>) => {
.editor-left {
z-index: 1;
flex-shrink: 0;
box-shadow: 8px 0 8px -8px rgba(0, 0, 0, 0.12);
box-shadow: 8px 0 8px -8px rgb(0 0 0 / 12%);
:deep(.el-collapse) {
border-top: none;
}
:deep(.el-collapse-item__wrap) {
border-bottom: none;
}
:deep(.el-collapse-item__content) {
padding-bottom: 0;
}
:deep(.el-collapse-item__header) {
border-bottom: none;
background-color: var(--el-bg-color-page);
padding: 0 24px;
height: 32px;
padding: 0 24px;
line-height: 32px;
background-color: var(--el-bg-color-page);
border-bottom: none;
}
.component-container {
@@ -116,25 +119,26 @@ const handleCloneComponent = (component: DiyComponent<any>) => {
}
.component {
display: flex;
width: 86px;
height: 86px;
display: flex;
cursor: move;
border-right: 1px solid var(--el-border-color-lighter);
border-bottom: 1px solid var(--el-border-color-lighter);
flex-direction: column;
align-items: center;
justify-content: center;
border-right: 1px solid var(--el-border-color-lighter);
border-bottom: 1px solid var(--el-border-color-lighter);
cursor: move;
.el-icon {
margin-bottom: 4px;
color: gray;
}
}
.component.active,
.component:hover {
background: var(--el-color-primary);
color: var(--el-color-white);
background: var(--el-color-primary);
.el-icon {
color: var(--el-color-white);
@@ -155,11 +159,10 @@ const handleCloneComponent = (component: DiyComponent<any>) => {
.drag-area {
/* 拖拽到手机区域时的样式 */
.draggable-ghost {
display: flex;
width: 100%;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
/* 条纹背景 */
background: linear-gradient(
45deg,
@@ -174,20 +177,25 @@ const handleCloneComponent = (component: DiyComponent<any>) => {
);
background-size: 1rem 1rem;
transition: all 0.5s;
justify-content: center;
align-items: center;
span {
color: #fff;
display: inline-block;
width: 140px;
height: 25px;
font-size: 12px;
text-align: center;
line-height: 25px;
color: #fff;
text-align: center;
background: #5487df;
}
/* 拖拽时隐藏组件 */
.component {
display: none;
}
/* 拖拽时显示占位提示 */
.drag-placement {
display: block;
@@ -17,8 +17,8 @@ defineProps<{ property: ImageBarProperty }>()
<style scoped lang="scss">
/* 图片 */
img {
display: block;
width: 100%;
height: 100%;
display: block;
}
</style>
@@ -35,22 +35,25 @@ defineProps<{ property: NavigationBarProperty }>()
</script>
<style lang="scss" scoped>
.navigation-bar {
display: flex;
height: 35px;
background: #fff;
display: flex;
justify-content: space-between;
align-items: center;
/* 左边 */
.left {
margin-left: 8px;
}
.center {
flex: 1;
text-align: center;
font-size: 14px;
line-height: 35px;
color: #333333;
color: #333;
text-align: center;
flex: 1;
}
/* 右边 */
.right {
margin-right: 8px;
@@ -45,21 +45,21 @@ defineProps<{ property: SearchProperty }>()
/* 搜索框 */
.inner {
position: relative;
min-height: 28px;
display: flex;
align-items: center;
min-height: 28px;
font-size: 14px;
align-items: center;
.placeholder {
display: flex;
align-items: center;
width: 100%;
padding: 0 8px;
gap: 2px;
text-overflow: ellipsis;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
white-space: nowrap;
align-items: center;
gap: 2px;
}
.right {
@@ -30,8 +30,9 @@ defineProps<{ property: TabBarProperty }>()
</script>
<style lang="scss" scoped>
.tab-bar {
width: 100%;
z-index: 2;
width: 100%;
.tab-bar-bg {
display: flex;
flex-direction: row;
@@ -41,11 +42,11 @@ defineProps<{ property: TabBarProperty }>()
.tab-bar-item {
display: flex;
width: 100%;
font-size: 12px;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: 12px;
width: 100%;
img {
width: 26px;
@@ -56,23 +56,23 @@ defineProps<{ property: TitleBarProperty }>()
</script>
<style scoped lang="scss">
.title-bar {
position: relative;
width: 100%;
min-height: 20px;
padding: 8px 16px;
border: 2px solid #fff;
box-sizing: border-box;
width: 100%;
padding: 8px 16px;
min-height: 20px;
position: relative;
/* 更多 */
.more {
position: absolute;
right: 8px;
top: 0;
right: 8px;
bottom: 0;
display: flex;
margin: auto;
font-size: 10px;
color: #969799;
display: flex;
align-items: center;
justify-content: center;
}
@@ -23,8 +23,8 @@ defineProps<{ property: VideoPlayerProperty }>()
<style scoped lang="scss">
/* 图片 */
img {
display: block;
width: 100%;
height: 100%;
display: block;
}
</style>
+35 -19
View File
@@ -337,28 +337,33 @@ onMounted(() => setDefaultSelectedComponent())
/* 手机宽度 */
$phone-width: 375px;
$toolbar-height: 42px;
/* 根节点样式 */
.editor {
display: flex;
height: 100%;
margin: calc(0px - var(--app-content-padding));
display: flex;
flex-direction: column;
/* 顶部:工具栏 */
.editor-header {
display: flex;
align-items: center;
justify-content: space-between;
height: $toolbar-height;
padding: 0;
border-bottom: solid 1px var(--el-border-color);
background-color: var(--el-bg-color);
border-bottom: solid 1px var(--el-border-color);
align-items: center;
justify-content: space-between;
/* 工具栏:右侧按钮 */
.header-right {
height: 100%;
.el-button {
height: 100%;
}
}
/* 隐藏工具栏按钮的边框 */
:deep(.el-radio-button__inner),
:deep(.el-button) {
@@ -367,33 +372,40 @@ $toolbar-height: 42px;
border-radius: 0 !important;
}
}
/* 中心操作区 */
.editor-container {
height: calc(
100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) -
$toolbar-height
);
/* 右侧属性面板 */
.editor-right {
flex-shrink: 0;
box-shadow: -8px 0 8px -8px rgba(0, 0, 0, 0.12);
overflow: hidden;
box-shadow: -8px 0 8px -8px rgb(0 0 0 / 12%);
flex-shrink: 0;
/* 属性面板顶部:减少内边距 */
:deep(.el-card__header) {
padding: 8px 16px;
}
/* 属性面板分组 */
:deep(.property-group) {
margin: 0 -20px;
&.el-card {
border: none;
}
/* 属性分组名称 */
.el-card__header {
border: none;
background: var(--el-bg-color-page);
padding: 8px 32px;
background: var(--el-bg-color-page);
border: none;
}
.el-card__body {
border: none;
}
@@ -403,33 +415,36 @@ $toolbar-height: 42px;
/* 中心区域 */
.editor-center {
position: relative;
flex: 1 1 0;
background-color: var(--app-content-bg-color);
display: flex;
width: 100%;
margin: 16px 0 0;
overflow: hidden;
background-color: var(--app-content-bg-color);
flex: 1 1 0;
flex-direction: column;
justify-content: center;
margin: 16px 0 0 0;
overflow: hidden;
width: 100%;
/* 手机顶部 */
.editor-design-top {
display: flex;
width: $phone-width;
margin: 0 auto;
display: flex;
flex-direction: column;
/* 手机顶部状态栏 */
.status-bar {
height: 20px;
width: $phone-width;
height: 20px;
background-color: #fff;
}
}
/* 手机底部导航 */
.editor-design-bottom {
width: $phone-width;
margin: 0 auto;
}
/* 手机页面编辑区域 */
:deep(.editor-design-center) {
width: 100%;
@@ -437,14 +452,15 @@ $toolbar-height: 42px;
/* 主体内容 */
.phone-container {
position: relative;
width: $phone-width;
height: 100%;
margin: 0 auto;
background-repeat: no-repeat;
background-size: 100% 100%;
height: 100%;
width: $phone-width;
margin: 0 auto;
.drag-area {
height: 100%;
width: 100%;
height: 100%;
}
}
}
@@ -144,6 +144,8 @@ watch(
} else if (isArray(props.modelValue)) {
// 情况2:字符串
files.concat(props.modelValue)
} else if (props.modelValue == null) {
// 情况3:undefined 不处理
} else {
throw new Error('不支持的 modelValue 类型')
}
+11 -7
View File
@@ -17,24 +17,28 @@ defineOptions({ name: 'VerticalButtonGroup' })
display: inline-flex;
flex-direction: column;
}
.el-button-group > :deep(.el-button:first-child) {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
border-top-right-radius: var(--el-border-radius-base);
border-bottom-color: var(--el-button-divide-border-color);
border-top-right-radius: var(--el-border-radius-base);
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.el-button-group > :deep(.el-button:last-child) {
border-top-left-radius: 0;
border-top-color: var(--el-button-divide-border-color);
border-top-right-radius: 0;
border-bottom-left-radius: var(--el-border-radius-base);
border-top-color: var(--el-button-divide-border-color);
border-top-left-radius: 0;
}
.el-button-group :deep(.el-button--primary:not(:first-child):not(:last-child)) {
.el-button-group :deep(.el-button--primary:not(:first-child, :last-child)) {
border-top-color: var(--el-button-divide-border-color);
border-bottom-color: var(--el-button-divide-border-color);
}
.el-button-group > :deep(.el-button:not(:last-child)) {
margin-bottom: -1px;
margin-right: 0;
margin-bottom: -1px;
}
</style>
@@ -88,8 +88,8 @@ onMounted(() => {
}
.message-list {
height: 400px;
display: flex;
height: 400px;
flex-direction: column;
.message-item {
+10
View File
@@ -503,6 +503,16 @@ const remainingRouter: AppRouteRecordRaw[] = [
hidden: true
},
component: () => import('@/views/crm/customer/detail/index.vue')
},
{
path: 'contact/detail/:id',
name: 'CrmContactDetail',
meta: {
title: '联系人详情',
noCache: true,
hidden: true
},
component: () => import('@/views/crm/contact/detail/index.vue')
}
]
}
+348
View File
@@ -0,0 +1,348 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible" :width="800">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="130px"
v-loading="formLoading"
:inline="true"
>
<el-form-item label="姓名" prop="name">
<el-input v-model="formData.name" placeholder="请输入姓名" />
</el-form-item>
<el-form-item label="负责人" prop="ownerUserId">
<el-select
v-model="ownerUserList"
placeholder="请选择负责人"
multiple
value-key="id"
lable-key="nickname"
@click="openOwerForm('open')"
>
<el-option
v-for="item in ownerUserList"
:key="item.id"
:label="item.nickname"
:value="item"
/>
</el-select>
</el-form-item>
<el-form-item label="客户名称" prop="customerName">
<el-popover
placement="bottom"
:width="600"
trigger="click"
:teleported="false"
:visible="showCustomer"
:offset="10"
>
<template #reference>
<el-input
placeholder="请选择"
@click="openCustomerSelect"
v-model="formData.customerName"
/>
</template>
<el-table :data="list" ref="multipleTableRef" @select="handleSelectionChange">
<el-table-column label="选择" type="selection" width="55" />
<el-table-column width="100" property="id" label="编号" />
<el-table-column width="150" property="name" label="客户名称" />
<el-table-column label="客户来源" align="center" prop="source" width="100">
<template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_CUSTOMER_SOURCE" :value="scope.row.source" />
</template>
</el-table-column>
<el-table-column label="客户等级" align="center" prop="level" width="120">
<template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_CUSTOMER_LEVEL" :value="scope.row.level" />
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-row :gutter="20">
<el-col>
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
layout="sizes, prev, pager, next"
/>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="10" :offset="13">
<el-button @click="selectCustomer">确认</el-button>
<el-button @click="showCustomer = false">取消</el-button>
</el-col>
</el-row>
</el-popover>
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-select v-model="formData.sex" placeholder="请选择">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="手机号" prop="mobile">
<el-input v-model="formData.mobile" placeholder="请输入手机号" />
</el-form-item>
<el-form-item label="座机" prop="telephone">
<el-input v-model="formData.telephone" placeholder="请输入座机" style="width: 215px" />
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="formData.email" placeholder="请输入邮箱" />
</el-form-item>
<el-form-item label="QQ" prop="qq">
<el-input v-model="formData.qq" placeholder="请输入QQ" style="width: 215px" />
</el-form-item>
<el-form-item label="微信" prop="webchat">
<el-input v-model="formData.webchat" placeholder="请输入微信" />
</el-form-item>
<el-form-item label="下次联系时间" prop="nextTime">
<el-date-picker
v-model="formData.nextTime"
type="date"
value-format="x"
placeholder="选择下次联系时间"
/>
</el-form-item>
<el-form-item label="地址" prop="address">
<el-input v-model="formData.address" placeholder="请输入地址" />
</el-form-item>
<el-form-item label="直属上级" prop="parentId">
<el-select v-model="formData.parentId" placeholder="请选择">
<el-option
v-for="item in allContactList"
:key="item.id"
:label="item.name"
:value="item.id"
:disabled="item.id == formData.id"
/>
</el-select>
</el-form-item>
<el-form-item label="职位" prop="post">
<el-input v-model="formData.post" placeholder="请输入职位" />
</el-form-item>
<el-form-item label="是否关键决策人" prop="policyMakers" style="width: 400px">
<el-radio-group v-model="formData.policyMakers">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
<OwerSelect
ref="owerRef"
@confirmOwerSelect="owerSelectValue"
:initOwerUser="formData.ownerUserId"
/>
</template>
<script setup lang="ts">
import * as ContactApi from '@/api/crm/contact'
import { DICT_TYPE, getIntDictOptions, getBoolDictOptions } from '@/utils/dict'
import OwerSelect from './OwerSelect.vue'
import * as UserApi from '@/api/system/user'
import * as CustomerApi from '@/api/crm/customer'
import { ElTable } from 'element-plus'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const formType = ref('') // 表单的类型:create - 新增;update - 修改
const formData = ref({
nextTime: undefined,
mobile: undefined,
telephone: undefined,
email: undefined,
customerId: undefined,
customerName: undefined,
address: undefined,
remark: undefined,
ownerUserId: undefined,
lastTime: undefined,
id: undefined,
parentId: undefined,
name: undefined,
post: undefined,
qq: undefined,
webchat: undefined,
sex: undefined,
policyMakers: undefined
})
const loading = ref(true) // 列表的加载中
const total = ref(0) // 列表的总页数
const list = ref([]) // 列表的数据
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
name: null,
mobile: null,
industryId: null,
level: null,
source: null
})
const formRules = reactive({
name: [{ required: true, message: '姓名不能为空', trigger: 'blur' }],
customerId: [{ required: true, message: '客户不能为空', trigger: 'blur' }],
ownerUserId: [{ required: true, message: '负责人不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
const ownerUserList = ref<any[]>([])
const userList = ref<UserApi.UserVO[]>([]) // 用户列表
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
allContactList.value = await ContactApi.simpleAlllist()
resetForm()
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await ContactApi.getContact(id)
userList.value = await UserApi.getSimpleUserList()
await gotOwnerUser(formData.value.ownerUserId)
} finally {
formLoading.value = false
}
}
}
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await CustomerApi.getCustomerPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
const gotOwnerUser = (owerUserId: any) => {
if (owerUserId !== null) {
owerUserId.split(',').forEach((item: string) => {
userList.value.find((user: { id: any }) => {
if (user.id == item) {
ownerUserList.value.push(user)
}
})
})
}
}
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
owerSelectValue(ownerUserList)
// 校验表单
if (!formRef) return
const valid = await formRef.value.validate()
if (!valid) return
// 提交请求
formLoading.value = true
try {
const data = formData.value as unknown as ContactApi.ContactVO
if (formType.value === 'create') {
await ContactApi.createContact(data)
message.success(t('common.createSuccess'))
} else {
await ContactApi.updateContact(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
nextTime: undefined,
mobile: undefined,
telephone: undefined,
email: undefined,
customerId: undefined,
address: undefined,
remark: undefined,
ownerUserId: undefined,
lastTime: undefined,
id: undefined,
parentId: undefined,
name: undefined,
post: undefined,
qq: undefined,
webchat: undefined,
sex: undefined,
policyMakers: undefined
}
formRef.value?.resetFields()
ownerUserList.value = []
}
/** 添加/修改操作 */
const owerRef = ref()
const openOwerForm = (type: string) => {
owerRef.value.open(type, ownerUserList.value)
}
const owerSelectValue = (value) => {
ownerUserList.value = value.value
formData.value.ownerUserId = undefined
value.value.forEach((item, index) => {
if (index != 0) {
formData.value.ownerUserId = formData.value.ownerUserId + ',' + item.id
} else {
formData.value.ownerUserId = item.id
}
})
}
//选择客户
const showCustomer = ref(false)
const openCustomerSelect = () => {
showCustomer.value = !showCustomer.value
queryParams.pageNo = 1
getList()
}
const multipleTableRef = ref<InstanceType<typeof ElTable>>()
const multipleSelection = ref()
const handleSelectionChange = ({}, row) => {
multipleSelection.value = row
multipleTableRef.value!.clearSelection()
multipleTableRef.value!.toggleRowSelection(row, undefined)
}
const selectCustomer = () => {
formData.value.customerId = multipleSelection.value.id
formData.value.customerName = multipleSelection.value.name
showCustomer.value = !showCustomer.value
}
const allContactList = ref([]) //所有联系人列表
onMounted(async () => {
allContactList.value = await ContactApi.simpleAlllist()
})
</script>
+71
View File
@@ -0,0 +1,71 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible" width="600px">
<el-transfer
v-model="value"
:data="data"
:titles="transferTitles"
:props="transferDataProp"
:right-default-checked="[1]"
/>
<el-row justify="end">
<el-col :span="4">
<el-button type="primary" @click="confirmOwerSelect">确认</el-button>
</el-col>
<el-col :span="4">
<el-button type="primary" @click="confirmOwerSelect">取消</el-button>
</el-col>
</el-row>
</Dialog>
</template>
<script setup lang="ts">
import * as UserApi from '@/api/system/user'
import { parseBigInt } from 'jsencrypt/lib/lib/jsbn/jsbn'
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('选择') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const formType = ref('')
const transferTitles = ref(['待选择', '已选择'])
const transferDataProp = ref({
key: 'id',
label: 'nickname'
})
const emit = defineEmits(['confirmOwerSelect'])
const data = ref<UserApi.UserVO[]>([])
const value = ref<any[]>([])
const rightDefaultChecked = ref<any[]>([])
/** 打开弹窗 */
const open = async (type: string, ownerUserList: any[]) => {
dialogVisible.value = true
formType.value = type
// 修改时,设置数据
if (ownerUserList) {
formLoading.value = true
try {
ownerUserList.forEach((item) => {
value.value.push(item.id)
})
} finally {
formLoading.value = false
}
}
rightDefaultChecked.value = []
data.value = await UserApi.getSimpleUserList()
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
const confirmOwerSelect = () => {
const returnData = ref<any[]>([])
data.value.forEach((item) => {
if (value.value.indexOf(item.id) > -1) {
returnData.value.push(item)
}
})
emit('confirmOwerSelect', returnData)
dialogVisible.value = false
value.value = []
}
</script>
<style>
.el-row {
margin-top: 20px;
}
</style>
@@ -0,0 +1,23 @@
<!--
* @Author: zyna
* @Date: 2023-11-11 14:50:11
* @LastEditTime: 2023-11-11 14:52:47
* @FilePath: \yudao-ui-admin-vue3\src\views\crm\contact\detail\ContactBasicInfo.vue
* @Description:
-->
<template>
<el-col>
<el-row>
<span class="text-xl font-bold">{{ contact.name }}</span>
</el-row>
</el-col>
<el-col class="mt-10px">
<!-- TODO 标签 -->
<!-- <Icon icon="ant-design:tag-filled" />-->
</el-col>
</template>
<script setup lang="ts">
import * as ContactApi from '@/api/crm/contact'
const { contact } = defineProps<{ contact: ContactApi.ContactVO }>()
</script>
@@ -0,0 +1,93 @@
<template>
<el-collapse v-model="activeNames">
<el-collapse-item name="basicInfo">
<template #title>
<span class="text-base font-bold">基本信息</span>
</template>
<el-descriptions :column="4">
<el-descriptions-item label="姓名">
{{ contact.name }}
</el-descriptions-item>
<el-descriptions-item label="客户名称">
{{ contact.customerName }}
</el-descriptions-item>
<el-descriptions-item label="手机">
{{ contact.mobile }}
</el-descriptions-item>
<el-descriptions-item label="座机">
{{ contact.telephone }}
</el-descriptions-item>
<el-descriptions-item label="邮箱">
{{ contact.email }}
</el-descriptions-item>
<el-descriptions-item label="QQ">
{{ contact.qq }}
</el-descriptions-item>
<el-descriptions-item label="微信">
{{ contact.webchat }}
</el-descriptions-item>
<el-descriptions-item label="详细地址">
{{ contact.address }}
</el-descriptions-item>
<el-descriptions-item label="下次联系时间">
{{ contact.nextTime ? formatDate(contact.nextTime) : '空' }}
</el-descriptions-item>
<el-descriptions-item label="性别">
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="contact.sex" />
</el-descriptions-item>
<el-descriptions-item label="备注">
{{ contact.remark }}
</el-descriptions-item>
</el-descriptions>
</el-collapse-item>
<el-collapse-item name="systemInfo">
<template #title>
<span class="text-base font-bold">系统信息</span>
</template>
<el-descriptions :column="2">
<el-descriptions-item label="负责人">
{{ gotOwnerUser(contact.ownerUserId) }}
</el-descriptions-item>
<el-descriptions-item label="创建人">
{{ contact.creatorName }}
</el-descriptions-item>
<el-descriptions-item label="创建时间">
{{ contact.createTime ? formatDate(contact.createTime) : '空' }}
</el-descriptions-item>
<el-descriptions-item label="更新时间">
{{ contact.updateTime ? formatDate(contact.updateTime) : '空' }}
</el-descriptions-item>
</el-descriptions>
</el-collapse-item>
</el-collapse>
</template>
<script setup lang="ts">
import * as ContactApi from '@/api/crm/contact'
import { DICT_TYPE } from '@/utils/dict'
import { formatDate } from '@/utils/formatTime'
import * as UserApi from '@/api/system/user'
const { contact } = defineProps<{ contact: ContactApi.ContactVO }>()
// 展示的折叠面板
const activeNames = ref(['basicInfo', 'systemInfo'])
const gotOwnerUser = (owerUserId: string) => {
let ownerName = ''
if (owerUserId !== null && owerUserId != undefined) {
owerUserId.split(',').forEach((item: string, index: number) => {
if (index != 0) {
ownerName =
ownerName + ',' + userList.value.find((user: { id: any }) => user.id == item)?.nickname
} else {
ownerName = userList.value.find((user: { id: any }) => user.id == item)?.nickname || ''
}
})
}
return ownerName
}
const userList = ref<UserApi.UserVO[]>([]) // 用户列表
/** 初始化 **/
onMounted(async () => {
userList.value = await UserApi.getSimpleUserList()
})
</script>
<style scoped lang="scss"></style>
+147
View File
@@ -0,0 +1,147 @@
<template>
<div v-loading="loading">
<div class="flex items-start justify-between">
<div>
<!-- 左上:客户基本信息 -->
<ContactBasicInfo :contact="contact" />
</div>
<div>
<!-- 右上:按钮 -->
<el-button @click="openForm('update', contact.id)" v-hasPermi="['crm:contact:update']">
编辑
</el-button>
</div>
</div>
<el-row class="mt-10px">
<el-button>
<Icon icon="ph:calendar-fill" class="mr-5px" />
创建任务
</el-button>
<el-button>
<Icon icon="carbon:email" class="mr-5px" />
发送邮件
</el-button>
<el-button>
<Icon icon="system-uicons:contacts" class="mr-5px" />
创建联系人
</el-button>
<el-button>
<Icon icon="ep:opportunity" class="mr-5px" />
创建商机
</el-button>
<el-button>
<Icon icon="clarity:contract-line" class="mr-5px" />
创建合同
</el-button>
<el-button>
<Icon icon="icon-park:income-one" class="mr-5px" />
创建回款
</el-button>
<el-button>
<Icon icon="fluent:people-team-add-20-filled" class="mr-5px" />
添加团队成员
</el-button>
</el-row>
</div>
<ContentWrap class="mt-10px">
<el-descriptions :column="5" direction="vertical">
<el-descriptions-item label="客户名称">
{{ contact.customerName }}
</el-descriptions-item>
<el-descriptions-item label="职务">
{{ contact.post }}
</el-descriptions-item>
<el-descriptions-item label="手机">
{{ contact.mobile }}
</el-descriptions-item>
<el-descriptions-item label="创建时间">
{{ contact.createTime ? formatDate(contact.createTime) : '空' }}
</el-descriptions-item>
</el-descriptions>
</ContentWrap>
<!-- TODO wanwan:这个 tab 拉满哈,可以更好看; -->
<el-col :span="18">
<el-tabs>
<el-tab-pane label="详细资料">
<!-- TODO wanwan:这个 ml-2 是不是可以优化下,不要整个左移,而是里面的内容有个几 px 的偏移,不顶在框里 -->
<ContactDetails class="ml-2" :contact="contact" />
</el-tab-pane>
<el-tab-pane label="活动" lazy> 活动</el-tab-pane>
<el-tab-pane label="邮件" lazy> 邮件</el-tab-pane>
<el-tab-pane label="工商信息" lazy> 工商信息</el-tab-pane>
<!-- TODO wanwan 以下标签上的数量需要接口统计返回 -->
<el-tab-pane label="客户" lazy>
<template #label> 客户<el-badge :value="12" class="item" type="primary" /> </template>
客户
</el-tab-pane>
<el-tab-pane label="团队成员" lazy>
<template #label> 团队成员<el-badge :value="2" class="item" type="primary" /> </template>
团队成员
</el-tab-pane>
<el-tab-pane label="商机" lazy> 商机</el-tab-pane>
<el-tab-pane label="合同" lazy>
<template #label> 合同<el-badge :value="3" class="item" type="primary" /> </template>
合同
</el-tab-pane>
<el-tab-pane label="回款" lazy>
<template #label> 回款<el-badge :value="4" class="item" type="primary" /> </template>
回款
</el-tab-pane>
<el-tab-pane label="回访" lazy> 回访</el-tab-pane>
<el-tab-pane label="发票" lazy> 发票</el-tab-pane>
</el-tabs>
</el-col>
<!-- 表单弹窗:添加/修改 -->
<ContactForm ref="formRef" @success="getContactData(id)" />
</template>
<script setup lang="ts">
import { ElMessage } from 'element-plus'
import { useTagsViewStore } from '@/store/modules/tagsView'
import * as ContactApi from '@/api/crm/contact'
import ContactBasicInfo from '@/views/crm/contact/detail/ContactBasicInfo.vue'
import ContactDetails from '@/views/crm/contact/detail/ContactDetails.vue'
import ContactForm from '@/views/crm/contact/ContactForm.vue'
import { formatDate } from '@/utils/formatTime'
import * as CustomerApi from '@/api/crm/customer'
defineOptions({ name: 'ContactDetail' })
const { delView } = useTagsViewStore() // 视图操作
const route = useRoute()
const { currentRoute } = useRouter() // 路由
const id = Number(route.params.id)
const loading = ref(true) // 加载中
// 联系人详情
const contact = ref<ContactApi.ContactVO>({} as ContactApi.ContactVO)
/**
* 获取详情
*
* @param id
*/
const getContactData = async (id: number) => {
loading.value = true
try {
contact.value = await ContactApi.getContact(id)
} finally {
loading.value = false
}
}
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/**
* 初始化
*/
onMounted(async () => {
if (!id) {
ElMessage.warning('参数错误,联系人不能为空!')
delView(unref(currentRoute))
return
}
await getContactData(id)
})
</script>
+333
View File
@@ -0,0 +1,333 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="客户编号" prop="customerId">
<el-input
v-model="queryParams.customerId"
placeholder="请输入客户编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="姓名" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入姓名"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="手机号" prop="mobile">
<el-input
v-model="queryParams.mobile"
placeholder="请输入手机号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="座机" prop="telephone">
<el-input
v-model="queryParams.telephone"
placeholder="请输入电话"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="QQ" prop="qq">
<el-input
v-model="queryParams.qq"
placeholder="请输入QQ"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="微信" prop="webchat">
<el-input
v-model="queryParams.webchat"
placeholder="请输入微信"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="电子邮箱" prop="email">
<el-input
v-model="queryParams.email"
placeholder="请输入电子邮箱"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button type="primary" @click="openForm('create')" v-hasPermi="['crm:contact:create']">
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['crm:contact:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="姓名" fixed="left" align="center" prop="name">
<template #default="scope">
<el-link type="primary" :underline="false" @click="openDetail(scope.row.id)">{{
scope.row.name
}}</el-link>
</template>
</el-table-column>
<el-table-column label="客户名称" fixed="left" align="center" prop="customerName" />
<el-table-column label="性别" align="center" prop="sex">
<template #default="scope">
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
</template>
</el-table-column>
<el-table-column label="职位" align="center" prop="post" />
<el-table-column label="是否关键决策人" align="center" prop="policyMakers">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.policyMakers" />
</template>
</el-table-column>
<el-table-column label="直属上级" align="center" prop="parentId">
<template #default="scope">
{{ allContactList.find((contact) => contact.id === scope.row.parentId)?.name }}
</template>
</el-table-column>
<el-table-column label="手机号" align="center" prop="mobile" />
<el-table-column label="座机" align="center" prop="telephone" />
<el-table-column label="QQ" align="center" prop="qq" />
<el-table-column label="微信" align="center" prop="webchat" />
<el-table-column label="邮箱" align="center" prop="email" />
<el-table-column label="地址" align="center" prop="address" />
<el-table-column
label="下次联系时间"
align="center"
prop="nextTime"
width="180px"
:formatter="dateFormatter"
/>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column
label="最后跟进时间"
align="center"
prop="lastTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="负责人" align="center" prop="ownerUserId">
<template #default="scope">
{{ gotOwnerUser(scope.row.ownerUserId) }}
</template>
</el-table-column>
<!-- <el-table-column label="所属部门" align="center" prop="ownerUserId" /> -->
<el-table-column
label="更新时间"
align="center"
prop="updateTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<!-- <el-table-column
label="创建人"
align="center"
prop="creator"
:formatter="dateFormatter"
width="180px"
>
<template #default="scope">
{{ userList.find((user) => user.id === scope.row.creator)?.nickname }}
</template>
</el-table-column> -->
<el-table-column label="操作" align="center" fixed="right" width="200">
<template #default="scope">
<el-button
plain
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['crm:contact:update']"
>
编辑
</el-button>
<el-button
plain
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['crm:contact:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<ContactForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import * as ContactApi from '@/api/crm/contact'
import ContactForm from './ContactForm.vue'
import { DICT_TYPE } from '@/utils/dict'
import * as UserApi from '@/api/system/user'
import * as CustomerApi from '@/api/crm/customer'
defineOptions({ name: 'CrmContact' })
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const loading = ref(true) // 列表的加载中
const total = ref(0) // 列表的总页数
const list = ref([]) // 列表的数据
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
nextTime: [],
mobile: null,
telephone: null,
email: null,
customerId: null,
address: null,
remark: null,
ownerUserId: null,
createTime: [],
lastTime: [],
parentId: null,
name: null,
post: null,
qq: null,
webchat: null,
sex: null,
policyMakers: null
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中
const userList = ref<UserApi.UserVO[]>([]) // 用户列表
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await ContactApi.getContactPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await ContactApi.deleteContact(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
// 导出的二次确认
await message.exportConfirm()
// 发起导出
exportLoading.value = true
const data = await ContactApi.exportContact(queryParams)
download.excel(data, '联系人.xls')
} catch {
} finally {
exportLoading.value = false
}
}
const gotOwnerUser = (owerUserId: string) => {
let ownerName = ''
if (owerUserId !== null) {
owerUserId.split(',').forEach((item: string, index: number) => {
if (index != 0) {
ownerName =
ownerName + ',' + userList.value.find((user: { id: any }) => user.id == item)?.nickname
} else {
ownerName = userList.value.find((user: { id: any }) => user.id == item)?.nickname || ''
}
})
}
return ownerName
}
/** 详情页面 */
/** 打开客户详情 */
const { push } = useRouter()
const openDetail = (id: number) => {
push({ name: 'CrmContactDetail', params: { id } })
}
const allContactList = ref([]) //所有联系人列表
const allCustomerList = ref([]) //客户列表
/** 初始化 **/
onMounted(async () => {
await getList()
userList.value = await UserApi.getSimpleUserList()
allContactList.value = await ContactApi.simpleAlllist()
})
</script>
+1 -1
View File
@@ -8,7 +8,7 @@
<colum-info-form ref="columInfoRef" :columns="formData.columns" />
</el-tab-pane>
<el-tab-pane label="生成信息" name="generateInfo">
<generate-info-form ref="generateInfoRef" :table="formData.table" />
<generate-info-form ref="generateInfoRef" :table="formData.table" :columns="formData.columns" />
</el-tab-pane>
</el-tabs>
<el-form>
+1 -1
View File
@@ -20,8 +20,8 @@
ref="treeRef"
:data="preview.fileTree"
:expand-on-click-node="false"
highlight-current
default-expand-all
highlight-current
node-key="id"
@node-click="handleNodeClick"
/>
@@ -3,7 +3,7 @@
<el-row>
<el-col :span="12">
<el-form-item label="生成模板" prop="templateType">
<el-select v-model="formData.templateType" @change="tplSelectChange">
<el-select v-model="formData.templateType">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.INFRA_CODEGEN_TEMPLATE_TYPE)"
:key="dict.value"
@@ -182,50 +182,33 @@
</el-col>
</el-row>
<el-row v-show="formData.tplCategory === 'tree'">
<h4 class="form-header">其他信息</h4>
<el-col :span="12">
<el-form-item>
<template #label>
<span>
树编码字段
<el-tooltip content="树显示的编码字段名, 如:dept_id" placement="top">
<Icon icon="ep:question-filled" />
</el-tooltip>
</span>
</template>
<el-select v-model="formData.treeCode" placeholder="请选择">
<el-option
v-for="(column, index) in formData.columns"
:key="index"
:label="column.columnName + ':' + column.columnComment"
:value="column.columnName"
/>
</el-select>
</el-form-item>
<!-- 树表信息 -->
<el-row v-if="formData.templateType == 2">
<el-col :span="24">
<h4 class="form-header">树表信息</h4>
</el-col>
<el-col :span="12">
<el-form-item>
<el-form-item prop="treeParentColumnId">
<template #label>
<span>
树父编码字段
父编号字段
<el-tooltip content="树显示的父编码字段名, 如:parent_Id" placement="top">
<Icon icon="ep:question-filled" />
</el-tooltip>
</span>
</template>
<el-select v-model="formData.treeParentCode" placeholder="请选择">
<el-select v-model="formData.treeParentColumnId" placeholder="请选择">
<el-option
v-for="(column, index) in formData.columns"
v-for="(column, index) in props.columns"
:key="index"
:label="column.columnName + ':' + column.columnComment"
:value="column.columnName"
:value="column.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item>
<el-form-item prop="treeNameColumnId">
<template #label>
<span>
树名称字段
@@ -234,60 +217,79 @@
</el-tooltip>
</span>
</template>
<el-select v-model="formData.treeName" placeholder="请选择">
<el-select v-model="formData.treeNameColumnId" placeholder="请选择">
<el-option
v-for="(column, index) in formData.columns"
v-for="(column, index) in props.columns"
:key="index"
:label="column.columnName + ':' + column.columnComment"
:value="column.columnName"
:value="column.id"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row v-show="formData.tplCategory === 'sub'">
<h4 class="form-header">关联信息</h4>
<!-- 主表信息 -->
<el-row v-if="formData.templateType == 15">
<el-col :span="24">
<h4 class="form-header">主表信息</h4>
</el-col>
<el-col :span="12">
<el-form-item>
<el-form-item prop="masterTableId">
<template #label>
<span>
关联子表的表名
<el-tooltip content="关联子表的表名, 如:sys_user" placement="top">
关联的主表
<el-tooltip content="关联主表(父表)的表名, 如:system_user" placement="top">
<Icon icon="ep:question-filled" />
</el-tooltip>
</span>
</template>
<el-select v-model="formData.subTableName" placeholder="请选择" @change="subSelectChange">
<el-select v-model="formData.masterTableId" placeholder="请选择">
<el-option
v-for="(table0, index) in tables"
:key="index"
:label="table0.tableName + ':' + table0.tableComment"
:value="table0.tableName"
:value="table0.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item>
<el-form-item prop="subJoinColumnId">
<template #label>
<span>
子表关联的外键名
<el-tooltip content="子表关联的外键名, 如:user_id" placement="top">
子表关联的字段
<el-tooltip content="子表关联的字段, 如:user_id" placement="top">
<Icon icon="ep:question-filled" />
</el-tooltip>
</span>
</template>
<el-select v-model="formData.subTableFkName" placeholder="请选择">
<el-select v-model="formData.subJoinColumnId" placeholder="请选择">
<el-option
v-for="(column, index) in subColumns"
v-for="(column, index) in props.columns"
:key="index"
:label="column.columnName + ':' + column.columnComment"
:value="column.columnName"
:value="column.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="subJoinMany">
<template #label>
<span>
关联关系
<el-tooltip content="主表与子表的关联关系" placement="top">
<Icon icon="ep:question-filled" />
</el-tooltip>
</span>
</template>
<el-radio-group v-model="formData.subJoinMany" placeholder="请选择">
<el-radio :label="true">一对多</el-radio>
<el-radio :label="false">一对一</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
@@ -305,6 +307,10 @@ const props = defineProps({
table: {
type: Object as PropType<Nullable<CodegenApi.CodegenTableVO>>,
default: () => null
},
columns: {
type: Array as unknown as PropType<CodegenApi.CodegenColumnVO[]>,
default: () => null
}
})
@@ -319,13 +325,12 @@ const formData = ref({
classComment: '',
parentMenuId: null,
genPath: '',
treeCode: '',
treeParentCode: '',
treeName: '',
tplCategory: '',
subTableName: '',
subTableFkName: '',
genType: ''
genType: '',
masterTableId: undefined,
subJoinColumnId: undefined,
subJoinMany: undefined,
treeParentColumnId: undefined,
treeNameColumnId: undefined
})
const rules = reactive({
@@ -336,41 +341,29 @@ const rules = reactive({
businessName: [required],
businessPackage: [required],
className: [required],
classComment: [required]
classComment: [required],
masterTableId: [required],
subJoinColumnId: [required],
subJoinMany: [required],
treeParentColumnId: [required],
treeNameColumnId: [required]
})
const tables = ref([])
const subColumns = ref([])
const tables = ref([]) // 表定义列表
const menus = ref<any[]>([])
const menuTreeProps = {
label: 'name'
}
/** 选择子表名触发 */
const subSelectChange = () => {
formData.value.subTableFkName = ''
}
/** 选择生成模板触发 */
const tplSelectChange = (value) => {
if (value !== 1) {
// TODO 芋艿:暂时不考虑支持树形结构
message.error(
'暂时不考虑支持【树形】和【主子表】的代码生成。原因是:导致 vm 模板过于复杂,不利于胖友二次开发'
)
return false
}
if (value !== 'sub') {
formData.value.subTableName = ''
formData.value.subTableFkName = ''
}
}
watch(
() => props.table,
(table) => {
async (table) => {
if (!table) return
formData.value = table as any
// 加载表列表
if (table.dataSourceConfigId >= 0) {
tables.value = await CodegenApi.getCodegenTableList(formData.value.dataSourceConfigId)
}
},
{
deep: true,
@@ -380,6 +373,7 @@ watch(
onMounted(async () => {
try {
// 加载菜单
const resp = await MenuApi.getSimpleMenusList()
menus.value = handleTree(resp)
} catch {}
+3 -1
View File
@@ -1,5 +1,7 @@
<template>
<doc-alert title="代码生成" url="https://doc.iocoder.cn/new-feature/" />
<doc-alert title="代码生成(单表)" url="https://doc.iocoder.cn/new-feature/" />
<doc-alert title="代码生成(树表)" url="https://doc.iocoder.cn/new-feature/tree/" />
<doc-alert title="代码生成(主子表)" url="https://doc.iocoder.cn/new-feature/master-sub/" />
<doc-alert title="单元测试" url="https://doc.iocoder.cn/unit-test/" />
<!-- 搜索 -->
@@ -0,0 +1,126 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="名字" prop="name">
<el-input v-model="formData.name" placeholder="请输入名字" />
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-radio-group v-model="formData.sex">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="出生年" prop="birthday">
<el-date-picker
v-model="formData.birthday"
type="date"
value-format="x"
placeholder="选择出生年"
/>
</el-form-item>
<el-form-item label="简介" prop="description">
<Editor v-model="formData.description" height="150px" />
</el-form-item>
<el-form-item label="头像" prop="avatar">
<UploadImg v-model="formData.avatar" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import * as Demo01ContactApi from '@/api/infra/demo/demo01'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const formType = ref('') // 表单的类型:create - 新增;update - 修改
const formData = ref({
id: undefined,
name: undefined,
sex: undefined,
birthday: undefined,
description: undefined,
avatar: undefined
})
const formRules = reactive({
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
sex: [{ required: true, message: '性别不能为空', trigger: 'blur' }],
birthday: [{ required: true, message: '出生年不能为空', trigger: 'blur' }],
description: [{ required: true, message: '简介不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await Demo01ContactApi.getDemo01Contact(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
// 提交请求
formLoading.value = true
try {
const data = formData.value as unknown as Demo01ContactApi.Demo01ContactVO
if (formType.value === 'create') {
await Demo01ContactApi.createDemo01Contact(data)
message.success(t('common.createSuccess'))
} else {
await Demo01ContactApi.updateDemo01Contact(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
name: undefined,
sex: undefined,
birthday: undefined,
description: undefined,
avatar: undefined
}
formRef.value?.resetFields()
}
</script>
+214
View File
@@ -0,0 +1,214 @@
<template>
<doc-alert title="代码生成(单表)" url="https://doc.iocoder.cn/new-feature/" />
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="名字" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入名字"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-select v-model="queryParams.sex" placeholder="请选择性别" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['infra:demo01-contact:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['infra:demo01-contact:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="性别" align="center" prop="sex">
<template #default="scope">
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
</template>
</el-table-column>
<el-table-column
label="出生年"
align="center"
prop="birthday"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="简介" align="center" prop="description" />
<el-table-column label="头像" align="center" prop="avatar" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['infra:demo01-contact:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['infra:demo01-contact:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<Demo01ContactForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import * as Demo01ContactApi from '@/api/infra/demo/demo01'
import Demo01ContactForm from './Demo01ContactForm.vue'
defineOptions({ name: 'Demo01Contact' })
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const loading = ref(true) // 列表的加载中
const list = ref([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
name: null,
sex: null,
createTime: []
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await Demo01ContactApi.getDemo01ContactPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await Demo01ContactApi.deleteDemo01Contact(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
// 导出的二次确认
await message.exportConfirm()
// 发起导出
exportLoading.value = true
const data = await Demo01ContactApi.exportDemo01Contact(queryParams)
download.excel(data, '示例联系人.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>
@@ -0,0 +1,114 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="名字" prop="name">
<el-input v-model="formData.name" placeholder="请输入名字" />
</el-form-item>
<el-form-item label="父级编号" prop="parentId">
<el-tree-select
v-model="formData.parentId"
:data="demo02CategoryTree"
:props="defaultProps"
check-strictly
default-expand-all
placeholder="请选择父级编号"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import * as Demo02CategoryApi from '@/api/infra/demo/demo02'
import { defaultProps, handleTree } from '@/utils/tree'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const formType = ref('') // 表单的类型:create - 新增;update - 修改
const formData = ref({
id: undefined,
name: undefined,
parentId: undefined
})
const formRules = reactive({
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
parentId: [{ required: true, message: '父级编号不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
const demo02CategoryTree = ref() // 树形结构
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await Demo02CategoryApi.getDemo02Category(id)
} finally {
formLoading.value = false
}
}
await getDemo02CategoryTree()
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
// 提交请求
formLoading.value = true
try {
const data = formData.value as unknown as Demo02CategoryApi.Demo02CategoryVO
if (formType.value === 'create') {
await Demo02CategoryApi.createDemo02Category(data)
message.success(t('common.createSuccess'))
} else {
await Demo02CategoryApi.updateDemo02Category(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
name: undefined,
parentId: undefined
}
formRef.value?.resetFields()
}
/** 获得示例分类树 */
const getDemo02CategoryTree = async () => {
demo02CategoryTree.value = []
const data = await Demo02CategoryApi.getDemo02CategoryList()
const root: Tree = { id: 0, name: '顶级示例分类', children: [] }
root.children = handleTree(data, 'id', 'parentId')
demo02CategoryTree.value.push(root)
}
</script>
+207
View File
@@ -0,0 +1,207 @@
<template>
<doc-alert title="代码生成(树表)" url="https://doc.iocoder.cn/new-feature/tree/" />
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="名字" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入名字"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['infra:demo02-category:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['infra:demo02-category:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button type="danger" plain @click="toggleExpandAll">
<Icon icon="ep:sort" class="mr-5px" /> 展开/折叠
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
row-key="id"
:default-expand-all="isExpandAll"
v-if="refreshTable"
>
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="名字" align="center" prop="name" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['infra:demo02-category:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['infra:demo02-category:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<Demo02CategoryForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import { handleTree } from '@/utils/tree'
import download from '@/utils/download'
import * as Demo02CategoryApi from '@/api/infra/demo/demo02'
import Demo02CategoryForm from './Demo02CategoryForm.vue'
defineOptions({ name: 'Demo02Category' })
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const loading = ref(true) // 列表的加载中
const list = ref([]) // 列表的数据
const queryParams = reactive({
name: null,
parentId: null,
createTime: []
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await Demo02CategoryApi.getDemo02CategoryList(queryParams)
list.value = handleTree(data, 'id', 'parentId')
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await Demo02CategoryApi.deleteDemo02Category(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
// 导出的二次确认
await message.exportConfirm()
// 发起导出
exportLoading.value = true
const data = await Demo02CategoryApi.exportDemo02Category(queryParams)
download.excel(data, '示例分类.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 展开/折叠操作 */
const isExpandAll = ref(true) // 是否展开,默认全部展开
const refreshTable = ref(true) // 重新渲染表格状态
const toggleExpandAll = async () => {
refreshTable.value = false
isExpandAll.value = !isExpandAll.value
await nextTick()
refreshTable.value = true
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>
@@ -0,0 +1,121 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="名字" prop="name">
<el-input v-model="formData.name" placeholder="请输入名字" />
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-radio-group v-model="formData.sex">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="出生日期" prop="birthday">
<el-date-picker
v-model="formData.birthday"
type="date"
value-format="x"
placeholder="选择出生日期"
/>
</el-form-item>
<el-form-item label="简介" prop="description">
<Editor v-model="formData.description" height="150px" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import * as Demo03StudentApi from '@/api/infra/demo/demo03/erp'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const formType = ref('') // 表单的类型:create - 新增;update - 修改
const formData = ref({
id: undefined,
name: undefined,
sex: undefined,
birthday: undefined,
description: undefined
})
const formRules = reactive({
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
sex: [{ required: true, message: '性别不能为空', trigger: 'blur' }],
birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
description: [{ required: true, message: '简介不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await Demo03StudentApi.getDemo03Student(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
// 提交请求
formLoading.value = true
try {
const data = formData.value as unknown as Demo03StudentApi.Demo03StudentVO
if (formType.value === 'create') {
await Demo03StudentApi.createDemo03Student(data)
message.success(t('common.createSuccess'))
} else {
await Demo03StudentApi.updateDemo03Student(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
name: undefined,
sex: undefined,
birthday: undefined,
description: undefined
}
formRef.value?.resetFields()
}
</script>
@@ -0,0 +1,99 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="名字" prop="name">
<el-input v-model="formData.name" placeholder="请输入名字" />
</el-form-item>
<el-form-item label="分数" prop="score">
<el-input v-model="formData.score" placeholder="请输入分数" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import * as Demo03StudentApi from '@/api/infra/demo/demo03/erp'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const formType = ref('') // 表单的类型:create - 新增;update - 修改
const formData = ref({
id: undefined,
studentId: undefined,
name: undefined,
score: undefined
})
const formRules = reactive({
studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
score: [{ required: true, message: '分数不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
/** 打开弹窗 */
const open = async (type: string, id?: number, studentId: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
formData.value.studentId = studentId
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await Demo03StudentApi.getDemo03Course(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
// 提交请求
formLoading.value = true
try {
const data = formData.value
if (formType.value === 'create') {
await Demo03StudentApi.createDemo03Course(data)
message.success(t('common.createSuccess'))
} else {
await Demo03StudentApi.updateDemo03Course(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
studentId: undefined,
name: undefined,
score: undefined
}
formRef.value?.resetFields()
}
</script>
@@ -0,0 +1,126 @@
<template>
<!-- 列表 -->
<ContentWrap>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['infra:demo03-student:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="分数" align="center" prop="score" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['infra:demo03-student:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['infra:demo03-student:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<Demo03CourseForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import * as Demo03StudentApi from '@/api/infra/demo/demo03/erp'
import Demo03CourseForm from './Demo03CourseForm.vue'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const props = defineProps<{
studentId: undefined // 学生编号(主表的关联字段)
}>()
const loading = ref(false) // 列表的加载中
const list = ref([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
studentId: undefined
})
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.studentId,
(val) => {
queryParams.studentId = val
handleQuery()
},
{ immediate: false }
)
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await Demo03StudentApi.getDemo03CoursePage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
if (!props.studentId) {
message.error('请选择一个学生')
return
}
formRef.value.open(type, id, props.studentId)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await Demo03StudentApi.deleteDemo03Course(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
} catch {}
}
</script>
@@ -0,0 +1,99 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="名字" prop="name">
<el-input v-model="formData.name" placeholder="请输入名字" />
</el-form-item>
<el-form-item label="班主任" prop="teacher">
<el-input v-model="formData.teacher" placeholder="请输入班主任" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import * as Demo03StudentApi from '@/api/infra/demo/demo03/erp'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const formType = ref('') // 表单的类型:create - 新增;update - 修改
const formData = ref({
id: undefined,
studentId: undefined,
name: undefined,
teacher: undefined
})
const formRules = reactive({
studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
teacher: [{ required: true, message: '班主任不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
/** 打开弹窗 */
const open = async (type: string, id?: number, studentId: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
formData.value.studentId = studentId
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await Demo03StudentApi.getDemo03Grade(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
// 提交请求
formLoading.value = true
try {
const data = formData.value
if (formType.value === 'create') {
await Demo03StudentApi.createDemo03Grade(data)
message.success(t('common.createSuccess'))
} else {
await Demo03StudentApi.updateDemo03Grade(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
studentId: undefined,
name: undefined,
teacher: undefined
}
formRef.value?.resetFields()
}
</script>
@@ -0,0 +1,126 @@
<template>
<!-- 列表 -->
<ContentWrap>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['infra:demo03-student:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="班主任" align="center" prop="teacher" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['infra:demo03-student:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['infra:demo03-student:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<Demo03GradeForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import * as Demo03StudentApi from '@/api/infra/demo/demo03/erp'
import Demo03GradeForm from './Demo03GradeForm.vue'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const props = defineProps<{
studentId: undefined // 学生编号(主表的关联字段)
}>()
const loading = ref(false) // 列表的加载中
const list = ref([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
studentId: undefined
})
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.studentId,
(val) => {
queryParams.studentId = val
handleQuery()
},
{ immediate: false }
)
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await Demo03StudentApi.getDemo03GradePage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
if (!props.studentId) {
message.error('请选择一个学生')
return
}
formRef.value.open(type, id, props.studentId)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await Demo03StudentApi.deleteDemo03Grade(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
} catch {}
}
</script>
+240
View File
@@ -0,0 +1,240 @@
<template>
<doc-alert title="代码生成(主子表)" url="https://doc.iocoder.cn/new-feature/master-sub/" />
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="名字" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入名字"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-select v-model="queryParams.sex" placeholder="请选择性别" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['infra:demo03-student:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['infra:demo03-student:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
highlight-current-row
@current-change="handleCurrentChange"
>
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="性别" align="center" prop="sex">
<template #default="scope">
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
</template>
</el-table-column>
<el-table-column
label="出生日期"
align="center"
prop="birthday"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="简介" align="center" prop="description" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['infra:demo03-student:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['infra:demo03-student:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<Demo03StudentForm ref="formRef" @success="getList" />
<!-- 子表的列表 -->
<ContentWrap>
<el-tabs model-value="demo03Course">
<el-tab-pane label="学生课程" name="demo03Course">
<Demo03CourseList :student-id="currentRow.id" />
</el-tab-pane>
<el-tab-pane label="学生班级" name="demo03Grade">
<Demo03GradeList :student-id="currentRow.id" />
</el-tab-pane>
</el-tabs>
</ContentWrap>
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import * as Demo03StudentApi from '@/api/infra/demo/demo03/erp'
import Demo03StudentForm from './Demo03StudentForm.vue'
import Demo03CourseList from './components/Demo03CourseList.vue'
import Demo03GradeList from './components/Demo03GradeList.vue'
defineOptions({ name: 'Demo03Student' })
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const loading = ref(true) // 列表的加载中
const list = ref([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
name: null,
sex: null,
description: null,
createTime: []
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await Demo03StudentApi.getDemo03StudentPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await Demo03StudentApi.deleteDemo03Student(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
// 导出的二次确认
await message.exportConfirm()
// 发起导出
exportLoading.value = true
const data = await Demo03StudentApi.exportDemo03Student(queryParams)
download.excel(data, '学生.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 选中行操作 */
const currentRow = ref({}) // 选中行
const handleCurrentChange = (row) => {
currentRow.value = row
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>
@@ -0,0 +1,153 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="名字" prop="name">
<el-input v-model="formData.name" placeholder="请输入名字" />
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-radio-group v-model="formData.sex">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="出生日期" prop="birthday">
<el-date-picker
v-model="formData.birthday"
type="date"
value-format="x"
placeholder="选择出生日期"
/>
</el-form-item>
<el-form-item label="简介" prop="description">
<Editor v-model="formData.description" height="150px" />
</el-form-item>
</el-form>
<!-- 子表的表单 -->
<el-tabs v-model="subTabsName">
<el-tab-pane label="学生课程" name="demo03Course">
<Demo03CourseForm ref="demo03CourseFormRef" :student-id="formData.id" />
</el-tab-pane>
<el-tab-pane label="学生班级" name="demo03Grade">
<Demo03GradeForm ref="demo03GradeFormRef" :student-id="formData.id" />
</el-tab-pane>
</el-tabs>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import * as Demo03StudentApi from '@/api/infra/demo/demo03/inner'
import Demo03CourseForm from './components/Demo03CourseForm.vue'
import Demo03GradeForm from './components/Demo03GradeForm.vue'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const formType = ref('') // 表单的类型:create - 新增;update - 修改
const formData = ref({
id: undefined,
name: undefined,
sex: undefined,
birthday: undefined,
description: undefined
})
const formRules = reactive({
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
sex: [{ required: true, message: '性别不能为空', trigger: 'blur' }],
birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
description: [{ required: true, message: '简介不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
/** 子表的表单 */
const subTabsName = ref('demo03Course')
const demo03CourseFormRef = ref()
const demo03GradeFormRef = ref()
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await Demo03StudentApi.getDemo03Student(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
// 校验子表单
try {
await demo03CourseFormRef.value.validate()
} catch (e) {
subTabsName.value = 'demo03Course'
return
}
try {
await demo03GradeFormRef.value.validate()
} catch (e) {
subTabsName.value = 'demo03Grade'
return
}
// 提交请求
formLoading.value = true
try {
const data = formData.value as unknown as Demo03StudentApi.Demo03StudentVO
// 拼接子表的数据
data.demo03Courses = demo03CourseFormRef.value.getData()
data.demo03Grade = demo03GradeFormRef.value.getData()
if (formType.value === 'create') {
await Demo03StudentApi.createDemo03Student(data)
message.success(t('common.createSuccess'))
} else {
await Demo03StudentApi.updateDemo03Student(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
name: undefined,
sex: undefined,
birthday: undefined,
description: undefined
}
formRef.value?.resetFields()
}
</script>
@@ -0,0 +1,100 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-width="0px"
:inline-message="true"
>
<el-table :data="formData" class="-mt-10px">
<el-table-column label="序号" type="index" width="100" />
<el-table-column label="名字" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.name`" :rules="formRules.name" class="mb-0px!">
<el-input v-model="row.name" placeholder="请输入名字" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="分数" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.score`" :rules="formRules.score" class="mb-0px!">
<el-input v-model="row.score" placeholder="请输入分数" />
</el-form-item>
</template>
</el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60">
<template #default="{ $index }">
<el-button @click="handleDelete($index)" link>—</el-button>
</template>
</el-table-column>
</el-table>
</el-form>
<el-row justify="center" class="mt-3">
<el-button @click="handleAdd" round>+ 添加学生课程</el-button>
</el-row>
</template>
<script setup lang="ts">
import * as Demo03StudentApi from '@/api/infra/demo/demo03/inner'
const props = defineProps<{
studentId: undefined // 学生编号(主表的关联字段)
}>()
const formLoading = ref(false) // 表单的加载中
const formData = ref([])
const formRules = reactive({
studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
score: [{ required: true, message: '分数不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.studentId,
async (val) => {
// 1. 重置表单
formData.value = []
// 2. val 非空,则加载数据
if (!val) {
return;
}
try {
formLoading.value = true
formData.value = await Demo03StudentApi.getDemo03CourseListByStudentId(val)
} finally {
formLoading.value = false
}
},
{ immediate: true }
)
/** 新增按钮操作 */
const handleAdd = () => {
const row = {
id: undefined,
studentId: undefined,
name: undefined,
score: undefined
}
row.studentId = props.studentId
formData.value.push(row)
}
/** 删除按钮操作 */
const handleDelete = (index) => {
formData.value.splice(index, 1)
}
/** 表单校验 */
const validate = () => {
return formRef.value.validate()
}
/** 表单值 */
const getData = () => {
return formData.value
}
defineExpose({ validate, getData })
</script>
@@ -0,0 +1,51 @@
<template>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="分数" align="center" prop="score" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
</el-table>
</ContentWrap>
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import * as Demo03StudentApi from '@/api/infra/demo/demo03/inner'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const props = defineProps<{
studentId: undefined // 学生编号(主表的关联字段)
}>()
const loading = ref(false) // 列表的加载中
const list = ref([]) // 列表的数据
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
list.value = await Demo03StudentApi.getDemo03CourseListByStudentId(props.studentId)
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>
@@ -0,0 +1,72 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="名字" prop="name">
<el-input v-model="formData.name" placeholder="请输入名字" />
</el-form-item>
<el-form-item label="班主任" prop="teacher">
<el-input v-model="formData.teacher" placeholder="请输入班主任" />
</el-form-item>
</el-form>
</template>
<script setup lang="ts">
import * as Demo03StudentApi from '@/api/infra/demo/demo03/inner'
const props = defineProps<{
studentId: undefined // 学生编号(主表的关联字段)
}>()
const formLoading = ref(false) // 表单的加载中
const formData = ref([])
const formRules = reactive({
studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
teacher: [{ required: true, message: '班主任不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.studentId,
async (val) => {
// 1. 重置表单
formData.value = {
id: undefined,
studentId: undefined,
name: undefined,
teacher: undefined,
}
// 2. val 非空,则加载数据
if (!val) {
return;
}
try {
formLoading.value = true
const data = await Demo03StudentApi.getDemo03GradeByStudentId(val)
if (!data) {
return
}
formData.value = data
} finally {
formLoading.value = false
}
},
{ immediate: true }
)
/** 表单校验 */
const validate = () => {
return formRef.value.validate()
}
/** 表单值 */
const getData = () => {
return formData.value
}
defineExpose({ validate, getData })
</script>
@@ -0,0 +1,55 @@
<template>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="班主任" align="center" prop="teacher" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
</el-table>
</ContentWrap>
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import * as Demo03StudentApi from '@/api/infra/demo/demo03/inner'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const props = defineProps<{
studentId: undefined // 学生编号(主表的关联字段)
}>()
const loading = ref(false) // 列表的加载中
const list = ref([]) // 列表的数据
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await Demo03StudentApi.getDemo03GradeByStudentId(props.studentId)
if (!data) {
return
}
list.value.push(data)
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>
+229
View File
@@ -0,0 +1,229 @@
<template>
<doc-alert title="代码生成(主子表)" url="https://doc.iocoder.cn/new-feature/master-sub/" />
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="名字" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入名字"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-select v-model="queryParams.sex" placeholder="请选择性别" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['infra:demo03-student:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['infra:demo03-student:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<!-- 子表的列表 -->
<el-table-column type="expand">
<template #default="scope">
<el-tabs model-value="demo03Course">
<el-tab-pane label="学生课程" name="demo03Course">
<Demo03CourseList :student-id="scope.row.id" />
</el-tab-pane>
<el-tab-pane label="学生班级" name="demo03Grade">
<Demo03GradeList :student-id="scope.row.id" />
</el-tab-pane>
</el-tabs>
</template>
</el-table-column>
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="性别" align="center" prop="sex">
<template #default="scope">
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
</template>
</el-table-column>
<el-table-column
label="出生日期"
align="center"
prop="birthday"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="简介" align="center" prop="description" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['infra:demo03-student:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['infra:demo03-student:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<Demo03StudentForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import * as Demo03StudentApi from '@/api/infra/demo/demo03/inner'
import Demo03StudentForm from './Demo03StudentForm.vue'
import Demo03CourseList from './components/Demo03CourseList.vue'
import Demo03GradeList from './components/Demo03GradeList.vue'
defineOptions({ name: 'Demo03Student' })
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const loading = ref(true) // 列表的加载中
const list = ref([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
name: null,
sex: null,
description: null,
createTime: []
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await Demo03StudentApi.getDemo03StudentPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await Demo03StudentApi.deleteDemo03Student(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
// 导出的二次确认
await message.exportConfirm()
// 发起导出
exportLoading.value = true
const data = await Demo03StudentApi.exportDemo03Student(queryParams)
download.excel(data, '学生.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>
@@ -0,0 +1,153 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="名字" prop="name">
<el-input v-model="formData.name" placeholder="请输入名字" />
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-radio-group v-model="formData.sex">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="出生日期" prop="birthday">
<el-date-picker
v-model="formData.birthday"
type="date"
value-format="x"
placeholder="选择出生日期"
/>
</el-form-item>
<el-form-item label="简介" prop="description">
<Editor v-model="formData.description" height="150px" />
</el-form-item>
</el-form>
<!-- 子表的表单 -->
<el-tabs v-model="subTabsName">
<el-tab-pane label="学生课程" name="demo03Course">
<Demo03CourseForm ref="demo03CourseFormRef" :student-id="formData.id" />
</el-tab-pane>
<el-tab-pane label="学生班级" name="demo03Grade">
<Demo03GradeForm ref="demo03GradeFormRef" :student-id="formData.id" />
</el-tab-pane>
</el-tabs>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import * as Demo03StudentApi from '@/api/infra/demo/demo03/normal'
import Demo03CourseForm from './components/Demo03CourseForm.vue'
import Demo03GradeForm from './components/Demo03GradeForm.vue'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const formType = ref('') // 表单的类型:create - 新增;update - 修改
const formData = ref({
id: undefined,
name: undefined,
sex: undefined,
birthday: undefined,
description: undefined
})
const formRules = reactive({
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
sex: [{ required: true, message: '性别不能为空', trigger: 'blur' }],
birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
description: [{ required: true, message: '简介不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
/** 子表的表单 */
const subTabsName = ref('demo03Course')
const demo03CourseFormRef = ref()
const demo03GradeFormRef = ref()
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await Demo03StudentApi.getDemo03Student(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
// 校验子表单
try {
await demo03CourseFormRef.value.validate()
} catch (e) {
subTabsName.value = 'demo03Course'
return
}
try {
await demo03GradeFormRef.value.validate()
} catch (e) {
subTabsName.value = 'demo03Grade'
return
}
// 提交请求
formLoading.value = true
try {
const data = formData.value as unknown as Demo03StudentApi.Demo03StudentVO
// 拼接子表的数据
data.demo03Courses = demo03CourseFormRef.value.getData()
data.demo03Grade = demo03GradeFormRef.value.getData()
if (formType.value === 'create') {
await Demo03StudentApi.createDemo03Student(data)
message.success(t('common.createSuccess'))
} else {
await Demo03StudentApi.updateDemo03Student(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
name: undefined,
sex: undefined,
birthday: undefined,
description: undefined
}
formRef.value?.resetFields()
}
</script>
@@ -0,0 +1,100 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-width="0px"
:inline-message="true"
>
<el-table :data="formData" class="-mt-10px">
<el-table-column label="序号" type="index" width="100" />
<el-table-column label="名字" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.name`" :rules="formRules.name" class="mb-0px!">
<el-input v-model="row.name" placeholder="请输入名字" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="分数" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.score`" :rules="formRules.score" class="mb-0px!">
<el-input v-model="row.score" placeholder="请输入分数" />
</el-form-item>
</template>
</el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60">
<template #default="{ $index }">
<el-button @click="handleDelete($index)" link>—</el-button>
</template>
</el-table-column>
</el-table>
</el-form>
<el-row justify="center" class="mt-3">
<el-button @click="handleAdd" round>+ 添加学生课程</el-button>
</el-row>
</template>
<script setup lang="ts">
import * as Demo03StudentApi from '@/api/infra/demo/demo03/normal'
const props = defineProps<{
studentId: undefined // 学生编号(主表的关联字段)
}>()
const formLoading = ref(false) // 表单的加载中
const formData = ref([])
const formRules = reactive({
studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
score: [{ required: true, message: '分数不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.studentId,
async (val) => {
// 1. 重置表单
formData.value = []
// 2. val 非空,则加载数据
if (!val) {
return;
}
try {
formLoading.value = true
formData.value = await Demo03StudentApi.getDemo03CourseListByStudentId(val)
} finally {
formLoading.value = false
}
},
{ immediate: true }
)
/** 新增按钮操作 */
const handleAdd = () => {
const row = {
id: undefined,
studentId: undefined,
name: undefined,
score: undefined
}
row.studentId = props.studentId
formData.value.push(row)
}
/** 删除按钮操作 */
const handleDelete = (index) => {
formData.value.splice(index, 1)
}
/** 表单校验 */
const validate = () => {
return formRef.value.validate()
}
/** 表单值 */
const getData = () => {
return formData.value
}
defineExpose({ validate, getData })
</script>
@@ -0,0 +1,72 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="名字" prop="name">
<el-input v-model="formData.name" placeholder="请输入名字" />
</el-form-item>
<el-form-item label="班主任" prop="teacher">
<el-input v-model="formData.teacher" placeholder="请输入班主任" />
</el-form-item>
</el-form>
</template>
<script setup lang="ts">
import * as Demo03StudentApi from '@/api/infra/demo/demo03/normal'
const props = defineProps<{
studentId: undefined // 学生编号(主表的关联字段)
}>()
const formLoading = ref(false) // 表单的加载中
const formData = ref([])
const formRules = reactive({
studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
teacher: [{ required: true, message: '班主任不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.studentId,
async (val) => {
// 1. 重置表单
formData.value = {
id: undefined,
studentId: undefined,
name: undefined,
teacher: undefined,
}
// 2. val 非空,则加载数据
if (!val) {
return;
}
try {
formLoading.value = true
const data = await Demo03StudentApi.getDemo03GradeByStudentId(val)
if (!data) {
return
}
formData.value = data
} finally {
formLoading.value = false
}
},
{ immediate: true }
)
/** 表单校验 */
const validate = () => {
return formRef.value.validate()
}
/** 表单值 */
const getData = () => {
return formData.value
}
defineExpose({ validate, getData })
</script>
@@ -0,0 +1,214 @@
<template>
<doc-alert title="代码生成(主子表)" url="https://doc.iocoder.cn/new-feature/master-sub/" />
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="名字" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入名字"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-select v-model="queryParams.sex" placeholder="请选择性别" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['infra:demo03-student:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['infra:demo03-student:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="性别" align="center" prop="sex">
<template #default="scope">
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
</template>
</el-table-column>
<el-table-column
label="出生日期"
align="center"
prop="birthday"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="简介" align="center" prop="description" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['infra:demo03-student:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['infra:demo03-student:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<Demo03StudentForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import * as Demo03StudentApi from '@/api/infra/demo/demo03/normal'
import Demo03StudentForm from './Demo03StudentForm.vue'
defineOptions({ name: 'Demo03Student' })
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const loading = ref(true) // 列表的加载中
const list = ref([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
name: null,
sex: null,
description: null,
createTime: []
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await Demo03StudentApi.getDemo03StudentPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await Demo03StudentApi.deleteDemo03Student(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
// 导出的二次确认
await message.exportConfirm()
// 发起导出
exportLoading.value = true
const data = await Demo03StudentApi.exportDemo03Student(queryParams)
download.excel(data, '学生.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>
-4
View File
@@ -1,4 +0,0 @@
<template>
<div>index</div>
</template>
<script lang="ts" setup></script>
@@ -110,9 +110,11 @@ const handleTimeRangeChange = async (times: [dayjs.ConfigType, dayjs.ConfigType]
.trapezoid1 {
transform: perspective(5em) rotateX(-11deg);
}
.trapezoid2 {
transform: perspective(7em) rotateX(-20deg);
}
.trapezoid3 {
transform: perspective(3em) rotateX(-13deg);
}
@@ -316,6 +316,7 @@ onMounted(() => {
:deep(.order-table-col > .cell) {
padding: 0;
}
.summary {
.el-col {
margin-bottom: 1rem;