提交 2b7ed3b0 authored 作者: 王鹏飞's avatar 王鹏飞

refactor: 重构

上级 543c2134
module.exports = { module.exports = {
root: true, root: true,
env: { env: { node: true },
node: true extends: ['plugin:vue/essential', 'eslint:recommended'],
},
'extends': [
'plugin:vue/essential',
'eslint:recommended'
],
parserOptions: { parserOptions: {
parser: 'babel-eslint' ecmaVersion: 'latest'
}, },
rules: { rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 'vue/no-mutating-props': 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off' 'vue/multi-word-component-names': 'off'
} }
} }
module.exports = {
presets: ['@vue/cli-plugin-babel/preset', '@vue/babel-preset-jsx', ['@babel/preset-env', { modules: false }]],
plugins: [
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk'
}
]
]
}
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAucCbdPPyAp6vmnr5XObuPsctUhVLyXwqbIpgI5jWzjG7wmk8
V6z8WJKPO9KZM6D9ejtN/bbbd3j1cRiw7NSl8AUykiVHJWz9TXAflET2EpILLera
I1B2XAcBsc8dZBGGJD/LT97ZvNLYzuQOr7R1wytWH1uisAK5ClzgnSptMenXFyhw
5Xw0Lm3zoeeqYF/KMQ1McAYMGxgu6s6dxXKiA0BcgWQ31yZey0c4HhCt7T7sA/UN
ahUsxtCcSNSvdgXay5Pu/l3N88TwW2QzaCzrueILHWRFwkREhpqyrwjN3gkaa+1T
jLxzCsk/pTnPccxlFwc3YQ3hYLMl36NJ/OIpHwIDAQABAoIBACuMmaXYz6OHmroI
HNCIH9E+F0UIUyVg4/1gj9uoqKvdAx04WPphRyRo8AXhgSOWmfb/UnCqX1fqVvj2
BfzwehsEzO9wp/aBT/3IzM6RQHPoI5DXX98prSY0SlRqr4RXi3CSOFN4duoLMOOI
mlzdXUKttVpSvJixerqQPeT7HnC18NBKOydFMYPdXsgWcMXvu2BuvRClIzsjlXKM
VP00BNRY3Oje6T9yl8N051jIZh48YD3yyEAVFKPOWaJVzUU/RRPOOdTb2Y3A1bek
IbCdurdzoEQoJxkeTuColnuL1jj2mpxIBskKYhPAMV5arYS0pZ0VAtjoGGCyn7gT
l/bkTVkCgYEA6EB15hzRD2iTTIFMtDBqw0l3vJWcuWPvwFZl6zculO8Cdsvx0cDZ
VbEXByA0+CG3q47/UrVqETRhtyuVnxuKrceKU8/zib1dvvTMNjeYLKosjyG49xO6
gDx7nVBwYHmQN/iEuWTobLg1vtSNyd99WgG4cFHvqF7kIJb2W0IaGrsCgYEAzL70
VHn9BUP3CGecoU8Fnck9/7GWhvGgFU58Q/dU3Jr8g6lroeDas9zQU2tCnJN0e7cr
13thq2kQQHTYCY4J6EUtjO89sNVx4bO83xqQhobZBwZXkE5QDWIKCbiYGRLAb1+f
AAEwIEdPBgM88YFHOU5YbPTYH8TLkJfxyvMonu0CgYEArGWE3n3PdVeT1zs3O52g
8jrrpVGNF1QmWCgJ2VKJwkW0F4iFhMRYzzH3vPNcPj+Q/cjUn4lIJWMzkWrJ0mP4
ScyPUm1PApRNLPy7RRd5XtYm40wN52F+k8fRnlFiSUqTEejoZFGR8Xm/c1qFsS6y
9ofGZ6F6ewmM3uAQGGd1xxcCgYBFhjoVTW8bkJ6b3gMTy2+Oyr0gzD7fB8FiOsp7
kcrhNke0tZz01ROuq7aZ/Pwbiv6s2+ApRZ4+xGheWs7ZP8AhfQwgpUR/fZs0FwJ1
h+G3rKaZeg/V0qHgSYA7GNGdAf8SUpf9OmoLK+urkQHqyAlVbkMcjG+vKfYt3Uqf
rb4HaQKBgQCxm1oz9QrmxWKJ4eYKHSsD9UPu4QZhltBECH1btgvTwAEmwuXaCcta
RaFNhMe609sQ+YVIxa9fK0MXBiq7DG6nSLGvnLfVEYo4nGe6EvL9nQ7IFZywJjTb
/Fw4rTMwT59VSWJdv8BPznV7Gk7p17fcXM55iJxxu65r3ZuOXjQSGA==
-----END RSA PRIVATE KEY-----
\ No newline at end of file
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
</template> </template>
<script> <script>
import Application from './ciis/application' import Application from './ciis/application/index.vue'
export default { export default {
components: { Application } components: { Application }
} }
......
...@@ -6,7 +6,7 @@ export default { ...@@ -6,7 +6,7 @@ export default {
id: 'application_declare', id: 'application_declare',
title: '申请声明', title: '申请声明',
visible() { visible() {
return this.tabActive !== 'application_info_first' return false
}, },
update: { update: {
action: '/api/enrollment/v1.0/application-materials/submit/1005' action: '/api/enrollment/v1.0/application-materials/submit/1005'
......
...@@ -17,7 +17,6 @@ export default { ...@@ -17,7 +17,6 @@ export default {
visible() { visible() {
return this.tabActive !== 'application_info_first' return this.tabActive !== 'application_info_first'
}, },
show: false
} }
] ]
} }
...@@ -20,9 +20,7 @@ export default { ...@@ -20,9 +20,7 @@ export default {
question1: first.question || '个人描述(60-1000字)中文或者英文', question1: first.question || '个人描述(60-1000字)中文或者英文',
answer1: first.answer, answer1: first.answer,
qid2: second.qid || '2', qid2: second.qid || '2',
question2: question2: second.question || '申请紫荆教育康博斯威尔大学教育硕士的原因?以及您的职业或个人发展的预期目标(60-1000字)中文或者英文',
second.question ||
'申请紫荆教育康博斯威尔大学教育硕士的原因?以及您的职业或个人发展的预期目标(60-1000字)中文或者英文',
answer2: second.answer answer2: second.answer
} }
} }
...@@ -39,8 +37,6 @@ export default { ...@@ -39,8 +37,6 @@ export default {
} }
}, },
form: { form: {
prev: { to: { query: { active: 'application_info', tab: 'application_info_career' } } },
next: { to: { query: { active: 'application_info', tab: 'application_info_training' } } },
options: {}, options: {},
items: [ items: [
{ {
......
...@@ -31,15 +31,7 @@ export default { ...@@ -31,15 +31,7 @@ export default {
const [startDate, endDate] = item.dates const [startDate, endDate] = item.dates
item.start_date = startDate item.start_date = startDate
item.end_date = endDate item.end_date = endDate
return [ return ['start_date', 'end_date', 'company_name_cn', 'industry', 'dept_cn', 'position_cn', 'job_desc_cn'].reduce((result, key) => {
'start_date',
'end_date',
'company_name_cn',
'industry',
'dept_cn',
'position_cn',
'job_desc_cn'
].reduce((result, key) => {
result[key] = item[key] result[key] = item[key]
return result return result
}, {}) }, {})
...@@ -48,8 +40,6 @@ export default { ...@@ -48,8 +40,6 @@ export default {
} }
}, },
form: { form: {
prev: { to: { query: { active: 'application_info', tab: 'application_info_education' } } },
next: { to: { query: { active: 'application_info', tab: 'application_info_answer' } } },
hasAdd: true, hasAdd: true,
options: { options: {
labelWidth: '140px' labelWidth: '140px'
......
...@@ -40,8 +40,6 @@ export default { ...@@ -40,8 +40,6 @@ export default {
} }
}, },
form: { form: {
prev: { to: { query: { active: 'application_info', tab: 'application_info_profile' } } },
next: { to: { query: { active: 'application_info', tab: 'application_info_career' } } },
hasAdd: true, hasAdd: true,
options: { options: {
labelWidth: '140px' labelWidth: '140px'
......
...@@ -41,7 +41,6 @@ export default { ...@@ -41,7 +41,6 @@ export default {
}, },
form: { form: {
hasButton: false, hasButton: false,
next: { to: { query: { active: 'application_info', tab: 'application_info_profile' } }, isSubmit: true },
options: { labelWidth: '140px' }, options: { labelWidth: '140px' },
items: [ items: [
{ {
......
...@@ -29,8 +29,6 @@ export default { ...@@ -29,8 +29,6 @@ export default {
} }
}, },
form: { form: {
prev: { to: { query: { active: 'application_info', tab: 'application_info_training' } } },
next: { to: { query: { active: 'application_tjx' } } },
hasAdd: true, hasAdd: true,
options: { options: {
labelWidth: '140px' labelWidth: '140px'
......
...@@ -12,11 +12,7 @@ export default { ...@@ -12,11 +12,7 @@ export default {
get: { get: {
action: '/api/enrollment/v1.0/application-materials/1005', action: '/api/enrollment/v1.0/application-materials/1005',
callback(data) { callback(data) {
const { const { basic_info: basicInfo = {}, attachments = [], submission_stage: submissionStage = 'FILLING' } = data.data.material
basic_info: basicInfo = {},
attachments = [],
submission_stage: submissionStage = 'FILLING'
} = data.data.material
this.form.options.disabled = submissionStage !== 'FILLING' this.form.options.disabled = submissionStage !== 'FILLING'
const attachment = attachments.reduce( const attachment = attachments.reduce(
(result, item) => { (result, item) => {
...@@ -62,8 +58,6 @@ export default { ...@@ -62,8 +58,6 @@ export default {
} }
}, },
form: { form: {
prev: { to: { query: { active: 'application_info', tab: 'application_info_first' } }, isSubmit: true },
next: { to: { query: { active: 'application_info', tab: 'application_info_education' } }, isSubmit: true },
options: { labelWidth: '140px' }, options: { labelWidth: '140px' },
items: [ items: [
{ {
......
...@@ -39,8 +39,6 @@ export default { ...@@ -39,8 +39,6 @@ export default {
} }
}, },
form: { form: {
prev: { to: { query: { active: 'application_info', tab: 'application_info_answer' } } },
next: { to: { query: { active: 'application_info', tab: 'application_info_honor' } } },
hasAdd: true, hasAdd: true,
options: { options: {
labelWidth: '140px' labelWidth: '140px'
......
...@@ -18,7 +18,7 @@ export default { ...@@ -18,7 +18,7 @@ export default {
form: { form: {
prev: { to: { query: { active: 'application_tjx' } } }, prev: { to: { query: { active: 'application_tjx' } } },
next: { to: { query: { active: 'application_declare' } } }, next: { to: { query: { active: 'application_declare' } } },
hasButton: false, hasSubmit: false,
options: {}, options: {},
items: [ items: [
{ {
......
...@@ -8,15 +8,13 @@ ...@@ -8,15 +8,13 @@
@tab-change="handleTabChange" @tab-change="handleTabChange"
@success="handleSuccess" @success="handleSuccess"
@error="handleError" @error="handleError"
@back="$router.push('/my')" @back="handleBack">
@prev="handlePrev"
@next="handleNext"
>
<template #aside-append v-if="visible"> <template #aside-append v-if="visible">
<el-button @click="dialogVisible = true">预览全部</el-button> <el-button @click="dialogVisible = true">预览全部</el-button>
</template> </template>
<!-- 报名缴费 --> <!-- 报名缴费 -->
<template #content v-if="currentActive === 'application_pay'"> <template #content v-if="currentActive === 'application_pay'">
pay
<!-- <app-pay /> --> <!-- <app-pay /> -->
</template> </template>
<template #form-name-prepend> 正确 </template> <template #form-name-prepend> 正确 </template>
...@@ -38,30 +36,17 @@ export default { ...@@ -38,30 +36,17 @@ export default {
return { return {
visible: false, visible: false,
menus: [menus], menus: [menus],
currentActive: 'application_info_profile', currentActive: 'application_info',
tabActive: 'application_info_profile', tabActive: 'application_info_profile',
dialogVisible: false dialogVisible: false
} }
}, },
watch: {
$route: {
immediate: true,
handler(route) {
const { query = {} } = route
this.currentActive = query.active || 'application_info_profile'
this.tabActive = query.tab || 'application_info_profile'
}
}
},
methods: { methods: {
handlePageChange(value) { handlePageChange(value) {
this.currentActive = value this.currentActive = value
this.$router.push({ path: this.$route.path, query: { active: value } })
}, },
handleTabChange(value) { handleTabChange(value) {
this.tabActive = value this.tabActive = value
const query = Object.assign({}, this.$route.query, { tab: value })
this.$router.push({ query })
}, },
handleSuccess(data) { handleSuccess(data) {
console.log('提交成功了', data) console.log('提交成功了', data)
...@@ -71,11 +56,8 @@ export default { ...@@ -71,11 +56,8 @@ export default {
console.log('提交失败了', data) console.log('提交失败了', data)
this.$message({ type: 'error', message: data.message }) this.$message({ type: 'error', message: data.message })
}, },
handlePrev(to) { handleBack() {
this.$router.push(to) console.log('back')
},
handleNext(to) {
this.$router.push(to)
} }
} }
} }
......
import Vue from 'vue' import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App.vue' import App from './App.vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import VueForm from '../src/index' import VueForm from '../src/index'
Vue.use(VueRouter) Vue.use(ElementUI)
Vue.use(VueForm) Vue.use(VueForm)
Vue.config.productionTip = false Vue.config.productionTip = false
new Vue({ new Vue({
router: new VueRouter(),
render: h => h(App) render: h => h(App)
}).$mount('#app') }).$mount('#app')
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAwZGHX8Zg+EP5uwnEBWkQazq8DMnKz3QfcNRUjFsxsZjM/98r
oYYp+K6/i/b8JXAVMqjC9+X/ZajgbDPLTrgDJ4TQ70ajdusqG3swNqG0qLUogNgU
PcgVRKr2Pk+m79GD/nnxFgeaG6eBfLsb73G2cQUwsgi3bjf6mX6b9bjxjqzwX0PW
es27yyqdS9uQFzV5KLTA2FJJjGGbg54ZLxVc01aVXx2gG0eLnOFcDSmgXUN4hBmN
gYF4FYHhOVXdMl2+yGGp6IvtIIrt+cp2/TQePnxB2QYwrlDMajHrKp0x7LsqWwZT
jepPgGWWDssiSgTCYVaPx28ESbotpzR7D+LlHQIDAQABAoIBAQCCvXGrHcmXRgph
62mrodgGJQioto82aZ9mzPNCTcIVyzgDRtAoa/7jSdx0g+CwxLB8pAH0ADPtjQ/v
5VfXlnAC/DFGu/Zittmc8CqTa8si/CEcTVX2mLLMy5BAa/o8Fs5JTkGo+H99WDkc
byCiLLLmSXQne72xQzwO+rYKVN1K2JUfzch5wpv86IgfJm0gNEOOvtToeNeMbOWj
7AFfpqq7bRMIdZZZhm2n33duSCSnAO7/OuKHY2/RUkc6FvamAth/ME5S2eHrB7yb
KOMZTJH73xnZc3gmsBiIfC1BsqzV/37Ptd7ncTxuK5YZPXIyJ/BjnDTe712LAz+r
f3FEmtJdAoGBAOdPpbT1ylZKinxEIP4sUPUUrrlXqQxYn2xTOCSBz1dB7OpeqiD+
OBa6ur5Sh0+Ot/VRqV2MbXaGee/qqBiziFH23wKoFc6kxeH8RCv247y89yOHqpCP
SM4I7d10RpPh/POU0apGNOP4HOLOMY4V11u68em9hQDeN6oUBWKvDWTPAoGBANY6
mZ/EWKOFJSPfJNNtfXDO27P12ENsa9UvDv7f+FrcPqGkJq1qFBr3ySBjUE7hTv1e
jedRHtBg5Y038vj/MTofEPSaa5POFgzwfG5TPYCcrZkDoLosnuQ92yafMxZPAf16
Nt3vimpxV2Hwf1Nl3IAU/BavngdohWJkO+yOuupTAoGBAMxkTrJmdhJl75T6xoSS
OD83tWTFFvV34fdgWb24jrQ15tj6KS7aNEmxWo4Ocs5T+C1nqVamXZtcHKdpHHwn
OA/lKw435H0ikFCuDrcig/4ko+TbXlY6pkSZE0aaFjtad5/tIo9pVhcTCMNJG/TH
S/Mcb+LwunQX5+v7oP6gXB91AoGAFDbjWBgG5ScjIgdkSi8CrypVwN1p0rLgWfVe
zN4FaU1u+4GpxKNF0mWfLNcyNL893NqXOUSGS9NY1cJ5wtURqBJWXz5S+Fdx7Tak
ByUDoKcoGlAlUmvzckYD79kF0Q0Tev+VPcvkm7amMC+pVA1AiTVxtBJOLxTFwUsD
/IZbTNECgYEA5uwkBWpb/2yYk86cfuUWJjZ0k8jZPrdG4d9gTdD1Fj4abS3FniKM
x9eN8BcnH0j4raRo+MESzYf5hLbfHRG01oRtBQFZXEM0k/zkkRYdKWG1Ulg1+iZR
ZG/lblczYEUW/IOPYZKMX8c5nq7F6huLsioIvsYOdCGjLZbyRHjEPv8=
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIGtjCCBZ6gAwIBAgIQDjUArTRdZ4P5wtQVmCqJGjANBgkqhkiG9w0BAQsFADBj MIIGtDCCBZygAwIBAgIQJtN62MbxMBaLhLadTXD/LzANBgkqhkiG9w0BAQsFADBj
MQswCQYDVQQGEwJDTjE2MDQGA1UECgwtQmVpamluZyBYaW5jaGFjaGEgQ3JlZGl0 MQswCQYDVQQGEwJDTjE2MDQGA1UECgwtQmVpamluZyBYaW5jaGFjaGEgQ3JlZGl0
IE1hbmFnZW1lbnQgQ28uLCBMdGQuMRwwGgYDVQQDDBNYY2MgVHJ1c3QgT1YgU1NM IE1hbmFnZW1lbnQgQ28uLCBMdGQuMRwwGgYDVQQDDBNYY2MgVHJ1c3QgT1YgU1NM
IENBMB4XDTIyMDgxODE0MDAzMVoXDTIzMDkxNzE0MDAzMFowgY4xCzAJBgNVBAYT IENBMB4XDTIzMDkwNzA1NTM0MVoXDTI0MDkwNjA1NTM0MFowgY4xCzAJBgNVBAYT
AkNOMRIwEAYDVQQIDAnljJfkuqzluIIxEjAQBgNVBAcMCeWMl+S6rOW4gjE/MD0G AkNOMRIwEAYDVQQIDAnljJfkuqzluIIxEjAQBgNVBAcMCeWMl+S6rOW4gjE/MD0G
A1UECgw25riF5o6n57Sr6I2G77yI5YyX5Lqs77yJ5pWZ6IKy56eR5oqA6IKh5Lu9 A1UECgw25riF5o6n57Sr6I2G77yI5YyX5Lqs77yJ5pWZ6IKy56eR5oqA6IKh5Lu9
5pyJ6ZmQ5YWs5Y+4MRYwFAYDVQQDDA0qLmV6aWppbmcuY29tMIIBIjANBgkqhkiG 5pyJ6ZmQ5YWs5Y+4MRYwFAYDVQQDDA0qLmV6aWppbmcuY29tMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAucCbdPPyAp6vmnr5XObuPsctUhVLyXwqbIpg 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwZGHX8Zg+EP5uwnEBWkQazq8DMnKz3QfcNRU
I5jWzjG7wmk8V6z8WJKPO9KZM6D9ejtN/bbbd3j1cRiw7NSl8AUykiVHJWz9TXAf jFsxsZjM/98roYYp+K6/i/b8JXAVMqjC9+X/ZajgbDPLTrgDJ4TQ70ajdusqG3sw
lET2EpILLeraI1B2XAcBsc8dZBGGJD/LT97ZvNLYzuQOr7R1wytWH1uisAK5Clzg NqG0qLUogNgUPcgVRKr2Pk+m79GD/nnxFgeaG6eBfLsb73G2cQUwsgi3bjf6mX6b
nSptMenXFyhw5Xw0Lm3zoeeqYF/KMQ1McAYMGxgu6s6dxXKiA0BcgWQ31yZey0c4 9bjxjqzwX0PWes27yyqdS9uQFzV5KLTA2FJJjGGbg54ZLxVc01aVXx2gG0eLnOFc
HhCt7T7sA/UNahUsxtCcSNSvdgXay5Pu/l3N88TwW2QzaCzrueILHWRFwkREhpqy DSmgXUN4hBmNgYF4FYHhOVXdMl2+yGGp6IvtIIrt+cp2/TQePnxB2QYwrlDMajHr
rwjN3gkaa+1TjLxzCsk/pTnPccxlFwc3YQ3hYLMl36NJ/OIpHwIDAQABo4IDODCC Kp0x7LsqWwZTjepPgGWWDssiSgTCYVaPx28ESbotpzR7D+LlHQIDAQABo4IDNjCC
AzQwDAYDVR0TAQH/BAIwADBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8veGluY2hh AzIwDAYDVR0TAQH/BAIwADBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8veGluY2hh
Y2hhMm92LmNybC5jZXJ0dW0ucGwveGluY2hhY2hhMm92LmNybDB5BggrBgEFBQcB Y2hhMm92LmNybC5jZXJ0dW0ucGwveGluY2hhY2hhMm92LmNybDB5BggrBgEFBQcB
AQRtMGswLwYIKwYBBQUHMAGGI2h0dHA6Ly94aW5jaGFjaGEyb3Yub2NzcC1jZXJ0 AQRtMGswLwYIKwYBBQUHMAGGI2h0dHA6Ly94aW5jaGFjaGEyb3Yub2NzcC1jZXJ0
dW0uY29tMDgGCCsGAQUFBzAChixodHRwOi8vcmVwb3NpdG9yeS5jZXJ0dW0ucGwv dW0uY29tMDgGCCsGAQUFBzAChixodHRwOi8vcmVwb3NpdG9yeS5jZXJ0dW0ucGwv
eGluY2hhY2hhMm92LmNlcjAfBgNVHSMEGDAWgBT6oMvCx12BtSCSByALtjtwOwkO eGluY2hhY2hhMm92LmNlcjAfBgNVHSMEGDAWgBT6oMvCx12BtSCSByALtjtwOwkO
VTAdBgNVHQ4EFgQUEJufsd5nLNR+wqR2GsFWDn7qTn0wTAYDVR0gBEUwQzAIBgZn VTAdBgNVHQ4EFgQUXm2TAFqEePvMkmcMN+bVXSvLTH8wTAYDVR0gBEUwQzAIBgZn
gQwBAgIwNwYMKoRoAYb2dwIFARYCMCcwJQYIKwYBBQUHAgEWGWh0dHBzOi8vd3d3 gQwBAgIwNwYMKoRoAYb2dwIFARYCMCcwJQYIKwYBBQUHAgEWGWh0dHBzOi8vd3d3
LmNlcnR1bS5wbC9DUFMwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4G LmNlcnR1bS5wbC9DUFMwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4G
A1UdDwEB/wQEAwIFoDAlBgNVHREEHjAcgg0qLmV6aWppbmcuY29tggtlemlqaW5n A1UdDwEB/wQEAwIFoDAlBgNVHREEHjAcgg0qLmV6aWppbmcuY29tggtlemlqaW5n
LmNvbTCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFoAHYAVYHUwhaQNgFK6gubVzxT LmNvbTCCAXwGCisGAQQB1nkCBAIEggFsBIIBaAFmAHUA7s3QZNXbGs7FXLedtM0T
8MDkOHhwJQgXL6OqHQcT0wwAAAGCsUFwdgAABAMARzBFAiAc51lynft4sehXTgyw ojKHRny87N7DUUhZRnEftZsAAAGKbjQU6wAABAMARjBEAiAMbEi/VFFT/mgWiXPw
tjQ83PAVmfZ3FC55eIpIETe2hgIhANvo5ZtGQpcZQ5HSGbRLy4Y9/MbUrS8dtkwP WgVT5THVJCfr9j1oIcfiB5MFHgIgJ2nAv7xTmfoZfcO8sWoGigLdN8QtGksVUSI2
l7I/lRj7AHYArfe++nz/EMiLnT2cHj4YarRnKV3PsQwkyoWGNOvcgooAAAGCsUFw 86Wg3O4AdgDatr9rP7W2Ip+bwrtca+hwkXFsu1GEhTS9pD0wSNf7qwAAAYpuNBUS
TwAABAMARzBFAiATnQDMw1wykBdnTIRfSSXPj7HZfDdRRq6VaiTbSpYKYQIhAMTp AAAEAwBHMEUCIDmQ1/B1s3jRr+0SvDSWEFN9/b4/W8QV5yULASXqQkYqAiEA0wKZ
V6K0W9gtdYGdeg4j6n17S1yMODYvLJxd3kAFFNDTAHYAejKMVNi3LbYg6jjgUh7p lklUASXMM8mluAimD5e4qSXu76+148bfZA2d404AdQBIsONr2qZHNA/lagL6nTDr
hBZwMhOFTTvSK8E6V6NS61IAAAGCsUFwrQAABAMARzBFAiEAwWKXKxp6DcKG7R/d HFIBy1bdLIHZu7+rOdiEcwAAAYpuNBefAAAEAwBGMEQCICyokQlEyxPTPYNBZzwv
rxmPUg8uNbUcdxysrpB3gOzkIlACICWpx7/+2ulDG2EC9m4RqGcXbts3VWu/yxpE W8AxbKUJl+I5TbJEJsiFECRUAiA8fA86Hof/yLHhMl4amx5AttDNhpDrCHDK1N7m
0pAYuAP8MA0GCSqGSIb3DQEBCwUAA4IBAQCf3AdKLO8EUntMjKaRa0lncwh/pBIQ NYx9XjANBgkqhkiG9w0BAQsFAAOCAQEAq4Q2vW3Xh5TOYk/DofnV2uRiK08P5a5I
bcQfkJBfiTpo6tnRphR+DE50oYOX1TSQRm4cDgP2JURYiTK6Z2+ljqMbUx4mNLqe NRE5Tet3J5rp2WnNgXoSAOabqWGI6VrTyenTZxrmS/2Aq2A008WOj4Z7T3P9iDS/
+6yG+PGCUX6rX4BsJqlRP2W7WONE/I3/3S6MRfclKmakHSyrGFi8O/JJyNqm+5z9 MgJkPmc/REqHr15LIDnyRRfmn9+1ShVMwukYHSmZgPewAzSkKdGFN85t3uCEUnXz
8tnk8c1Cn7FboJZonhX0yszHkXLLeA93xm5+Etkw0+DvRcZGiEqKQivO3CnUh1gs kna3ZmSqgJrSWSO9n/3t/kICsVivjqSUuHtnCSbBa+DTSNxIkbkr1t1RJkF4KvSk
LZg27a8s3dtmAAHbb2icm5jloK9Jgpx/NkGL/cCoNZ8Ng2TZkRvo6GzIp43uS332 AKkvyojoKoeCd+WWEl2MBHY6TK4CzfyLN5qhQub0XqTOh6cG9TwALcLZ4MQeaeOO
R07dQ6rNWZkPzdxKUdNcT0v3yJJyxD1H3Rk4/bxp78giw4JGHp52Df+U ZkGv9DcyeOz7FwwzFa+vAyzhq2XlDPLlpZ4ELALbaqnq3x7HHpzlpw==
-----END CERTIFICATE----- -----END CERTIFICATE-----
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIEzzCCA7egAwIBAgIRAPJECC2rqQ2ljHLp8pqTQK4wDQYJKoZIhvcNAQELBQAw MIIEzzCCA7egAwIBAgIRAPJECC2rqQ2ljHLp8pqTQK4wDQYJKoZIhvcNAQELBQAw
...@@ -111,3 +111,4 @@ CjqTE5s7FCMTY5w/0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5x ...@@ -111,3 +111,4 @@ CjqTE5s7FCMTY5w/0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5x
O/fIR/RpbxXyEV6DHpx8Uq79AtoSqFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs O/fIR/RpbxXyEV6DHpx8Uq79AtoSqFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs
6GAqm4VKQPNriiTsBhYscw== 6GAqm4VKQPNriiTsBhYscw==
-----END CERTIFICATE----- -----END CERTIFICATE-----
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<div id="app"></div>
<script type="module" src="/examples/main.js"></script>
</body>
</html>
This source diff could not be displayed because it is too large. You can view the blob instead.
{ {
"name": "@ezijing/vue-form", "name": "@ezijing/vue-form",
"version": "2.3.18", "version": "2.5.16",
"private": false, "private": false,
"description": "基于Vue Element-UI的表单", "description": "基于Vue Element-UI的表单",
"type": "module",
"scripts": { "scripts": {
"serve": "vue-cli-service serve --open", "dev": "vite",
"build": "vue-cli-service build --target lib --name vue-form ./src/index.js", "build": "vite build"
"lint": "vue-cli-service lint" },
"main": "./dist/vue-form.umd.cjs",
"module": "./dist/vue-form.js",
"exports": {
".": {
"import": "./dist/vue-form.js",
"require": "./dist/vue-form.umd.cjs"
},
"./style.css": "./dist/style.css"
}, },
"main": "dist/vue-form.umd.min.js",
"files": [ "files": [
"dist/", "dist/",
"package.json", "package.json",
"README.md" "README.md"
], ],
"dependencies": { "dependencies": {
"@vue/babel-helper-vue-jsx-merge-props": "^1.0.0", "axios": "^1.6.7",
"@vue/babel-preset-jsx": "^1.1.2", "element-ui": "^2.15.14",
"axios": "^0.20.0", "vue": "^2.7.16"
"core-js": "^3.6.5",
"element-ui": "^2.14.1",
"qs": "^6.9.4",
"vue": "^2.6.12"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0", "@vitejs/plugin-vue2": "^2.3.1",
"@vue/cli-plugin-eslint": "~4.5.0", "eslint": "^8.56.0",
"@vue/cli-service": "~4.5.0", "eslint-plugin-vue": "^9.21.1",
"babel-eslint": "^10.1.0", "sass": "^1.71.0",
"babel-plugin-component": "^1.1.1", "unplugin-vue-components": "^0.26.0",
"babel-preset-env": "^1.7.0", "vite": "^5.1.3"
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"vue-router": "^3.4.6",
"vue-template-compiler": "^2.6.11"
}, },
"keywords": [ "keywords": [
"element-ui", "element-ui",
......
...@@ -3,61 +3,53 @@ ...@@ -3,61 +3,53 @@
<div class="v-layout-aside"> <div class="v-layout-aside">
<slot name="aside"> <slot name="aside">
<slot name="aside-prepend"></slot> <slot name="aside-prepend"></slot>
<v-menu :default-active="defaultActive" :datalist="menus" @select="onSelect" v-bind="$attrs"></v-menu> <v-menu v-model="menuActiveId" :menus="currentMenus" @change="handleMenuChange"></v-menu>
<slot name="aside-append"></slot> <slot name="aside-append"></slot>
</slot> </slot>
</div> </div>
<div class="v-layout-main" v-if="page" :key="activeId"> <div class="v-layout-main" :key="menuActiveId">
<slot> <slot>
<!-- 选项卡 --> <!-- 选项卡 -->
<template v-if="page.tabs"> <VCardFormTabs
<v-card-tabs :default-active="tabActive" v-bind="page" v-on="$listeners"> v-model="tabActiveId"
:tabs="tabPages"
@change="handleTabChange"
@prev="handleStepChange"
@next="handleStepChange"
v-on="$listeners"
v-if="tabPages.length">
<!-- slot --> <!-- slot -->
<template v-slot:[slotName]="slotProps" v-for="slotName in tabSlotNames"> <template v-slot:[slotName]="slotProps" v-for="slotName in slotNames">
<slot :name="slotName" v-bind="slotProps"></slot> <slot :name="slotName" v-bind="slotProps"></slot>
</template> </template>
</v-card-tabs> </VCardFormTabs>
</template>
<template v-else> <VCardForm :page="page" @prev="handleStepChange" @next="handleStepChange" v-on="$listeners" v-else>
<v-card v-bind="page" v-on="$listeners"> <slot name="content"></slot>
<slot name="content-header"></slot>
<slot name="content">
<div class="v-layout-html" v-html="page.html" v-if="page.html"></div>
<v-form-pane v-bind="page" v-on="$listeners" v-if="page.form">
<!-- slot --> <!-- slot -->
<template v-slot:[slotName]="slotProps" v-for="slotName in slotNames"> <template v-slot:[slotName]="slotProps" v-for="slotName in slotNames">
<slot :name="slotName" v-bind="slotProps"></slot> <slot :name="slotName" v-bind="slotProps"></slot>
</template> </template>
</v-form-pane> </VCardForm>
</slot>
<slot name="content-footer"></slot>
</v-card>
</template>
</slot> </slot>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import VMenu from '@/packages/layout/src/menu' import VMenu from '@/components/Menu.vue'
import VCard from '@/packages/layout/src/card' import VCardForm from './components/CardForm.vue'
import VCardTabs from '@/packages/layout/src/card-tabs' import VCardFormTabs from './components/CardFormTabs.vue'
import VFormPane from '@/packages/form/src/form-pane' import VFormPane from '@/components/FormPane.vue'
export default { export default {
name: 'VueForm', name: 'VueForm',
components: { VMenu, VCardForm, VCardFormTabs, VFormPane },
props: { props: {
asideWidth: String, menus: { type: Array, default: () => [] },
menus: {
type: Array,
required: true,
default() {
return []
}
},
defaultActive: { type: String }, defaultActive: { type: String },
tabActive: { type: String }, tabActive: { type: String },
disabled: { type: Boolean, default: false },
backText: { type: String, default: '返回报名系统' }, backText: { type: String, default: '返回报名系统' },
prevText: { type: String, default: '上一步' }, prevText: { type: String, default: '上一步' },
nextText: { type: String, default: '下一步' }, nextText: { type: String, default: '下一步' },
...@@ -65,40 +57,34 @@ export default { ...@@ -65,40 +57,34 @@ export default {
}, },
provide() { provide() {
return { return {
options: { backText: this.backText, prevText: this.prevText, nextText: this.nextText, submitText: this.submitText } options: { disabled: this.disabled, backText: this.backText, prevText: this.prevText, nextText: this.nextText, submitText: this.submitText }
} }
}, },
components: { VMenu, VCard, VCardTabs, VFormPane },
data() { data() {
return { return { menuActiveId: this.defaultActive, tabActiveId: this.tabActive }
activeId: this.defaultActive
}
},
watch: {
defaultActive(value) {
this.activeId = value
}
}, },
computed: { computed: {
page() { currentMenus() {
return this.getDeepItem(this.menus, this.activeId) return this.filterVisible(this.menus)
}, },
tabSlotNames() { pages() {
const slotNames = [] const pages = this.currentMenus[0].children.reduce((result, item) => {
this.page?.tabs?.forEach(tab => { if (item.tabs) {
tab.form?.items?.forEach(item => { return [...result, ...item.tabs.map(tab => ({ ...tab, isTab: true, parentId: item.id }))]
if (item.slotName) { }
slotNames.push(item.slotName) return [...result, item]
} }, [])
if (item.prependSlotName) { return pages.map((item, index, arr) => {
slotNames.push(item.prependSlotName) return { ...item, prev: arr[index - 1]?.id, next: arr[index + 1]?.id }
}
if (item.appendSlotName) {
slotNames.push(item.appendSlotName)
}
}) })
}) },
return slotNames tabPages() {
return this.pages.filter(item => item.parentId === this.menuActiveId)
},
// 当前页的数据
page() {
const id = this.tabPages.length ? this.tabActiveId : this.menuActiveId
return this.pages.find(item => item.id === id)
}, },
slotNames() { slotNames() {
return ( return (
...@@ -117,23 +103,50 @@ export default { ...@@ -117,23 +103,50 @@ export default {
) )
} }
}, },
methods: { watch: {
getDeepItem(arr, id) { defaultActive(value) {
for (const item of arr) { this.menuActiveId = value
if (item.id === id || id === undefined) { },
return item tabActive(value) {
this.tabActiveId = value
} }
},
methods: {
filterVisible(data) {
return data.filter(item => {
// 检查当前项的visible属性是否为函数,若是则调用函数获取结果
const isVisible = typeof item.visible === 'function' ? item.visible() : item.visible === undefined ? true : item.visible
if (!isVisible) {
return false // 若当前项不可见,则过滤掉
}
// 如果当前项有children属性,则递归过滤children
if (item.children) { if (item.children) {
const found = this.getDeepItem(item.children, id) item.children = this.filterVisible(item.children)
if (found) {
return found
} }
// 如果当前项有tabs属性,则递归过滤tabs
if (item.tabs) {
item.tabs = this.filterVisible(item.tabs)
} }
return true // 当前项可见,保留
})
},
// 上一步\下一步
handleStepChange(id) {
const nextPage = this.pages.find(item => item.id === id)
if (nextPage.isTab) {
if (this.menuActiveId !== nextPage.parentId) this.handleMenuChange(nextPage.parentId)
this.handleTabChange(id)
} else {
this.handleMenuChange(id)
} }
}, },
onSelect(id) { handleMenuChange(id) {
this.activeId = id this.menuActiveId = id
this.$emit('page-change', id) this.$emit('page-change', this.menuActiveId)
},
handleTabChange(id) {
this.tabActiveId = id
this.$emit('tab-change', this.tabActiveId)
} }
} }
} }
...@@ -155,9 +168,12 @@ export default { ...@@ -155,9 +168,12 @@ export default {
flex: 1; flex: 1;
margin-left: 20px; margin-left: 20px;
} }
.v-layout-html { .v-card-html {
font-size: 14px; font-size: 14px;
color: #222; color: #222;
line-height: 34px; line-height: 34px;
} }
.red {
color: var(--main-color);
}
</style> </style>
...@@ -2,26 +2,32 @@ ...@@ -2,26 +2,32 @@
<div class="v-card"> <div class="v-card">
<div class="v-card__hd"> <div class="v-card__hd">
<slot name="header"> <slot name="header">
<h1 class="v-card__title">{{ title }}</h1> <h1 class="v-card__title">{{ page.title }}</h1>
<div class="v-card__back" @click="$emit('back')"> <div class="v-card__back" @click="$emit('back')">
<i class="el-icon-arrow-left"></i> <i class="el-icon-arrow-left"></i>
<span>{{ backText || options.backText }}</span> <span>{{ options.backText }}</span>
</div> </div>
</slot> </slot>
</div> </div>
<div class="v-card__bd"> <div class="v-card__bd">
<slot></slot> <slot>
<div class="v-card-html" v-html="page.prepend" v-if="page.prepend"></div>
<VFormPane :page="page" :key="page.id" v-on="$listeners"></VFormPane>
<div class="v-card-html" v-html="page.append" v-if="page.append"></div>
</slot>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import VFormPane from './FormPane.vue'
export default { export default {
name: 'VCard', name: 'VCardForm',
components: { VFormPane },
inject: ['options'], inject: ['options'],
props: { props: {
title: { type: String }, page: { type: Object, default: () => ({}) }
backText: { type: String }
} }
} }
</script> </script>
......
...@@ -2,67 +2,45 @@ ...@@ -2,67 +2,45 @@
<div class="v-tabs-card"> <div class="v-tabs-card">
<div class="v-tabs-card__back" @click="$emit('back')"> <div class="v-tabs-card__back" @click="$emit('back')">
<i class="el-icon-arrow-left"></i> <i class="el-icon-arrow-left"></i>
<span>{{ backText || options.backText }}</span> <span>{{ options.backText }}</span>
</div> </div>
<el-tabs type="card" v-model="activeName" @tab-click="handleTabClick"> <el-tabs type="card" :value="value" @tab-click="handleTabClick">
<el-tab-pane :lazy="true" :label="tab.title" :name="tab.id" :key="tab.id" v-for="tab in currentTabs"> <el-tab-pane lazy v-for="page in tabs" :name="page.id" :key="page.id">
<template v-slot:label> <template #label>
{{ tab.title }} {{ page.title }}
<span class="red" v-if="tab.required">*</span> <span class="red" v-if="page.required">*</span>
</template> </template>
<v-form-pane v-bind="tab" v-on="$listeners"> <div class="v-card-html" v-html="page.prepend" v-if="page.prepend"></div>
<!-- slot --> <VFormPane :page="page" :key="page.id" v-on="$listeners">
<template v-slot:[slotName]="slotProps" v-for="slotName in tabSlotNames"> <template v-slot:[slotName]="slotProps" v-for="slotName in tabSlotNames">
<slot :name="slotName" v-bind="slotProps"></slot> <slot :name="slotName" v-bind="slotProps"></slot>
</template> </template>
</v-form-pane> </VFormPane>
<div class="v-card-html" v-html="page.append" v-if="page.append"></div>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</div> </div>
</template> </template>
<script> <script>
import VFormPane from '../../form/src/form-pane' import VFormPane from './FormPane.vue'
export default { export default {
name: 'VCardTabs', name: 'VCardFormTabs',
components: { VFormPane },
inject: ['options'], inject: ['options'],
props: { props: {
defaultActive: { type: String }, value: { type: String },
tabs: { type: Array, default: () => [] }, tabs: { type: Array, default: () => [] }
backText: { type: String }
}, },
components: { VFormPane },
data() { data() {
return { return {}
activeName: ''
}
},
watch: {
defaultActive: {
immediate: true,
handler(value) {
this.activeName = value
}
}
// tabs: {
// immediate: true,
// handler(list) {
// const [first] = list
// this.activeName = first.id
// }
// }
}, },
computed: { computed: {
currentTabs() {
return this.tabs.filter(item => {
return item.visible === undefined || item.visible.call(this.$parent)
})
},
tabSlotNames() { tabSlotNames() {
const slotNames = [] const slotNames = []
this.tabs?.forEach(tab => { this.tabs?.forEach(page => {
tab.form?.items?.forEach(item => { page.form?.items?.forEach(item => {
if (item.slotName) { if (item.slotName) {
slotNames.push(item.slotName) slotNames.push(item.slotName)
} }
...@@ -79,7 +57,7 @@ export default { ...@@ -79,7 +57,7 @@ export default {
}, },
methods: { methods: {
handleTabClick() { handleTabClick() {
this.$emit('tab-change', this.activeName) this.$emit('change', this.value)
} }
} }
} }
......
<template>
<el-form v-bind="options" ref="form" :model="ruleForm" @submit.native.prevent>
<template v-for="(item, index) in currentItems">
<el-form-item v-bind="item" :prop="item.model" :key="index">
<template v-if="item.slotName">
<slot :name="item.slotName" v-bind="{ item, items, model: ruleForm }"></slot>
</template>
<template v-else>
<div class="v-form-item__prepend" v-html="item.prepend" v-if="item.prepend"></div>
<slot :name="item.prependSlotName" v-bind="{ item, items, form: ruleForm }" v-if="item.prependSlotName"></slot>
<component :is="item.type" :options="item" :data="ruleForm" v-bind="item.attrs"></component>
<slot :name="item.appendSlotName" v-bind="{ item, items, form: ruleForm }" v-if="item.appendSlotName"></slot>
<div class="v-form-item__append" v-html="item.append" v-if="item.append"></div>
</template>
</el-form-item>
</template>
</el-form>
</template>
<script>
import VInput from '@/components/Input.vue'
import VSelect from '@/components/Select.vue'
import VRadio from '@/components/Radio.vue'
import VCheckbox from '@/components/Checkbox.vue'
import VDatepicker from '@/components/DatePicker.vue'
import VUpload from '@/components/Upload.vue'
export default {
name: 'VForm',
components: { VInput, VSelect, VRadio, VCheckbox, VDatepicker, VUpload },
props: {
options: { type: Object, default: () => ({}) },
model: { type: Object, default: () => ({}) },
items: { type: Array, default: () => [] }
},
data() {
return {
ruleForm: {}
}
},
watch: {
model: {
immediate: true,
deep: true,
handler(value) {
this.ruleForm = value
}
}
},
computed: {
$form() {
return this.$refs.form
},
currentItems() {
return this.items.filter(item => {
if (Object.prototype.hasOwnProperty.call(item, 'isShow')) {
return item.isShow(this.ruleForm)
}
return true
})
}
}
}
</script>
<template> <template>
<div class="v-form-pane" ref="formpane"> <div class="v-form-pane">
<template v-if="form.hint"> <div class="v-form-pane__prepend" v-html="form.prepend" v-if="form.prepend"></div>
<div class="v-form-pane__hint" v-html="form.hint"></div>
</template>
<!-- 多个表单 --> <!-- 多个表单 -->
<template v-if="isMultiple"> <template v-if="isMultiple">
<v-form <v-form :options="form.options" :items="form.prependItems" :model="model[0] || model" ref="form" v-if="form.prependItems"></v-form>
:options="form.options"
:items="form.prependItems"
:model="model[0] || model"
:hasButton="false"
v-on="$listeners"
ref="form"
v-if="form.prependItems"
></v-form>
<template v-for="(item, index) in model"> <template v-for="(item, index) in model">
<div class="v-form-group" :key="index"> <div class="v-form-group" :key="index">
<div class="v-form-group__inner"> <div class="v-form-group__inner">
<v-form <v-form :options="form.options" :items="form.items" :model="item" ref="form" class="v-form-group__content">
:disabled="form.disabled && form.disabled(item)"
:options="form.options"
:items="form.items"
:model="item"
:hasButton="false"
:submitText="form.submitText"
v-on="$listeners"
ref="form"
class="v-form-group__content"
>
<!-- slot --> <!-- slot -->
<template v-slot:[slotName]="slotProps" v-for="slotName in slotNames"> <template v-slot:[slotName]="slotProps" v-for="slotName in slotNames">
<slot :name="slotName" v-bind="slotProps"></slot> <slot :name="slotName" v-bind="slotProps"></slot>
...@@ -43,8 +23,7 @@ ...@@ -43,8 +23,7 @@
size="medium" size="medium"
plain plain
@click="button.onClick(item, $refs.form[index])" @click="button.onClick(item, $refs.form[index])"
v-if="button.visible && button.visible(item)" v-if="button.visible && button.visible(item)">
>
{{ button.text }}</el-button {{ button.text }}</el-button
> >
</div> </div>
...@@ -52,7 +31,7 @@ ...@@ -52,7 +31,7 @@
</div> </div>
</template> </template>
</div> </div>
<template v-if="index > currentForm.minlength - 1"> <template v-if="index > form.minlength - 1">
<div class="v-form-group__remove" @click="handleRemove(index)">删除</div> <div class="v-form-group__remove" @click="handleRemove(index)">删除</div>
</template> </template>
</div> </div>
...@@ -60,82 +39,66 @@ ...@@ -60,82 +39,66 @@
<div class="v-form-group__add" v-if="form.hasAdd"> <div class="v-form-group__add" v-if="form.hasAdd">
<i class="el-icon-circle-plus" @click="handleAdd"></i> <i class="el-icon-circle-plus" @click="handleAdd"></i>
</div> </div>
<v-form <v-form :options="form.options" :items="form.appendItems" :model="model[0] || model" ref="form" v-if="form.appendItems"></v-form>
:options="form.options"
:items="form.appendItems"
:model="model[0] || model"
:hasButton="false"
v-on="$listeners"
ref="form"
v-if="form.appendItems"
></v-form>
</template> </template>
<!-- 一个表单 --> <!-- 一个表单 -->
<template v-else> <template v-else>
<v-form <v-form :options="form.options" :items="form.items" :model="model" ref="form">
:options="form.options"
:items="form.items"
:model="model"
:hasButton="false"
:submitText="form.submitText"
@onSubmit="onSubmit"
v-on="$listeners"
ref="form"
>
<!-- slot --> <!-- slot -->
<template v-slot:[slotName]="slotProps" v-for="slotName in slotNames"> <template v-slot:[slotName]="slotProps" v-for="slotName in slotNames">
<slot :name="slotName" v-bind="slotProps"></slot> <slot :name="slotName" v-bind="slotProps"></slot>
</template> </template>
</v-form> </v-form>
</template> </template>
<div class="v-form-pane__append" v-html="form.append" v-if="form.append"></div>
<div class="v-form-footer"> <div class="v-form-footer" v-if="form.hasButton">
<el-button type="primary" size="medium" @click="handlePrev" v-if="form.prev">{{ options.prevText }}</el-button> <el-button size="medium" @click="handlePrev" v-if="page.prev">{{ options.prevText }}</el-button>
<el-button type="primary" size="medium" :disabled="currentForm.options.disabled" @click="handleSubmit" v-if="currentForm.hasButton"> <el-button type="primary" size="medium" :disabled="form.options.disabled" @click="handleSubmit" style="min-width: 120px" v-if="form.hasSubmit">
{{ form.submitText || options.submitText }} {{ submitButtonText }}
</el-button> </el-button>
<el-button type="primary" size="medium" @click="handleNext" v-if="form.next">{{ options.nextText }}</el-button> <el-button size="medium" @click="handleNext" v-if="page.next">{{ options.nextText }}</el-button>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import httpRequest from '@/utils/axios' import httpRequest from '@/utils/axios'
import VForm from './form.vue' import VForm from './Form.vue'
const defaultAxiosOptions = {
action: '',
headers: {},
params: {},
data: {},
beforeRequest(params) {
return params
},
callback(res) {
return res
},
errorCallback(res) {
return res
}
}
export default { export default {
name: 'VFormPane', name: 'VFormPane',
components: { VForm },
inject: ['options'], inject: ['options'],
components: { VForm },
props: { props: {
title: String, page: { type: Object, default: () => ({}) }
get: Object,
update: Object,
form: {
type: Object,
default() {
return {}
}
}
}, },
data() { data() {
const model = this.form.model || (this.form.hasAdd ? [Object.assign({}, this.form.defaultModel)] : {})
return { return {
model, model: undefined,
detail: {} form: {}
} }
}, },
computed: { computed: {
isMultiple() { isMultiple() {
return Array.isArray(this.model) return Array.isArray(this.model)
}, },
currentForm() {
return Object.assign({ minlength: 1, hasSubmit: true, hasButton: true, options: {} }, this.form)
},
that() {
return this
},
slotNames() { slotNames() {
return ( return (
this.form?.items?.reduce((slotNames, item) => { this.form?.items?.reduce((slotNames, item) => {
...@@ -151,123 +114,121 @@ export default { ...@@ -151,123 +114,121 @@ export default {
return slotNames return slotNames
}, []) || [] }, []) || []
) )
},
submitButtonText() {
return this.form.submitText || this.options.submitText
},
get() {
return Object.assign({}, defaultAxiosOptions, this.page.get)
},
update() {
return Object.assign({}, defaultAxiosOptions, this.page.update)
} }
}, },
methods: { watch: {
init() { page: {
this.get && this.getData() immediate: true,
handler() {
const { form } = this.page
this.model = form.model || (form.hasAdd ? [Object.assign({}, form.defaultModel)] : {})
const formOptions = Object.assign({ disabled: this.options.disabled }, form.options)
this.form = Object.assign({ minlength: 1, hasSubmit: true, hasButton: true }, form, { options: formOptions })
this.getData()
}
}
}, },
methods: {
// 获取 // 获取
getData() { async getData() {
let { action: url, method = 'get', headers = {}, params = {}, data = {}, beforeRequest, callback, errorCallback } = this.get let { action, headers = {}, params = {}, beforeRequest, callback, errorCallback } = this.get
if (!action) {
if (callback) {
this.model = callback.call(this)
}
return
}
if (beforeRequest) { if (beforeRequest) {
data = beforeRequest(data) params = beforeRequest(params)
} }
httpRequest({ try {
method, const res = await httpRequest.get(action, { params, headers })
url,
params,
data,
headers
})
.then(res => {
this.detail = JSON.parse(JSON.stringify(Object.assign({}, res)))
// 默认数据设置 // 默认数据设置
if (this.form.hasAdd && Array.isArray(res) && !res.length) { if (this.form.hasAdd && Array.isArray(res) && !res.length) {
res.push(Object.assign({}, this.form.defaultModel)) res.push(Object.assign({}, this.form.defaultModel))
} }
if (callback) { this.model = callback ? callback.call(this, res) : res
res = callback.call(this, res) } catch (error) {
} errorCallback && errorCallback.call(this, error)
this.model = res
})
.catch(error => {
if (errorCallback) {
errorCallback.call(this, error)
} else {
this.$emit('error', error) this.$emit('error', error)
} }
})
}, },
// 更新 // 更新
async updateData(formData) { async updateData() {
let { action, headers = {}, data = {}, beforeRequest, callback, errorCallback } = this.update let { action, headers = {}, data = {}, beforeRequest, callback, errorCallback } = this.update
if (!action) {
this.$emit('update', this.update.beforeRequest(this.model))
return
}
if (beforeRequest) { if (beforeRequest) {
formData = beforeRequest(formData) data = beforeRequest(Object.assign({}, this.model, data))
} }
// 自定义数据和表单数据合并 try {
formData = Object.assign({}, formData, data) const res = await httpRequest.post(action, data, { headers })
await httpRequest callback && callback.call(this, res)
.post(action, formData, { headers })
.then(res => {
if (callback) {
callback.call(this, res)
} else {
this.$emit('success', res) this.$emit('success', res)
} } catch (error) {
}) errorCallback && errorCallback.call(this, error)
.catch(error => {
if (errorCallback) {
errorCallback.call(this, error)
} else {
this.$emit('error', error) this.$emit('error', error)
} }
})
},
onSubmit(data) {
this.updateData(data)
}, },
// 新增表单 // 新增表单
handleAdd() { handleAdd() {
if (this.currentForm.options.disabled) { if (this.form.options.disabled) {
return return
} }
this.model.push(Object.assign({}, this.form.defaultModel)) this.model.push(Object.assign({}, this.form.defaultModel))
}, },
// 删除表单 // 删除表单
handleRemove(index) { handleRemove(index) {
if (this.currentForm.options.disabled) { if (this.form.options.disabled) {
return return
} }
this.model.splice(index, 1) this.model.splice(index, 1)
}, },
// 提交 // 提交
async handleSubmit() { async handleSubmit() {
if (this.currentForm.options.disabled || !this.update) { if (this.form.options.disabled) return
return
}
const form = this.$refs.form const form = this.$refs.form
const formCompoents = Array.isArray(form) ? form : [form] const formComponents = Array.isArray(form) ? form : [form]
const allPromise = formCompoents.map(form => form.validate()) const allPromise = formComponents.map(form => form.$form.validate())
await Promise.all(allPromise).then(() => { try {
return this.updateData(this.model) await Promise.all(allPromise)
}) if (this.page.onUpdate) {
return await this.page.onUpdate(this.update.beforeRequest(this.model))
} else {
return await this.updateData()
}
} catch (error) {
console.log(error)
}
}, },
// 上一步 // 上一步
async handlePrev() { async handlePrev() {
if (this.form.prev.isSubmit) { if (this.page.onPrev) await this.page.onPrev(this.model)
await this.handleSubmit() if (this.form.triggerSubmitOnChangeStep) await this.handleSubmit()
} this.$emit('prev', this.page.prev)
this.$emit('prev', this.form.prev.to)
}, },
// 下一步 // 下一步
async handleNext() { async handleNext() {
if (this.form.next.isSubmit) { if (this.page.onNext) await this.page.onNext(this.model)
await this.handleSubmit() if (this.form.triggerSubmitOnChangeStep) await this.handleSubmit()
this.$emit('next', this.page.next)
} }
this.$emit('next', this.form.next.to)
}
},
beforeMount() {
this.init()
} }
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.v-form-pane__hint {
margin-bottom: 20px;
}
.v-form-group { .v-form-group {
position: relative; position: relative;
margin-bottom: 20px; margin-bottom: 20px;
...@@ -308,8 +269,11 @@ export default { ...@@ -308,8 +269,11 @@ export default {
margin-top: 20px; margin-top: 20px;
padding: 20px 0; padding: 20px 0;
border-top: 1px solid #f1f1f1; border-top: 1px solid #f1f1f1;
.el-button + .el-button { }
margin-left: 20px; .v-form-pane__prepend {
} margin-bottom: 20px;
}
.v-form-pane__append {
margin-top: 20px;
} }
</style> </style>
<template>
<div class="v-menu">
<div class="v-menu__item" v-for="(item, index) in menus" :key="index">
<div class="v-menu__title">{{ item.title }}</div>
<div class="v-submenu" v-if="item.children">
<div class="v-submenu__item" :class="{ 'is-active': item.id === value }" v-for="item in item.children" :key="item.id" @click="handleClick(item)">
<a :href="item.href" :target="item.target || '_blank'" v-if="item.href">
<em v-if="item.required">*</em><span>{{ item.title }}</span>
</a>
<template v-else>
<em v-if="item.required">*</em><span>{{ item.title }}</span>
</template>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'VMenu',
props: {
menus: { type: Array, default: () => [] },
value: { type: String, default: '' }
},
methods: {
handleClick(item) {
if (item.href) return
if (item.onClick) return item.onClick(item)
this.$emit('input', item.id)
this.$emit('change', item.id, item)
}
}
}
</script>
<style lang="scss">
.v-menu {
margin: 20px 0;
}
.v-menu__item {
margin-bottom: 10px;
}
.v-menu__title {
padding-left: 60px;
height: 44px;
font-size: 14px;
font-weight: bold;
line-height: 44px;
color: #222;
background: #fff4ee;
border-left-style: solid;
border-left-width: 4px;
border-left-color: var(--main-color);
}
.v-submenu {
padding: 10px 0;
}
.v-submenu__item {
padding-left: 64px;
font-size: 14px;
line-height: 34px;
color: #666;
cursor: pointer;
}
.v-submenu__item.is-active {
color: var(--main-color);
}
.v-submenu__item em {
color: var(--main-color);
}
</style>
<template> <template>
<div class="v-submenu"> <div class="v-submenu">
<template v-for="item in menus"> <div class="v-submenu__item" :class="{ 'is-active': item.isActive }" v-for="item in menus" :key="item.id" @click="handleSelect(item)">
<div <a :href="item.href" :target="item.target || '_blank'" v-if="item.href">
:class="{ 'v-submenu__item': true, 'is-active': item.isActive }"
:key="item.id"
@click="handleSelect(item)"
v-if="item.show === undefined ? true : item.show"
>
<template v-if="item.href">
<a :href="item.href" :target="item.target || '_blank'">
<em v-if="item.required">*</em><span>{{ item.title }}</span> <em v-if="item.required">*</em><span>{{ item.title }}</span>
</a> </a>
</template>
<template v-else> <template v-else>
<em v-if="item.required">*</em><span>{{ item.title }}</span> <em v-if="item.required">*</em><span>{{ item.title }}</span>
</template> </template>
</div> </div>
</template>
</div> </div>
</template> </template>
...@@ -24,25 +15,17 @@ ...@@ -24,25 +15,17 @@
export default { export default {
name: 'VSubmenu', name: 'VSubmenu',
props: { datalist: { type: Array, default: () => [] } }, props: { datalist: { type: Array, default: () => [] } },
data() {
return {}
},
computed: { computed: {
menus() { menus() {
return this.datalist.filter(item => { return this.datalist.filter(item => {
return item.visible === undefined || item.visible.call(this.$parent.$parent) return (item.show === undefined ? true : item.show) || item.visible === undefined || item.visible.call(this.$parent.$parent)
}) })
} }
}, },
methods: { methods: {
handleSelect(item) { handleSelect(item) {
if (item.href) { if (item.href) return
return if (item.onClick) return item.onClick(this)
}
if (item.onClick) {
item.onClick(this)
return
}
this.$emit('select', item.id, item) this.$emit('select', item.id, item)
} }
} }
......
...@@ -27,11 +27,7 @@ ...@@ -27,11 +27,7 @@
<span class="el-upload-list__item-preview" @click="handlePreview(file)"> <span class="el-upload-list__item-preview" @click="handlePreview(file)">
<i class="el-icon-zoom-in"></i> <i class="el-icon-zoom-in"></i>
</span> </span>
<span <span v-if="!uploadDisabled && !file.disabled" class="el-upload-list__item-delete" @click="handleRemove(file)">
v-if="!uploadDisabled && !file.disabled"
class="el-upload-list__item-delete"
@click="handleRemove(file)"
>
<i class="el-icon-delete"></i> <i class="el-icon-delete"></i>
</span> </span>
</span> </span>
...@@ -144,12 +140,7 @@ export default { ...@@ -144,12 +140,7 @@ export default {
// 上传成功 // 上传成功
handleSuccess(res) { handleSuccess(res) {
this.files = res.data.material.attachments.filter(item => { this.files = res.data.material.attachments.filter(item => {
return ( return item.file_type_id === this.options.model || (this.options.model === 'RECOMMENDATION_LETTER' && item.file_type_id === 'RECOMMENDATION_LETTER_2' && this.limit !== 1)
item.file_type_id === this.options.model ||
(this.options.model === 'RECOMMENDATION_LETTER' &&
item.file_type_id === 'RECOMMENDATION_LETTER_2' &&
this.limit !== 1)
)
}) })
this.data[this.options.model] = this.files this.data[this.options.model] = this.files
this.$emit('uploaded', res) this.$emit('uploaded', res)
......
export const a = () => ({
id: '',
title: '推荐信',
prepend: '',
append: '',
required: true,
form: {
prepend: '',
append: '',
model: {},
items: [],
options: { disabled: false },
triggerSubmitOnChangeStep: true,
submitText: '保存',
hasSubmit: true,
hasButton: true
},
visible() {},
async onPrev() {},
async onNext() {},
async onUpdate(params) {
return params
},
get: {
action: '',
headers: {},
params: {},
beforeRequest() {},
callback() {},
errorCallback() {}
},
update: {
action: '',
headers: {},
data: {},
beforeRequest() {},
callback() {},
errorCallback() {}
}
})
## 组件简介
| 字段值 | 说明 | 字段属性 | 默认值 |
| ------- | ------------------------- | ------- | ----- |
| `type` | 类型:`String`; 说明:组件类型名 | 自定义字段 | `checkbox-group-form` |
| `label` | 类型:`String`; 说明:组件左侧显示名称 | element-ui el-form-item对应字段 | `''` |
| `label-width` | 类型:`String`; 说明:组件左侧显示名称宽度(加单位),父级设置可以子级继承 | element-ui el-form-item对应字段 | `''` |
| `required` | 类型:`Boolean`; 说明:标识是否必填 | element-ui el-form-item对应字段 | `false` |
| `disabled` | 类型:`Boolean`; 说明:标识是否只读 | element-ui el-form-item对应字段 | `false` |
| `model` | 类型:`String`; 说明:表单提交name值和回显对照字段 | 自定义字段 | `''` |
| `model-width` | 类型:`String`; 说明:右侧输入组件宽度(加单位) | 自定义字段 | `'89%'` |
| `placeholder` | 类型:`String`; 说明:组件input框中,默认提示文字 | element-ui el-input对应字段 | `''` |
| `values` | 类型:`Array`; 说明:里面是选择类型值label和value(值可以是 int 或 str),选择组 | 自定义字段 | `[]` |
| `attrs` | 类型:`Object`; 说明:定义标签上Data属性值 | element-ui对应字段 | `{}` |
| `rules` | 类型:`Array`; 说明:组件错误提示规则 | element-ui el-form-item对应字段 | `[]` |
### Demo:
``` js
return {
type: 'checkbox-group-form',
label: '性别',
labelWidth: '160px',
required: true,
disabled: false,
model: 'gender', // 特别注意,这个model是数组
modelWidth: '',
values: [{ label: '男', value: 1 }, { label: '女', value: 2 }],
attrs: {},
rules: []
}
```
* 其他属性 [参考文档]([https://](https://element.eleme.cn/#/zh-CN/component/input))
import CheckboxGroup from './src/checkboxGroupForm'
/* istanbul ignore next */
CheckboxGroup.install = function (Vue) {
Vue.component(CheckboxGroup.name, CheckboxGroup)
}
export default CheckboxGroup
<template>
<div class="radio-group-form">
<el-form-item
:key="item.model"
:prop="item.model"
:label="item.label || ''"
:label-width="item.labelWidth || item['label-width'] || ''"
:required="item.required || false"
:rules="item.rules || []"
:size="item.size"
>
<el-checkbox-group
v-bind="item.attrs"
v-on="$listeners"
v-model="formData[item.model]"
:style="{ width: item.modelWidth || item['model-width'] || '89%' }"
:disabled="item.disabled || false"
>
<el-checkbox
v-for="checkbox in item.values"
:label="checkbox.value"
:key="checkbox.value"
>{{checkbox.label}}</el-checkbox>
</el-checkbox-group>
</el-form-item>
</div>
</template>
<script>
export default {
name: 'CheckboxGroupForm',
componentName: 'CheckboxGroupForm',
props: {
item: {
type: Object,
default () {
return {}
}
},
formData: {
type: Object,
default () {
return {}
}
}
},
data () {
return {}
}
}
</script>
## 组件简介
| 字段值 | 说明 | 字段属性 | 默认值 |
| ------- | ------------------------- | ------- | ----- |
| `type` | 类型:`String`; 说明:组件类型名 | 自定义字段 | `city-select-form` |
| `label` | 类型:`String`; 说明:组件左侧显示名称 | element-ui el-form-item对应字段 | `''` |
| `label-width` | 类型:`String`; 说明:组件左侧显示名称宽度(加单位),父级设置可以子级继承 | element-ui el-form-item对应字段 | `''` |
| `required` | 类型:`Boolean`; 说明:标识是否必填 | element-ui el-form-item对应字段 | `false` |
| `disabled` | 类型:`Boolean`; 说明:标识是否只读 | element-ui el-form-item对应字段 | `false` |
| `model` | 类型:`String`; 说明:表单提交name值和回显对照字段 | 自定义字段 | `''` |
| `separator` | 类型:`String`; 说明:回显时,值间隔符 | 自定义字段 | `'-'` |
| `model-width` | 类型:`String`; 说明:右侧输入组件,每一个单独宽度(加单位) | 自定义字段 | `'100px'` |
| `placeholder$0` | 类型:`String`; 说明:组件input框中,默认提示文字 | element-ui el-input对应字段 | `''` |
| `attrs$0` | 类型:`Object`; 说明:定义标签上Data属性值 | element-ui对应字段 | `{}` |
| `rules` | 类型:`Array`; 说明:组件错误提示规则 | element-ui el-form-item对应字段 | `[]` |
### Demo Example:
``` js
return {
type: 'city-select-form',
label: '现居住城市',
labelWidth: '160px',
required: true,
disabled: false,
model: 'city_select_str',
separator: '-',
modelWidth: '',
placeholder0: '请输入省份',
placeholder1: '请输入城市',
attrs0: {},
attrs1: {},
rules: []
}
```
* 其他属性 [参考文档]([https://](https://element.eleme.cn/#/zh-CN/component/input))
import CitySelect from './src/citySelectForm'
/* istanbul ignore next */
CitySelect.install = function (Vue) {
Vue.component(CitySelect.name, CitySelect)
}
export default CitySelect
/* 按照这个 结构定义,支持扩展,并无限往下延伸 */
export default {
2: {
52: {
500: '东城区',
501: '西城区',
502: '海淀区',
503: '朝阳区',
504: '崇文区',
505: '宣武区',
506: '丰台区',
507: '石景山区',
508: '房山区',
509: '门头沟区',
510: '通州区',
511: '顺义区',
512: '昌平区',
513: '怀柔区',
514: '平谷区',
515: '大兴区',
516: '密云县',
517: '延庆县',
name: '北京'
},
name: '北京'
},
3: {
36: {
398: '迎江区',
399: '大观区',
400: '宜秀区',
401: '桐城市',
402: '怀宁县',
403: '枞阳县',
404: '潜山县',
405: '太湖县',
406: '宿松县',
407: '望江县',
408: '岳西县',
name: '安庆'
},
37: {
409: '中市区',
410: '东市区',
411: '西市区',
412: '郊区',
413: '怀远县',
414: '五河县',
415: '固镇县',
name: '蚌埠'
},
38: {
416: '居巢区',
417: '庐江县',
418: '无为县',
419: '含山县',
420: '和县',
name: '巢湖'
},
39: {
421: '贵池区',
422: '东至县',
423: '石台县',
424: '青阳县',
name: '池州'
},
40: {
425: '琅琊区',
426: '南谯区',
427: '天长市',
428: '明光市',
429: '来安县',
430: '全椒县',
431: '定远县',
432: '凤阳县',
name: '滁州'
},
41: {
433: '蚌山区',
434: '龙子湖区',
435: '禹会区',
436: '淮上区',
437: '颍州区',
438: '颍东区',
439: '颍泉区',
440: '界首市',
441: '临泉县',
442: '太和县',
443: '阜南县',
444: '颖上县',
name: '阜阳'
},
42: {
445: '相山区',
446: '杜集区',
447: '烈山区',
448: '濉溪县',
name: '淮北'
},
43: {
449: '田家庵区',
450: '大通区',
451: '谢家集区',
452: '八公山区',
453: '潘集区',
454: '凤台县',
name: '淮南'
},
44: {
455: '屯溪区',
456: '黄山区',
457: '徽州区',
458: '歙县',
459: '休宁县',
460: '黟县',
461: '祁门县',
name: '黄山'
},
45: {
462: '金安区',
463: '裕安区',
464: '寿县',
465: '霍邱县',
466: '舒城县',
467: '金寨县',
468: '霍山县',
name: '六安'
},
46: {
469: '雨山区',
470: '花山区',
471: '金家庄区',
472: '当涂县',
name: '马鞍山'
},
47: {
473: '埇桥区',
474: '砀山县',
475: '萧县',
476: '灵璧县',
477: '泗县',
name: '宿州'
},
48: {
478: '铜官山区',
479: '狮子山区',
480: '郊区',
481: '铜陵县',
name: '铜陵'
},
49: {
482: '镜湖区',
483: '弋江区',
484: '鸠江区',
485: '三山区',
486: '芜湖县',
487: '繁昌县',
488: '南陵县',
name: '芜湖'
},
50: {
489: '宣州区',
490: '宁国市',
491: '郎溪县',
492: '广德县',
493: '泾县',
494: '绩溪县',
495: '旌德县',
name: '宣城'
},
51: {
496: '涡阳县',
497: '蒙城县',
498: '利辛县',
499: '谯城区',
name: '亳州'
},
3401: {
3402: '庐阳区',
3403: '瑶海区',
3404: '蜀山区',
3405: '包河区',
3406: '长丰县',
3407: '肥东县',
3408: '肥西县',
name: '合肥'
},
name: '安徽'
},
4: {
53: {
518: '鼓楼区',
519: '台江区',
520: '仓山区',
521: '马尾区',
522: '晋安区',
523: '福清市',
524: '长乐市',
525: '闽侯县',
526: '连江县',
527: '罗源县',
528: '闽清县',
529: '永泰县',
530: '平潭县',
name: '福州'
},
54: {
531: '新罗区',
532: '漳平市',
533: '长汀县',
534: '永定县',
535: '上杭县',
536: '武平县',
537: '连城县',
name: '龙岩'
},
55: {
538: '延平区',
539: '邵武市',
540: '武夷山市',
541: '建瓯市',
542: '建阳市',
543: '顺昌县',
544: '浦城县',
545: '光泽县',
546: '松溪县',
547: '政和县',
name: '南平'
},
56: {
548: '蕉城区',
549: '福安市',
550: '福鼎市',
551: '霞浦县',
552: '古田县',
553: '屏南县',
554: '寿宁县',
555: '周宁县',
556: '柘荣县',
name: '宁德'
},
57: {
557: '城厢区',
558: '涵江区',
559: '荔城区',
560: '秀屿区',
561: '仙游县',
name: '莆田'
},
58: {
562: '鲤城区',
563: '丰泽区',
564: '洛江区',
565: '清濛开发区',
566: '泉港区',
567: '石狮市',
568: '晋江市',
569: '南安市',
570: '惠安县',
571: '安溪县',
572: '永春县',
573: '德化县',
574: '金门县',
name: '泉州'
},
59: {
575: '梅列区',
576: '三元区',
577: '永安市',
578: '明溪县',
579: '清流县',
580: '宁化县',
581: '大田县',
582: '尤溪县',
583: '沙县',
584: '将乐县',
585: '泰宁县',
586: '建宁县',
name: '三明'
},
60: {
587: '思明区',
588: '海沧区',
589: '湖里区',
590: '集美区',
591: '同安区',
592: '翔安区',
name: '厦门'
},
61: {
593: '芗城区',
594: '龙文区',
595: '龙海市',
596: '云霄县',
597: '漳浦县',
598: '诏安县',
599: '长泰县',
600: '东山县',
601: '南靖县',
602: '平和县',
603: '华安县',
name: '漳州'
},
name: '福建'
},
5: {
62: {
604: '皋兰县',
605: '城关区',
606: '七里河区',
607: '西固区',
608: '安宁区',
609: '红古区',
610: '永登县',
611: '榆中县',
name: '兰州'
},
63: {
612: '白银区',
613: '平川区',
614: '会宁县',
615: '景泰县',
616: '靖远县',
name: '白银'
},
64: {
617: '临洮县',
618: '陇西县',
619: '通渭县',
620: '渭源县',
621: '漳县',
622: '岷县',
623: '安定区',
624: '安定区',
name: '定西'
},
65: {
625: '合作市',
626: '临潭县',
627: '卓尼县',
628: '舟曲县',
629: '迭部县',
630: '玛曲县',
631: '碌曲县',
632: '夏河县',
name: '甘南'
},
66: {
633: '嘉峪关市',
name: '嘉峪关'
},
67: {
634: '金川区',
635: '永昌县',
name: '金昌'
},
68: {
636: '肃州区',
637: '玉门市',
638: '敦煌市',
639: '金塔县',
640: '瓜州县',
641: '肃北',
642: '阿克塞',
name: '酒泉'
},
69: {
643: '临夏市',
644: '临夏县',
645: '康乐县',
646: '永靖县',
647: '广河县',
648: '和政县',
649: '东乡族自治县',
650: '积石山',
name: '临夏'
},
70: {
651: '成县',
652: '徽县',
653: '康县',
654: '礼县',
655: '两当县',
656: '文县',
657: '西和县',
658: '宕昌县',
659: '武都区',
name: '陇南'
},
71: {
660: '崇信县',
661: '华亭县',
662: '静宁县',
663: '灵台县',
664: '崆峒区',
665: '庄浪县',
666: '泾川县',
name: '平凉'
},
72: {
667: '合水县',
668: '华池县',
669: '环县',
670: '宁县',
671: '庆城县',
672: '西峰区',
673: '镇原县',
674: '正宁县',
name: '庆阳'
},
73: {
675: '甘谷县',
676: '秦安县',
677: '清水县',
678: '秦州区',
679: '麦积区',
680: '武山县',
681: '张家川',
name: '天水'
},
74: {
682: '古浪县',
683: '民勤县',
684: '天祝',
685: '凉州区',
name: '武威'
},
75: {
686: '高台县',
687: '临泽县',
688: '民乐县',
689: '山丹县',
690: '肃南',
691: '甘州区',
name: '张掖'
},
name: '甘肃'
},
6: {
76: {
692: '从化市',
693: '天河区',
694: '东山区',
695: '白云区',
696: '海珠区',
697: '荔湾区',
698: '越秀区',
699: '黄埔区',
700: '番禺区',
701: '花都区',
702: '增城区',
703: '从化区',
704: '市郊',
name: '广州'
},
77: {
705: '福田区',
706: '罗湖区',
707: '南山区',
708: '宝安区',
709: '龙岗区',
710: '盐田区',
name: '深圳'
},
78: {
711: '湘桥区',
712: '潮安县',
713: '饶平县',
name: '潮州'
},
79: {
714: '南城区',
715: '东城区',
716: '万江区',
717: '莞城区',
718: '石龙镇',
719: '虎门镇',
720: '麻涌镇',
721: '道滘镇',
722: '石碣镇',
723: '沙田镇',
724: '望牛墩镇',
725: '洪梅镇',
726: '茶山镇',
727: '寮步镇',
728: '大岭山镇',
729: '大朗镇',
730: '黄江镇',
731: '樟木头',
732: '凤岗镇',
733: '塘厦镇',
734: '谢岗镇',
735: '厚街镇',
736: '清溪镇',
737: '常平镇',
738: '桥头镇',
739: '横沥镇',
740: '东坑镇',
741: '企石镇',
742: '石排镇',
743: '长安镇',
744: '中堂镇',
745: '高埗镇',
name: '东莞'
},
80: {
746: '禅城区',
747: '南海区',
748: '顺德区',
749: '三水区',
750: '高明区',
name: '佛山'
},
81: {
751: '东源县',
752: '和平县',
753: '源城区',
754: '连平县',
755: '龙川县',
756: '紫金县',
name: '河源'
},
82: {
757: '惠阳区',
758: '惠城区',
759: '大亚湾',
760: '博罗县',
761: '惠东县',
762: '龙门县',
name: '惠州'
},
83: {
763: '江海区',
764: '蓬江区',
765: '新会区',
766: '台山市',
767: '开平市',
768: '鹤山市',
769: '恩平市',
name: '江门'
},
84: {
770: '榕城区',
771: '普宁市',
772: '揭东县',
773: '揭西县',
774: '惠来县',
name: '揭阳'
},
85: {
775: '茂南区',
776: '茂港区',
777: '高州市',
778: '化州市',
779: '信宜市',
780: '电白县',
name: '茂名'
},
86: {
781: '梅县',
782: '梅江区',
783: '兴宁市',
784: '大埔县',
785: '丰顺县',
786: '五华县',
787: '平远县',
788: '蕉岭县',
name: '梅州'
},
87: {
789: '清城区',
790: '英德市',
791: '连州市',
792: '佛冈县',
793: '阳山县',
794: '清新县',
795: '连山',
796: '连南',
name: '清远'
},
88: {
797: '南澳县',
798: '潮阳区',
799: '澄海区',
800: '龙湖区',
801: '金平区',
802: '濠江区',
803: '潮南区',
name: '汕头'
},
89: {
804: '城区',
805: '陆丰市',
806: '海丰县',
807: '陆河县',
name: '汕尾'
},
90: {
808: '曲江县',
809: '浈江区',
810: '武江区',
811: '曲江区',
812: '乐昌市',
813: '南雄市',
814: '始兴县',
815: '仁化县',
816: '翁源县',
817: '新丰县',
818: '乳源',
name: '韶关'
},
91: {
819: '江城区',
820: '阳春市',
821: '阳西县',
822: '阳东县',
name: '阳江'
},
92: {
823: '云城区',
824: '罗定市',
825: '新兴县',
826: '郁南县',
827: '云安县',
name: '云浮'
},
93: {
828: '赤坎区',
829: '霞山区',
830: '坡头区',
831: '麻章区',
832: '廉江市',
833: '雷州市',
834: '吴川市',
835: '遂溪县',
836: '徐闻县',
name: '湛江'
},
94: {
837: '肇庆市',
838: '高要市',
839: '四会市',
840: '广宁县',
841: '怀集县',
842: '封开县',
843: '德庆县',
name: '肇庆'
},
95: {
844: '石岐街道',
845: '东区街道',
846: '西区街道',
847: '环城街道',
848: '中山港街道',
849: '五桂山街道',
name: '中山'
},
96: {
850: '香洲区',
851: '斗门区',
852: '金湾区',
name: '珠海'
},
name: '广东'
},
7: {
97: {
853: '邕宁区',
854: '青秀区',
855: '兴宁区',
856: '良庆区',
857: '西乡塘区',
858: '江南区',
859: '武鸣县',
860: '隆安县',
861: '马山县',
862: '上林县',
863: '宾阳县',
864: '横县',
name: '南宁'
},
98: {
865: '秀峰区',
866: '叠彩区',
867: '象山区',
868: '七星区',
869: '雁山区',
870: '阳朔县',
871: '临桂县',
872: '灵川县',
873: '全州县',
874: '平乐县',
875: '兴安县',
876: '灌阳县',
877: '荔浦县',
878: '资源县',
879: '永福县',
880: '龙胜',
881: '恭城',
name: '桂林'
},
99: {
882: '右江区',
883: '凌云县',
884: '平果县',
885: '西林县',
886: '乐业县',
887: '德保县',
888: '田林县',
889: '田阳县',
890: '靖西县',
891: '田东县',
892: '那坡县',
893: '隆林',
name: '百色'
},
100: {
894: '海城区',
895: '银海区',
896: '铁山港区',
897: '合浦县',
name: '北海'
},
101: {
898: '江州区',
899: '凭祥市',
900: '宁明县',
901: '扶绥县',
902: '龙州县',
903: '大新县',
904: '天等县',
name: '崇左'
},
102: {
905: '港口区',
906: '防城区',
907: '东兴市',
908: '上思县',
name: '防城港'
},
103: {
909: '港北区',
910: '港南区',
911: '覃塘区',
912: '桂平市',
913: '平南县',
name: '贵港'
},
104: {
914: '金城江区',
915: '宜州市',
916: '天峨县',
917: '凤山县',
918: '南丹县',
919: '东兰县',
920: '都安',
921: '罗城',
922: '巴马',
923: '环江',
924: '大化',
name: '河池'
},
105: {
925: '八步区',
926: '钟山县',
927: '昭平县',
928: '富川',
name: '贺州'
},
106: {
929: '兴宾区',
930: '合山市',
931: '象州县',
932: '武宣县',
933: '忻城县',
934: '金秀',
name: '来宾'
},
107: {
935: '城中区',
936: '鱼峰区',
937: '柳北区',
938: '柳南区',
939: '柳江县',
940: '柳城县',
941: '鹿寨县',
942: '融安县',
943: '融水',
944: '三江',
name: '柳州'
},
108: {
945: '钦南区',
946: '钦北区',
947: '灵山县',
948: '浦北县',
name: '钦州'
},
109: {
949: '万秀区',
950: '蝶山区',
951: '长洲区',
952: '岑溪市',
953: '苍梧县',
954: '藤县',
955: '蒙山县',
name: '梧州'
},
110: {
956: '玉州区',
957: '北流市',
958: '容县',
959: '陆川县',
960: '博白县',
961: '兴业县',
name: '玉林'
},
name: '广西'
},
8: {
111: {
962: '南明区',
963: '云岩区',
964: '花溪区',
965: '乌当区',
966: '白云区',
967: '小河区',
968: '金阳新区',
969: '新天园区',
970: '清镇市',
971: '开阳县',
972: '修文县',
973: '息烽县',
name: '贵阳'
},
112: {
974: '西秀区',
975: '关岭',
976: '镇宁',
977: '紫云',
978: '平坝县',
979: '普定县',
name: '安顺'
},
113: {
980: '毕节市',
981: '大方县',
982: '黔西县',
983: '金沙县',
984: '织金县',
985: '纳雍县',
986: '赫章县',
987: '威宁',
name: '毕节'
},
114: {
988: '钟山区',
989: '六枝特区',
990: '水城县',
991: '盘县',
name: '六盘水'
},
115: {
992: '凯里市',
993: '黄平县',
994: '施秉县',
995: '三穗县',
996: '镇远县',
997: '岑巩县',
998: '天柱县',
999: '锦屏县',
1000: '剑河县',
1001: '台江县',
1002: '黎平县',
1003: '榕江县',
1004: '从江县',
1005: '雷山县',
1006: '麻江县',
1007: '丹寨县',
name: '黔东南'
},
116: {
1008: '都匀市',
1009: '福泉市',
1010: '荔波县',
1011: '贵定县',
1012: '瓮安县',
1013: '独山县',
1014: '平塘县',
1015: '罗甸县',
1016: '长顺县',
1017: '龙里县',
1018: '惠水县',
1019: '三都',
name: '黔南'
},
117: {
1020: '兴义市',
1021: '兴仁县',
1022: '普安县',
1023: '晴隆县',
1024: '贞丰县',
1025: '望谟县',
1026: '册亨县',
1027: '安龙县',
name: '黔西南'
},
118: {
1028: '铜仁市',
1029: '江口县',
1030: '石阡县',
1031: '思南县',
1032: '德江县',
1033: '玉屏',
1034: '印江',
1035: '沿河',
1036: '松桃',
1037: '万山特区',
name: '铜仁'
},
119: {
1038: '红花岗区',
1039: '务川县',
1040: '道真县',
1041: '汇川区',
1042: '赤水市',
1043: '仁怀市',
1044: '遵义县',
1045: '桐梓县',
1046: '绥阳县',
1047: '正安县',
1048: '凤冈县',
1049: '湄潭县',
1050: '余庆县',
1051: '习水县',
1052: '道真',
1053: '务川',
name: '遵义'
},
name: '贵州'
},
9: {
120: {
1054: '秀英区',
1055: '龙华区',
1056: '琼山区',
1057: '美兰区',
name: '海口'
},
121: {
name: '三亚'
},
122: {
name: '白沙'
},
123: {
name: '保亭'
},
124: {
name: '昌江'
},
125: {
name: '澄迈县'
},
126: {
name: '定安县'
},
127: {
name: '东方'
},
128: {
name: '乐东'
},
129: {
name: '临高县'
},
130: {
name: '陵水'
},
131: {
name: '琼海'
},
132: {
name: '琼中'
},
133: {
name: '屯昌县'
},
134: {
name: '万宁'
},
135: {
name: '文昌'
},
136: {
name: '五指山'
},
137: {
1058: '市区',
1059: '洋浦开发区',
1060: '那大镇',
1061: '王五镇',
1062: '雅星镇',
1063: '大成镇',
1064: '中和镇',
1065: '峨蔓镇',
1066: '南丰镇',
1067: '白马井镇',
1068: '兰洋镇',
1069: '和庆镇',
1070: '海头镇',
1071: '排浦镇',
1072: '东成镇',
1073: '光村镇',
1074: '木棠镇',
1075: '新州镇',
1076: '三都镇',
1077: '其他',
name: '儋州'
},
name: '海南'
},
10: {
138: {
1078: '长安区',
1079: '桥东区',
1080: '桥西区',
1081: '新华区',
1082: '裕华区',
1083: '井陉矿区',
1084: '高新区',
1085: '辛集市',
1086: '藁城市',
1087: '晋州市',
1088: '新乐市',
1089: '鹿泉市',
1090: '井陉县',
1091: '正定县',
1092: '栾城县',
1093: '行唐县',
1094: '灵寿县',
1095: '高邑县',
1096: '深泽县',
1097: '赞皇县',
1098: '无极县',
1099: '平山县',
1100: '元氏县',
1101: '赵县',
name: '石家庄'
},
139: {
1102: '新市区',
1103: '南市区',
1104: '北市区',
1105: '涿州市',
1106: '定州市',
1107: '安国市',
1108: '高碑店市',
1109: '满城县',
1110: '清苑县',
1111: '涞水县',
1112: '阜平县',
1113: '徐水县',
1114: '定兴县',
1115: '唐县',
1116: '高阳县',
1117: '容城县',
1118: '涞源县',
1119: '望都县',
1120: '安新县',
1121: '易县',
1122: '曲阳县',
1123: '蠡县',
1124: '顺平县',
1125: '博野县',
1126: '雄县',
name: '保定'
},
140: {
1127: '运河区',
1128: '新华区',
1129: '泊头市',
1130: '任丘市',
1131: '黄骅市',
1132: '河间市',
1133: '沧县',
1134: '青县',
1135: '东光县',
1136: '海兴县',
1137: '盐山县',
1138: '肃宁县',
1139: '南皮县',
1140: '吴桥县',
1141: '献县',
1142: '孟村',
name: '沧州'
},
141: {
1143: '双桥区',
1144: '双滦区',
1145: '鹰手营子矿区',
1146: '承德县',
1147: '兴隆县',
1148: '平泉县',
1149: '滦平县',
1150: '隆化县',
1151: '丰宁',
1152: '宽城',
1153: '围场',
name: '承德'
},
142: {
1154: '从台区',
1155: '复兴区',
1156: '邯山区',
1157: '峰峰矿区',
1158: '武安市',
1159: '邯郸县',
1160: '临漳县',
1161: '成安县',
1162: '大名县',
1163: '涉县',
1164: '磁县',
1165: '肥乡县',
1166: '永年县',
1167: '邱县',
1168: '鸡泽县',
1169: '广平县',
1170: '馆陶县',
1171: '魏县',
1172: '曲周县',
name: '邯郸'
},
143: {
1173: '桃城区',
1174: '冀州市',
1175: '深州市',
1176: '枣强县',
1177: '武邑县',
1178: '武强县',
1179: '饶阳县',
1180: '安平县',
1181: '故城县',
1182: '景县',
1183: '阜城县',
name: '衡水'
},
144: {
1184: '安次区',
1185: '广阳区',
1186: '霸州市',
1187: '三河市',
1188: '固安县',
1189: '永清县',
1190: '香河县',
1191: '大城县',
1192: '文安县',
1193: '大厂',
name: '廊坊'
},
145: {
1194: '海港区',
1195: '山海关区',
1196: '北戴河区',
1197: '昌黎县',
1198: '抚宁县',
1199: '卢龙县',
1200: '青龙',
name: '秦皇岛'
},
146: {
1201: '路北区',
1202: '路南区',
1203: '古冶区',
1204: '开平区',
1205: '丰南区',
1206: '丰润区',
1207: '遵化市',
1208: '迁安市',
1209: '滦县',
1210: '滦南县',
1211: '乐亭县',
1212: '迁西县',
1213: '玉田县',
1214: '唐海县',
name: '唐山'
},
147: {
1215: '桥东区',
1216: '桥西区',
1217: '南宫市',
1218: '沙河市',
1219: '邢台县',
1220: '临城县',
1221: '内丘县',
1222: '柏乡县',
1223: '隆尧县',
1224: '任县',
1225: '南和县',
1226: '宁晋县',
1227: '巨鹿县',
1228: '新河县',
1229: '广宗县',
1230: '平乡县',
1231: '威县',
1232: '清河县',
1233: '临西县',
name: '邢台'
},
148: {
1234: '桥西区',
1235: '桥东区',
1236: '宣化区',
1237: '下花园区',
1238: '宣化县',
1239: '张北县',
1240: '康保县',
1241: '沽源县',
1242: '尚义县',
1243: '蔚县',
1244: '阳原县',
1245: '怀安县',
1246: '万全县',
1247: '怀来县',
1248: '涿鹿县',
1249: '赤城县',
1250: '崇礼县',
name: '张家口'
},
name: '河北'
},
11: {
149: {
1251: '金水区',
1252: '邙山区',
1253: '二七区',
1254: '管城区',
1255: '中原区',
1256: '上街区',
1257: '惠济区',
1258: '郑东新区',
1259: '经济技术开发区',
1260: '高新开发区',
1261: '出口加工区',
1262: '巩义市',
1263: '荥阳市',
1264: '新密市',
1265: '新郑市',
1266: '登封市',
1267: '中牟县',
name: '郑州'
},
150: {
1268: '西工区',
1269: '老城区',
1270: '涧西区',
1271: '瀍河回族区',
1272: '洛龙区',
1273: '吉利区',
1274: '偃师市',
1275: '孟津县',
1276: '新安县',
1277: '栾川县',
1278: '嵩县',
1279: '汝阳县',
1280: '宜阳县',
1281: '洛宁县',
1282: '伊川县',
name: '洛阳'
},
151: {
1283: '鼓楼区',
1284: '龙亭区',
1285: '顺河回族区',
1286: '金明区',
1287: '禹王台区',
1288: '杞县',
1289: '通许县',
1290: '尉氏县',
1291: '开封县',
1292: '兰考县',
name: '开封'
},
152: {
1293: '北关区',
1294: '文峰区',
1295: '殷都区',
1296: '龙安区',
1297: '林州市',
1298: '安阳县',
1299: '汤阴县',
1300: '滑县',
1301: '内黄县',
name: '安阳'
},
153: {
1302: '淇滨区',
1303: '山城区',
1304: '鹤山区',
1305: '浚县',
1306: '淇县',
name: '鹤壁'
},
154: {
1307: '济源市',
name: '济源'
},
155: {
1308: '解放区',
1309: '中站区',
1310: '马村区',
1311: '山阳区',
1312: '沁阳市',
1313: '孟州市',
1314: '修武县',
1315: '博爱县',
1316: '武陟县',
1317: '温县',
name: '焦作'
},
156: {
1318: '卧龙区',
1319: '宛城区',
1320: '邓州市',
1321: '南召县',
1322: '方城县',
1323: '西峡县',
1324: '镇平县',
1325: '内乡县',
1326: '淅川县',
1327: '社旗县',
1328: '唐河县',
1329: '新野县',
1330: '桐柏县',
name: '南阳'
},
157: {
1331: '新华区',
1332: '卫东区',
1333: '湛河区',
1334: '石龙区',
1335: '舞钢市',
1336: '汝州市',
1337: '宝丰县',
1338: '叶县',
1339: '鲁山县',
1340: '郏县',
name: '平顶山'
},
158: {
1341: '湖滨区',
1342: '义马市',
1343: '灵宝市',
1344: '渑池县',
1345: '陕县',
1346: '卢氏县',
name: '三门峡'
},
159: {
1347: '梁园区',
1348: '睢阳区',
1349: '永城市',
1350: '民权县',
1351: '睢县',
1352: '宁陵县',
1353: '虞城县',
1354: '柘城县',
1355: '夏邑县',
name: '商丘'
},
160: {
1356: '卫滨区',
1357: '红旗区',
1358: '凤泉区',
1359: '牧野区',
1360: '卫辉市',
1361: '辉县市',
1362: '新乡县',
1363: '获嘉县',
1364: '原阳县',
1365: '延津县',
1366: '封丘县',
1367: '长垣县',
name: '新乡'
},
161: {
1368: '浉河区',
1369: '平桥区',
1370: '罗山县',
1371: '光山县',
1372: '新县',
1373: '商城县',
1374: '固始县',
1375: '潢川县',
1376: '淮滨县',
1377: '息县',
name: '信阳'
},
162: {
1378: '魏都区',
1379: '禹州市',
1380: '长葛市',
1381: '许昌县',
1382: '鄢陵县',
1383: '襄城县',
name: '许昌'
},
163: {
1384: '川汇区',
1385: '项城市',
1386: '扶沟县',
1387: '西华县',
1388: '商水县',
1389: '沈丘县',
1390: '郸城县',
1391: '淮阳县',
1392: '太康县',
1393: '鹿邑县',
name: '周口'
},
164: {
1394: '驿城区',
1395: '西平县',
1396: '上蔡县',
1397: '平舆县',
1398: '正阳县',
1399: '确山县',
1400: '泌阳县',
1401: '汝南县',
1402: '遂平县',
1403: '新蔡县',
name: '驻马店'
},
165: {
1404: '郾城区',
1405: '源汇区',
1406: '召陵区',
1407: '舞阳县',
1408: '临颍县',
name: '漯河'
},
166: {
1409: '华龙区',
1410: '清丰县',
1411: '南乐县',
1412: '范县',
1413: '台前县',
1414: '濮阳县',
name: '濮阳'
},
name: '河南'
},
12: {
167: {
1415: '道里区',
1416: '南岗区',
1417: '动力区',
1418: '平房区',
1419: '香坊区',
1420: '太平区',
1421: '道外区',
1422: '阿城区',
1423: '呼兰区',
1424: '松北区',
1425: '尚志市',
1426: '双城市',
1427: '五常市',
1428: '方正县',
1429: '宾县',
1430: '依兰县',
1431: '巴彦县',
1432: '通河县',
1433: '木兰县',
1434: '延寿县',
name: '哈尔滨'
},
168: {
1435: '萨尔图区',
1436: '红岗区',
1437: '龙凤区',
1438: '让胡路区',
1439: '大同区',
1440: '肇州县',
1441: '肇源县',
1442: '林甸县',
1443: '杜尔伯特',
name: '大庆'
},
169: {
1444: '呼玛县',
1445: '漠河县',
1446: '塔河县',
name: '大兴安岭'
},
170: {
1447: '兴山区',
1448: '工农区',
1449: '南山区',
1450: '兴安区',
1451: '向阳区',
1452: '东山区',
1453: '萝北县',
1454: '绥滨县',
name: '鹤岗'
},
171: {
1455: '爱辉区',
1456: '五大连池市',
1457: '北安市',
1458: '嫩江县',
1459: '逊克县',
1460: '孙吴县',
name: '黑河'
},
172: {
1461: '鸡冠区',
1462: '恒山区',
1463: '城子河区',
1464: '滴道区',
1465: '梨树区',
1466: '虎林市',
1467: '密山市',
1468: '鸡东县',
name: '鸡西'
},
173: {
1469: '前进区',
1470: '郊区',
1471: '向阳区',
1472: '东风区',
1473: '同江市',
1474: '富锦市',
1475: '桦南县',
1476: '桦川县',
1477: '汤原县',
1478: '抚远县',
name: '佳木斯'
},
174: {
1479: '爱民区',
1480: '东安区',
1481: '阳明区',
1482: '西安区',
1483: '绥芬河市',
1484: '海林市',
1485: '宁安市',
1486: '穆棱市',
1487: '东宁县',
1488: '林口县',
name: '牡丹江'
},
175: {
1489: '桃山区',
1490: '新兴区',
1491: '茄子河区',
1492: '勃利县',
name: '七台河'
},
176: {
1493: '龙沙区',
1494: '昂昂溪区',
1495: '铁峰区',
1496: '建华区',
1497: '富拉尔基区',
1498: '碾子山区',
1499: '梅里斯达斡尔区',
1500: '讷河市',
1501: '龙江县',
1502: '依安县',
1503: '泰来县',
1504: '甘南县',
1505: '富裕县',
1506: '克山县',
1507: '克东县',
1508: '拜泉县',
name: '齐齐哈尔'
},
177: {
1509: '尖山区',
1510: '岭东区',
1511: '四方台区',
1512: '宝山区',
1513: '集贤县',
1514: '友谊县',
1515: '宝清县',
1516: '饶河县',
name: '双鸭山'
},
178: {
1517: '北林区',
1518: '安达市',
1519: '肇东市',
1520: '海伦市',
1521: '望奎县',
1522: '兰西县',
1523: '青冈县',
1524: '庆安县',
1525: '明水县',
1526: '绥棱县',
name: '绥化'
},
179: {
1527: '伊春区',
1528: '带岭区',
1529: '南岔区',
1530: '金山屯区',
1531: '西林区',
1532: '美溪区',
1533: '乌马河区',
1534: '翠峦区',
1535: '友好区',
1536: '上甘岭区',
1537: '五营区',
1538: '红星区',
1539: '新青区',
1540: '汤旺河区',
1541: '乌伊岭区',
1542: '铁力市',
1543: '嘉荫县',
name: '伊春'
},
name: '黑龙江'
},
13: {
180: {
1544: '江岸区',
1545: '武昌区',
1546: '江汉区',
1547: '硚口区',
1548: '汉阳区',
1549: '青山区',
1550: '洪山区',
1551: '东西湖区',
1552: '汉南区',
1553: '蔡甸区',
1554: '江夏区',
1555: '黄陂区',
1556: '新洲区',
1557: '经济开发区',
name: '武汉'
},
181: {
1558: '仙桃市',
name: '仙桃'
},
182: {
1559: '鄂城区',
1560: '华容区',
1561: '梁子湖区',
name: '鄂州'
},
183: {
1562: '黄州区',
1563: '麻城市',
1564: '武穴市',
1565: '团风县',
1566: '红安县',
1567: '罗田县',
1568: '英山县',
1569: '浠水县',
1570: '蕲春县',
1571: '黄梅县',
name: '黄冈'
},
184: {
1572: '黄石港区',
1573: '西塞山区',
1574: '下陆区',
1575: '铁山区',
1576: '大冶市',
1577: '阳新县',
name: '黄石'
},
185: {
1578: '东宝区',
1579: '掇刀区',
1580: '钟祥市',
1581: '京山县',
1582: '沙洋县',
name: '荆门'
},
186: {
1583: '沙市区',
1584: '荆州区',
1585: '石首市',
1586: '洪湖市',
1587: '松滋市',
1588: '公安县',
1589: '监利县',
1590: '江陵县',
name: '荆州'
},
187: {
1591: '潜江市',
name: '潜江'
},
188: {
1592: '神农架林区',
name: '神农架林区'
},
189: {
1593: '张湾区',
1594: '茅箭区',
1595: '丹江口市',
1596: '郧县',
1597: '郧西县',
1598: '竹山县',
1599: '竹溪县',
1600: '房县',
name: '十堰'
},
190: {
1601: '曾都区',
1602: '广水市',
name: '随州'
},
191: {
1603: '天门市',
name: '天门'
},
192: {
1604: '咸安区',
1605: '赤壁市',
1606: '嘉鱼县',
1607: '通城县',
1608: '崇阳县',
1609: '通山县',
name: '咸宁'
},
193: {
1610: '襄城区',
1611: '樊城区',
1612: '襄阳区',
1613: '老河口市',
1614: '枣阳市',
1615: '宜城市',
1616: '南漳县',
1617: '谷城县',
1618: '保康县',
name: '襄樊'
},
194: {
1619: '孝南区',
1620: '应城市',
1621: '安陆市',
1622: '汉川市',
1623: '孝昌县',
1624: '大悟县',
1625: '云梦县',
name: '孝感'
},
195: {
1626: '长阳',
1627: '五峰',
1628: '西陵区',
1629: '伍家岗区',
1630: '点军区',
1631: '猇亭区',
1632: '夷陵区',
1633: '宜都市',
1634: '当阳市',
1635: '枝江市',
1636: '远安县',
1637: '兴山县',
1638: '秭归县',
name: '宜昌'
},
196: {
1639: '恩施市',
1640: '利川市',
1641: '建始县',
1642: '巴东县',
1643: '宣恩县',
1644: '咸丰县',
1645: '来凤县',
1646: '鹤峰县',
name: '恩施'
},
name: '湖北'
},
14: {
197: {
1647: '岳麓区',
1648: '芙蓉区',
1649: '天心区',
1650: '开福区',
1651: '雨花区',
1652: '开发区',
1653: '浏阳市',
1654: '长沙县',
1655: '望城县',
1656: '宁乡县',
name: '长沙'
},
198: {
1657: '永定区',
1658: '武陵源区',
1659: '慈利县',
1660: '桑植县',
name: '张家界'
},
199: {
1661: '武陵区',
1662: '鼎城区',
1663: '津市市',
1664: '安乡县',
1665: '汉寿县',
1666: '澧县',
1667: '临澧县',
1668: '桃源县',
1669: '石门县',
name: '常德'
},
200: {
1670: '北湖区',
1671: '苏仙区',
1672: '资兴市',
1673: '桂阳县',
1674: '宜章县',
1675: '永兴县',
1676: '嘉禾县',
1677: '临武县',
1678: '汝城县',
1679: '桂东县',
1680: '安仁县',
name: '郴州'
},
201: {
1681: '雁峰区',
1682: '珠晖区',
1683: '石鼓区',
1684: '蒸湘区',
1685: '南岳区',
1686: '耒阳市',
1687: '常宁市',
1688: '衡阳县',
1689: '衡南县',
1690: '衡山县',
1691: '衡东县',
1692: '祁东县',
name: '衡阳'
},
202: {
1693: '鹤城区',
1694: '靖州',
1695: '麻阳',
1696: '通道',
1697: '新晃',
1698: '芷江',
1699: '沅陵县',
1700: '辰溪县',
1701: '溆浦县',
1702: '中方县',
1703: '会同县',
1704: '洪江市',
name: '怀化'
},
203: {
1705: '娄星区',
1706: '冷水江市',
1707: '涟源市',
1708: '双峰县',
1709: '新化县',
name: '娄底'
},
204: {
1710: '城步',
1711: '双清区',
1712: '大祥区',
1713: '北塔区',
1714: '武冈市',
1715: '邵东县',
1716: '新邵县',
1717: '邵阳县',
1718: '隆回县',
1719: '洞口县',
1720: '绥宁县',
1721: '新宁县',
name: '邵阳'
},
205: {
1722: '岳塘区',
1723: '雨湖区',
1724: '湘乡市',
1725: '韶山市',
1726: '湘潭县',
name: '湘潭'
},
206: {
1727: '吉首市',
1728: '泸溪县',
1729: '凤凰县',
1730: '花垣县',
1731: '保靖县',
1732: '古丈县',
1733: '永顺县',
1734: '龙山县',
name: '湘西'
},
207: {
1735: '赫山区',
1736: '资阳区',
1737: '沅江市',
1738: '南县',
1739: '桃江县',
1740: '安化县',
name: '益阳'
},
208: {
1741: '江华',
1742: '冷水滩区',
1743: '零陵区',
1744: '祁阳县',
1745: '东安县',
1746: '双牌县',
1747: '道县',
1748: '江永县',
1749: '宁远县',
1750: '蓝山县',
1751: '新田县',
name: '永州'
},
209: {
1752: '岳阳楼区',
1753: '君山区',
1754: '云溪区',
1755: '汨罗市',
1756: '临湘市',
1757: '岳阳县',
1758: '华容县',
1759: '湘阴县',
1760: '平江县',
name: '岳阳'
},
210: {
1761: '天元区',
1762: '荷塘区',
1763: '芦淞区',
1764: '石峰区',
1765: '醴陵市',
1766: '株洲县',
1767: '攸县',
1768: '茶陵县',
1769: '炎陵县',
name: '株洲'
},
name: '湖南'
},
15: {
211: {
1770: '朝阳区',
1771: '宽城区',
1772: '二道区',
1773: '南关区',
1774: '绿园区',
1775: '双阳区',
1776: '净月潭开发区',
1777: '高新技术开发区',
1778: '经济技术开发区',
1779: '汽车产业开发区',
1780: '德惠市',
1781: '九台市',
1782: '榆树市',
1783: '农安县',
name: '长春'
},
212: {
1784: '船营区',
1785: '昌邑区',
1786: '龙潭区',
1787: '丰满区',
1788: '蛟河市',
1789: '桦甸市',
1790: '舒兰市',
1791: '磐石市',
1792: '永吉县',
name: '吉林'
},
213: {
1793: '洮北区',
1794: '洮南市',
1795: '大安市',
1796: '镇赉县',
1797: '通榆县',
name: '白城'
},
214: {
1798: '江源区',
1799: '八道江区',
1800: '长白',
1801: '临江市',
1802: '抚松县',
1803: '靖宇县',
name: '白山'
},
215: {
1804: '龙山区',
1805: '西安区',
1806: '东丰县',
1807: '东辽县',
name: '辽源'
},
216: {
1808: '铁西区',
1809: '铁东区',
1810: '伊通',
1811: '公主岭市',
1812: '双辽市',
1813: '梨树县',
name: '四平'
},
217: {
1814: '前郭尔罗斯',
1815: '宁江区',
1816: '长岭县',
1817: '乾安县',
1818: '扶余县',
name: '松原'
},
218: {
1819: '东昌区',
1820: '二道江区',
1821: '梅河口市',
1822: '集安市',
1823: '通化县',
1824: '辉南县',
1825: '柳河县',
name: '通化'
},
219: {
1826: '延吉市',
1827: '图们市',
1828: '敦化市',
1829: '珲春市',
1830: '龙井市',
1831: '和龙市',
1832: '安图县',
1833: '汪清县',
name: '延边'
},
name: '吉林'
},
16: {
220: {
1834: '玄武区',
1835: '鼓楼区',
1836: '白下区',
1837: '建邺区',
1838: '秦淮区',
1839: '雨花台区',
1840: '下关区',
1841: '栖霞区',
1842: '浦口区',
1843: '江宁区',
1844: '六合区',
1845: '溧水县',
1846: '高淳县',
name: '南京'
},
221: {
1847: '沧浪区',
1848: '金阊区',
1849: '平江区',
1850: '虎丘区',
1851: '吴中区',
1852: '相城区',
1853: '园区',
1854: '新区',
1855: '常熟市',
1856: '张家港市',
1857: '玉山镇',
1858: '巴城镇',
1859: '周市镇',
1860: '陆家镇',
1861: '花桥镇',
1862: '淀山湖镇',
1863: '张浦镇',
1864: '周庄镇',
1865: '千灯镇',
1866: '锦溪镇',
1867: '开发区',
1868: '吴江市',
1869: '太仓市',
name: '苏州'
},
222: {
1870: '崇安区',
1871: '北塘区',
1872: '南长区',
1873: '锡山区',
1874: '惠山区',
1875: '滨湖区',
1876: '新区',
1877: '江阴市',
1878: '宜兴市',
name: '无锡'
},
223: {
1879: '天宁区',
1880: '钟楼区',
1881: '戚墅堰区',
1882: '郊区',
1883: '新北区',
1884: '武进区',
1885: '溧阳市',
1886: '金坛市',
name: '常州'
},
224: {
1887: '清河区',
1888: '清浦区',
1889: '楚州区',
1890: '淮阴区',
1891: '涟水县',
1892: '洪泽县',
1893: '盱眙县',
1894: '金湖县',
name: '淮安'
},
225: {
1895: '新浦区',
1896: '连云区',
1897: '海州区',
1898: '赣榆县',
1899: '东海县',
1900: '灌云县',
1901: '灌南县',
name: '连云港'
},
226: {
1902: '崇川区',
1903: '港闸区',
1904: '经济开发区',
1905: '启东市',
1906: '如皋市',
1907: '通州市',
1908: '海门市',
1909: '海安县',
1910: '如东县',
name: '南通'
},
227: {
1911: '宿城区',
1912: '宿豫区',
1913: '宿豫县',
1914: '沭阳县',
1915: '泗阳县',
1916: '泗洪县',
name: '宿迁'
},
228: {
1917: '海陵区',
1918: '高港区',
1919: '兴化市',
1920: '靖江市',
1921: '泰兴市',
1922: '姜堰市',
name: '泰州'
},
229: {
1923: '云龙区',
1924: '鼓楼区',
1925: '九里区',
1926: '贾汪区',
1927: '泉山区',
1928: '新沂市',
1929: '邳州市',
1930: '丰县',
1931: '沛县',
1932: '铜山县',
1933: '睢宁县',
name: '徐州'
},
230: {
1934: '城区',
1935: '亭湖区',
1936: '盐都区',
1937: '盐都县',
1938: '东台市',
1939: '大丰市',
1940: '响水县',
1941: '滨海县',
1942: '阜宁县',
1943: '射阳县',
1944: '建湖县',
name: '盐城'
},
231: {
1945: '广陵区',
1946: '维扬区',
1947: '邗江区',
1948: '仪征市',
1949: '高邮市',
1950: '江都市',
1951: '宝应县',
name: '扬州'
},
232: {
1952: '京口区',
1953: '润州区',
1954: '丹徒区',
1955: '丹阳市',
1956: '扬中市',
1957: '句容市',
name: '镇江'
},
name: '江苏'
},
17: {
233: {
1958: '东湖区',
1959: '西湖区',
1960: '青云谱区',
1961: '湾里区',
1962: '青山湖区',
1963: '红谷滩新区',
1964: '昌北区',
1965: '高新区',
1966: '南昌县',
1967: '新建县',
1968: '安义县',
1969: '进贤县',
name: '南昌'
},
234: {
1970: '临川区',
1971: '南城县',
1972: '黎川县',
1973: '南丰县',
1974: '崇仁县',
1975: '乐安县',
1976: '宜黄县',
1977: '金溪县',
1978: '资溪县',
1979: '东乡县',
1980: '广昌县',
name: '抚州'
},
235: {
1981: '章贡区',
1982: '于都县',
1983: '瑞金市',
1984: '南康市',
1985: '赣县',
1986: '信丰县',
1987: '大余县',
1988: '上犹县',
1989: '崇义县',
1990: '安远县',
1991: '龙南县',
1992: '定南县',
1993: '全南县',
1994: '宁都县',
1995: '兴国县',
1996: '会昌县',
1997: '寻乌县',
1998: '石城县',
name: '赣州'
},
236: {
1999: '安福县',
2000: '吉州区',
2001: '青原区',
2002: '井冈山市',
2003: '吉安县',
2004: '吉水县',
2005: '峡江县',
2006: '新干县',
2007: '永丰县',
2008: '泰和县',
2009: '遂川县',
2010: '万安县',
2011: '永新县',
name: '吉安'
},
237: {
2012: '珠山区',
2013: '昌江区',
2014: '乐平市',
2015: '浮梁县',
name: '景德镇'
},
238: {
2016: '浔阳区',
2017: '庐山区',
2018: '瑞昌市',
2019: '九江县',
2020: '武宁县',
2021: '修水县',
2022: '永修县',
2023: '德安县',
2024: '星子县',
2025: '都昌县',
2026: '湖口县',
2027: '彭泽县',
name: '九江'
},
239: {
2028: '安源区',
2029: '湘东区',
2030: '莲花县',
2031: '芦溪县',
2032: '上栗县',
name: '萍乡'
},
240: {
2033: '信州区',
2034: '德兴市',
2035: '上饶县',
2036: '广丰县',
2037: '玉山县',
2038: '铅山县',
2039: '横峰县',
2040: '弋阳县',
2041: '余干县',
2042: '波阳县',
2043: '万年县',
2044: '婺源县',
name: '上饶'
},
241: {
2045: '渝水区',
2046: '分宜县',
name: '新余'
},
242: {
2047: '袁州区',
2048: '丰城市',
2049: '樟树市',
2050: '高安市',
2051: '奉新县',
2052: '万载县',
2053: '上高县',
2054: '宜丰县',
2055: '靖安县',
2056: '铜鼓县',
name: '宜春'
},
243: {
2057: '月湖区',
2058: '贵溪市',
2059: '余江县',
name: '鹰潭'
},
name: '江西'
},
18: {
244: {
2060: '沈河区',
2061: '皇姑区',
2062: '和平区',
2063: '大东区',
2064: '铁西区',
2065: '苏家屯区',
2066: '东陵区',
2067: '沈北新区',
2068: '于洪区',
2069: '浑南新区',
2070: '新民市',
2071: '辽中县',
2072: '康平县',
2073: '法库县',
name: '沈阳'
},
245: {
2074: '西岗区',
2075: '中山区',
2076: '沙河口区',
2077: '甘井子区',
2078: '旅顺口区',
2079: '金州区',
2080: '开发区',
2081: '瓦房店市',
2082: '普兰店市',
2083: '庄河市',
2084: '长海县',
name: '大连'
},
246: {
2085: '铁东区',
2086: '铁西区',
2087: '立山区',
2088: '千山区',
2089: '岫岩',
2090: '海城市',
2091: '台安县',
name: '鞍山'
},
247: {
2092: '本溪',
2093: '平山区',
2094: '明山区',
2095: '溪湖区',
2096: '南芬区',
2097: '桓仁',
name: '本溪'
},
248: {
2098: '双塔区',
2099: '龙城区',
2100: '喀喇沁左翼蒙古族自治县',
2101: '北票市',
2102: '凌源市',
2103: '朝阳县',
2104: '建平县',
name: '朝阳'
},
249: {
2105: '振兴区',
2106: '元宝区',
2107: '振安区',
2108: '宽甸',
2109: '东港市',
2110: '凤城市',
name: '丹东'
},
250: {
2111: '顺城区',
2112: '新抚区',
2113: '东洲区',
2114: '望花区',
2115: '清原',
2116: '新宾',
2117: '抚顺县',
name: '抚顺'
},
251: {
2118: '阜新',
2119: '海州区',
2120: '新邱区',
2121: '太平区',
2122: '清河门区',
2123: '细河区',
2124: '彰武县',
name: '阜新'
},
252: {
2125: '龙港区',
2126: '南票区',
2127: '连山区',
2128: '兴城市',
2129: '绥中县',
2130: '建昌县',
name: '葫芦岛'
},
253: {
2131: '太和区',
2132: '古塔区',
2133: '凌河区',
2134: '凌海市',
2135: '北镇市',
2136: '黑山县',
2137: '义县',
name: '锦州'
},
254: {
2138: '白塔区',
2139: '文圣区',
2140: '宏伟区',
2141: '太子河区',
2142: '弓长岭区',
2143: '灯塔市',
2144: '辽阳县',
name: '辽阳'
},
255: {
2145: '双台子区',
2146: '兴隆台区',
2147: '大洼县',
2148: '盘山县',
name: '盘锦'
},
256: {
2149: '银州区',
2150: '清河区',
2151: '调兵山市',
2152: '开原市',
2153: '铁岭县',
2154: '西丰县',
2155: '昌图县',
name: '铁岭'
},
257: {
2156: '站前区',
2157: '西市区',
2158: '鲅鱼圈区',
2159: '老边区',
2160: '盖州市',
2161: '大石桥市',
name: '营口'
},
name: '辽宁'
},
19: {
258: {
2162: '回民区',
2163: '玉泉区',
2164: '新城区',
2165: '赛罕区',
2166: '清水河县',
2167: '土默特左旗',
2168: '托克托县',
2169: '和林格尔县',
2170: '武川县',
name: '呼和浩特'
},
259: {
2171: '阿拉善左旗',
2172: '阿拉善右旗',
2173: '额济纳旗',
name: '阿拉善盟'
},
260: {
2174: '临河区',
2175: '五原县',
2176: '磴口县',
2177: '乌拉特前旗',
2178: '乌拉特中旗',
2179: '乌拉特后旗',
2180: '杭锦后旗',
name: '巴彦淖尔盟'
},
261: {
2181: '昆都仑区',
2182: '青山区',
2183: '东河区',
2184: '九原区',
2185: '石拐区',
2186: '白云矿区',
2187: '土默特右旗',
2188: '固阳县',
2189: '达尔罕茂明安联合旗',
name: '包头'
},
262: {
2190: '红山区',
2191: '元宝山区',
2192: '松山区',
2193: '阿鲁科尔沁旗',
2194: '巴林左旗',
2195: '巴林右旗',
2196: '林西县',
2197: '克什克腾旗',
2198: '翁牛特旗',
2199: '喀喇沁旗',
2200: '宁城县',
2201: '敖汉旗',
name: '赤峰'
},
263: {
2202: '东胜区',
2203: '达拉特旗',
2204: '准格尔旗',
2205: '鄂托克前旗',
2206: '鄂托克旗',
2207: '杭锦旗',
2208: '乌审旗',
2209: '伊金霍洛旗',
name: '鄂尔多斯'
},
264: {
2210: '海拉尔区',
2211: '莫力达瓦',
2212: '满洲里市',
2213: '牙克石市',
2214: '扎兰屯市',
2215: '额尔古纳市',
2216: '根河市',
2217: '阿荣旗',
2218: '鄂伦春自治旗',
2219: '鄂温克族自治旗',
2220: '陈巴尔虎旗',
2221: '新巴尔虎左旗',
2222: '新巴尔虎右旗',
name: '呼伦贝尔'
},
265: {
2223: '科尔沁区',
2224: '霍林郭勒市',
2225: '科尔沁左翼中旗',
2226: '科尔沁左翼后旗',
2227: '开鲁县',
2228: '库伦旗',
2229: '奈曼旗',
2230: '扎鲁特旗',
name: '通辽'
},
266: {
2231: '海勃湾区',
2232: '乌达区',
2233: '海南区',
name: '乌海'
},
267: {
2234: '化德县',
2235: '集宁区',
2236: '丰镇市',
2237: '卓资县',
2238: '商都县',
2239: '兴和县',
2240: '凉城县',
2241: '察哈尔右翼前旗',
2242: '察哈尔右翼中旗',
2243: '察哈尔右翼后旗',
2244: '四子王旗',
name: '乌兰察布市'
},
268: {
2245: '二连浩特市',
2246: '锡林浩特市',
2247: '阿巴嘎旗',
2248: '苏尼特左旗',
2249: '苏尼特右旗',
2250: '东乌珠穆沁旗',
2251: '西乌珠穆沁旗',
2252: '太仆寺旗',
2253: '镶黄旗',
2254: '正镶白旗',
2255: '正蓝旗',
2256: '多伦县',
name: '锡林郭勒盟'
},
269: {
2257: '乌兰浩特市',
2258: '阿尔山市',
2259: '科尔沁右翼前旗',
2260: '科尔沁右翼中旗',
2261: '扎赉特旗',
2262: '突泉县',
name: '兴安盟'
},
name: '内蒙古'
},
20: {
270: {
2263: '西夏区',
2264: '金凤区',
2265: '兴庆区',
2266: '灵武市',
2267: '永宁县',
2268: '贺兰县',
name: '银川'
},
271: {
2269: '原州区',
2270: '海原县',
2271: '西吉县',
2272: '隆德县',
2273: '泾源县',
2274: '彭阳县',
name: '固原'
},
272: {
2275: '惠农县',
2276: '大武口区',
2277: '惠农区',
2278: '陶乐县',
2279: '平罗县',
name: '石嘴山'
},
273: {
2280: '利通区',
2281: '中卫县',
2282: '青铜峡市',
2283: '中宁县',
2284: '盐池县',
2285: '同心县',
name: '吴忠'
},
274: {
2286: '沙坡头区',
2287: '海原县',
2288: '中宁县',
name: '中卫'
},
name: '宁夏'
},
21: {
275: {
2289: '城中区',
2290: '城东区',
2291: '城西区',
2292: '城北区',
2293: '湟中县',
2294: '湟源县',
2295: '大通',
name: '西宁'
},
276: {
2296: '玛沁县',
2297: '班玛县',
2298: '甘德县',
2299: '达日县',
2300: '久治县',
2301: '玛多县',
name: '果洛'
},
277: {
2302: '海晏县',
2303: '祁连县',
2304: '刚察县',
2305: '门源',
name: '海北'
},
278: {
2306: '平安县',
2307: '乐都县',
2308: '民和',
2309: '互助',
2310: '化隆',
2311: '循化',
name: '海东'
},
279: {
2312: '共和县',
2313: '同德县',
2314: '贵德县',
2315: '兴海县',
2316: '贵南县',
name: '海南'
},
280: {
2317: '德令哈市',
2318: '格尔木市',
2319: '乌兰县',
2320: '都兰县',
2321: '天峻县',
name: '海西'
},
281: {
2322: '同仁县',
2323: '尖扎县',
2324: '泽库县',
2325: '河南蒙古族自治县',
name: '黄南'
},
282: {
2326: '玉树县',
2327: '杂多县',
2328: '称多县',
2329: '治多县',
2330: '囊谦县',
2331: '曲麻莱县',
name: '玉树'
},
name: '青海'
},
22: {
283: {
2332: '市中区',
2333: '历下区',
2334: '天桥区',
2335: '槐荫区',
2336: '历城区',
2337: '长清区',
2338: '章丘市',
2339: '平阴县',
2340: '济阳县',
2341: '商河县',
name: '济南'
},
284: {
2342: '市南区',
2343: '市北区',
2344: '城阳区',
2345: '四方区',
2346: '李沧区',
2347: '黄岛区',
2348: '崂山区',
2349: '胶州市',
2350: '即墨市',
2351: '平度市',
2352: '胶南市',
2353: '莱西市',
name: '青岛'
},
285: {
2354: '滨城区',
2355: '惠民县',
2356: '阳信县',
2357: '无棣县',
2358: '沾化县',
2359: '博兴县',
2360: '邹平县',
name: '滨州'
},
286: {
2361: '德城区',
2362: '陵县',
2363: '乐陵市',
2364: '禹城市',
2365: '宁津县',
2366: '庆云县',
2367: '临邑县',
2368: '齐河县',
2369: '平原县',
2370: '夏津县',
2371: '武城县',
name: '德州'
},
287: {
2372: '东营区',
2373: '河口区',
2374: '垦利县',
2375: '利津县',
2376: '广饶县',
name: '东营'
},
288: {
2377: '牡丹区',
2378: '曹县',
2379: '单县',
2380: '成武县',
2381: '巨野县',
2382: '郓城县',
2383: '鄄城县',
2384: '定陶县',
2385: '东明县',
name: '菏泽'
},
289: {
2386: '市中区',
2387: '任城区',
2388: '曲阜市',
2389: '兖州市',
2390: '邹城市',
2391: '微山县',
2392: '鱼台县',
2393: '金乡县',
2394: '嘉祥县',
2395: '汶上县',
2396: '泗水县',
2397: '梁山县',
name: '济宁'
},
290: {
2398: '莱城区',
2399: '钢城区',
name: '莱芜'
},
291: {
2400: '东昌府区',
2401: '临清市',
2402: '阳谷县',
2403: '莘县',
2404: '茌平县',
2405: '东阿县',
2406: '冠县',
2407: '高唐县',
name: '聊城'
},
292: {
2408: '兰山区',
2409: '罗庄区',
2410: '河东区',
2411: '沂南县',
2412: '郯城县',
2413: '沂水县',
2414: '苍山县',
2415: '费县',
2416: '平邑县',
2417: '莒南县',
2418: '蒙阴县',
2419: '临沭县',
name: '临沂'
},
293: {
2420: '东港区',
2421: '岚山区',
2422: '五莲县',
2423: '莒县',
name: '日照'
},
294: {
2424: '泰山区',
2425: '岱岳区',
2426: '新泰市',
2427: '肥城市',
2428: '宁阳县',
2429: '东平县',
name: '泰安'
},
295: {
2430: '荣成市',
2431: '乳山市',
2432: '环翠区',
2433: '文登市',
name: '威海'
},
296: {
2434: '潍城区',
2435: '寒亭区',
2436: '坊子区',
2437: '奎文区',
2438: '青州市',
2439: '诸城市',
2440: '寿光市',
2441: '安丘市',
2442: '高密市',
2443: '昌邑市',
2444: '临朐县',
2445: '昌乐县',
name: '潍坊'
},
297: {
2446: '芝罘区',
2447: '福山区',
2448: '牟平区',
2449: '莱山区',
2450: '开发区',
2451: '龙口市',
2452: '莱阳市',
2453: '莱州市',
2454: '蓬莱市',
2455: '招远市',
2456: '栖霞市',
2457: '海阳市',
2458: '长岛县',
name: '烟台'
},
298: {
2459: '市中区',
2460: '山亭区',
2461: '峄城区',
2462: '台儿庄区',
2463: '薛城区',
2464: '滕州市',
name: '枣庄'
},
299: {
2465: '张店区',
2466: '临淄区',
2467: '淄川区',
2468: '博山区',
2469: '周村区',
2470: '桓台县',
2471: '高青县',
2472: '沂源县',
name: '淄博'
},
name: '山东'
},
23: {
300: {
2473: '杏花岭区',
2474: '小店区',
2475: '迎泽区',
2476: '尖草坪区',
2477: '万柏林区',
2478: '晋源区',
2479: '高新开发区',
2480: '民营经济开发区',
2481: '经济技术开发区',
2482: '清徐县',
2483: '阳曲县',
2484: '娄烦县',
2485: '古交市',
name: '太原'
},
301: {
2486: '城区',
2487: '郊区',
2488: '沁县',
2489: '潞城市',
2490: '长治县',
2491: '襄垣县',
2492: '屯留县',
2493: '平顺县',
2494: '黎城县',
2495: '壶关县',
2496: '长子县',
2497: '武乡县',
2498: '沁源县',
name: '长治'
},
302: {
2499: '城区',
2500: '矿区',
2501: '南郊区',
2502: '新荣区',
2503: '阳高县',
2504: '天镇县',
2505: '广灵县',
2506: '灵丘县',
2507: '浑源县',
2508: '左云县',
2509: '大同县',
name: '大同'
},
303: {
2510: '城区',
2511: '高平市',
2512: '沁水县',
2513: '阳城县',
2514: '陵川县',
2515: '泽州县',
name: '晋城'
},
304: {
2516: '榆次区',
2517: '介休市',
2518: '榆社县',
2519: '左权县',
2520: '和顺县',
2521: '昔阳县',
2522: '寿阳县',
2523: '太谷县',
2524: '祁县',
2525: '平遥县',
2526: '灵石县',
name: '晋中'
},
305: {
2527: '尧都区',
2528: '侯马市',
2529: '霍州市',
2530: '曲沃县',
2531: '翼城县',
2532: '襄汾县',
2533: '洪洞县',
2534: '吉县',
2535: '安泽县',
2536: '浮山县',
2537: '古县',
2538: '乡宁县',
2539: '大宁县',
2540: '隰县',
2541: '永和县',
2542: '蒲县',
2543: '汾西县',
name: '临汾'
},
306: {
2544: '离石市',
2545: '离石区',
2546: '孝义市',
2547: '汾阳市',
2548: '文水县',
2549: '交城县',
2550: '兴县',
2551: '临县',
2552: '柳林县',
2553: '石楼县',
2554: '岚县',
2555: '方山县',
2556: '中阳县',
2557: '交口县',
name: '吕梁'
},
307: {
2558: '朔城区',
2559: '平鲁区',
2560: '山阴县',
2561: '应县',
2562: '右玉县',
2563: '怀仁县',
name: '朔州'
},
308: {
2564: '忻府区',
2565: '原平市',
2566: '定襄县',
2567: '五台县',
2568: '代县',
2569: '繁峙县',
2570: '宁武县',
2571: '静乐县',
2572: '神池县',
2573: '五寨县',
2574: '岢岚县',
2575: '河曲县',
2576: '保德县',
2577: '偏关县',
name: '忻州'
},
309: {
2578: '城区',
2579: '矿区',
2580: '郊区',
2581: '平定县',
2582: '盂县',
name: '阳泉'
},
310: {
2583: '盐湖区',
2584: '永济市',
2585: '河津市',
2586: '临猗县',
2587: '万荣县',
2588: '闻喜县',
2589: '稷山县',
2590: '新绛县',
2591: '绛县',
2592: '垣曲县',
2593: '夏县',
2594: '平陆县',
2595: '芮城县',
name: '运城'
},
name: '山西'
},
24: {
311: {
2596: '莲湖区',
2597: '新城区',
2598: '碑林区',
2599: '雁塔区',
2600: '灞桥区',
2601: '未央区',
2602: '阎良区',
2603: '临潼区',
2604: '长安区',
2605: '蓝田县',
2606: '周至县',
2607: '户县',
2608: '高陵县',
name: '西安'
},
312: {
2609: '汉滨区',
2610: '汉阴县',
2611: '石泉县',
2612: '宁陕县',
2613: '紫阳县',
2614: '岚皋县',
2615: '平利县',
2616: '镇坪县',
2617: '旬阳县',
2618: '白河县',
name: '安康'
},
313: {
2619: '陈仓区',
2620: '渭滨区',
2621: '金台区',
2622: '凤翔县',
2623: '岐山县',
2624: '扶风县',
2625: '眉县',
2626: '陇县',
2627: '千阳县',
2628: '麟游县',
2629: '凤县',
2630: '太白县',
name: '宝鸡'
},
314: {
2631: '汉台区',
2632: '南郑县',
2633: '城固县',
2634: '洋县',
2635: '西乡县',
2636: '勉县',
2637: '宁强县',
2638: '略阳县',
2639: '镇巴县',
2640: '留坝县',
2641: '佛坪县',
name: '汉中'
},
315: {
2642: '商州区',
2643: '洛南县',
2644: '丹凤县',
2645: '商南县',
2646: '山阳县',
2647: '镇安县',
2648: '柞水县',
name: '商洛'
},
316: {
2649: '耀州区',
2650: '王益区',
2651: '印台区',
2652: '宜君县',
name: '铜川'
},
317: {
2653: '临渭区',
2654: '韩城市',
2655: '华阴市',
2656: '华县',
2657: '潼关县',
2658: '大荔县',
2659: '合阳县',
2660: '澄城县',
2661: '蒲城县',
2662: '白水县',
2663: '富平县',
name: '渭南'
},
318: {
2664: '秦都区',
2665: '渭城区',
2666: '杨陵区',
2667: '兴平市',
2668: '三原县',
2669: '泾阳县',
2670: '乾县',
2671: '礼泉县',
2672: '永寿县',
2673: '彬县',
2674: '长武县',
2675: '旬邑县',
2676: '淳化县',
2677: '武功县',
name: '咸阳'
},
319: {
2678: '吴起县',
2679: '宝塔区',
2680: '延长县',
2681: '延川县',
2682: '子长县',
2683: '安塞县',
2684: '志丹县',
2685: '甘泉县',
2686: '富县',
2687: '洛川县',
2688: '宜川县',
2689: '黄龙县',
2690: '黄陵县',
name: '延安'
},
320: {
2691: '榆阳区',
2692: '神木县',
2693: '府谷县',
2694: '横山县',
2695: '靖边县',
2696: '定边县',
2697: '绥德县',
2698: '米脂县',
2699: '佳县',
2700: '吴堡县',
2701: '清涧县',
2702: '子洲县',
name: '榆林'
},
name: '陕西'
},
25: {
321: {
2703: '长宁区',
2704: '闸北区',
2705: '闵行区',
2706: '徐汇区',
2707: '浦东新区',
2708: '杨浦区',
2709: '普陀区',
2710: '静安区',
2711: '卢湾区',
2712: '虹口区',
2713: '黄浦区',
2714: '南汇区',
2715: '松江区',
2716: '嘉定区',
2717: '宝山区',
2718: '青浦区',
2719: '金山区',
2720: '奉贤区',
2721: '崇明县',
name: '上海'
},
name: '上海'
},
26: {
322: {
2722: '青羊区',
2723: '锦江区',
2724: '金牛区',
2725: '武侯区',
2726: '成华区',
2727: '龙泉驿区',
2728: '青白江区',
2729: '新都区',
2730: '温江区',
2731: '高新区',
2732: '高新西区',
2733: '都江堰市',
2734: '彭州市',
2735: '邛崃市',
2736: '崇州市',
2737: '金堂县',
2738: '双流县',
2739: '郫县',
2740: '大邑县',
2741: '蒲江县',
2742: '新津县',
2743: '都江堰市',
2744: '彭州市',
2745: '邛崃市',
2746: '崇州市',
2747: '金堂县',
2748: '双流县',
2749: '郫县',
2750: '大邑县',
2751: '蒲江县',
2752: '新津县',
name: '成都'
},
323: {
2753: '涪城区',
2754: '游仙区',
2755: '江油市',
2756: '盐亭县',
2757: '三台县',
2758: '平武县',
2759: '安县',
2760: '梓潼县',
2761: '北川县',
name: '绵阳'
},
324: {
2762: '马尔康县',
2763: '汶川县',
2764: '理县',
2765: '茂县',
2766: '松潘县',
2767: '九寨沟县',
2768: '金川县',
2769: '小金县',
2770: '黑水县',
2771: '壤塘县',
2772: '阿坝县',
2773: '若尔盖县',
2774: '红原县',
name: '阿坝'
},
325: {
2775: '巴州区',
2776: '通江县',
2777: '南江县',
2778: '平昌县',
name: '巴中'
},
326: {
2779: '通川区',
2780: '万源市',
2781: '达县',
2782: '宣汉县',
2783: '开江县',
2784: '大竹县',
2785: '渠县',
name: '达州'
},
327: {
2786: '旌阳区',
2787: '广汉市',
2788: '什邡市',
2789: '绵竹市',
2790: '罗江县',
2791: '中江县',
name: '德阳'
},
328: {
2792: '康定县',
2793: '丹巴县',
2794: '泸定县',
2795: '炉霍县',
2796: '九龙县',
2797: '甘孜县',
2798: '雅江县',
2799: '新龙县',
2800: '道孚县',
2801: '白玉县',
2802: '理塘县',
2803: '德格县',
2804: '乡城县',
2805: '石渠县',
2806: '稻城县',
2807: '色达县',
2808: '巴塘县',
2809: '得荣县',
name: '甘孜'
},
329: {
2810: '广安区',
2811: '华蓥市',
2812: '岳池县',
2813: '武胜县',
2814: '邻水县',
name: '广安'
},
330: {
2815: '利州区',
2816: '元坝区',
2817: '朝天区',
2818: '旺苍县',
2819: '青川县',
2820: '剑阁县',
2821: '苍溪县',
name: '广元'
},
331: {
2822: '峨眉山市',
2823: '乐山市',
2824: '犍为县',
2825: '井研县',
2826: '夹江县',
2827: '沐川县',
2828: '峨边',
2829: '马边',
name: '乐山'
},
332: {
2830: '西昌市',
2831: '盐源县',
2832: '德昌县',
2833: '会理县',
2834: '会东县',
2835: '宁南县',
2836: '普格县',
2837: '布拖县',
2838: '金阳县',
2839: '昭觉县',
2840: '喜德县',
2841: '冕宁县',
2842: '越西县',
2843: '甘洛县',
2844: '美姑县',
2845: '雷波县',
2846: '木里',
name: '凉山'
},
333: {
2847: '东坡区',
2848: '仁寿县',
2849: '彭山县',
2850: '洪雅县',
2851: '丹棱县',
2852: '青神县',
name: '眉山'
},
334: {
2853: '阆中市',
2854: '南部县',
2855: '营山县',
2856: '蓬安县',
2857: '仪陇县',
2858: '顺庆区',
2859: '高坪区',
2860: '嘉陵区',
2861: '西充县',
name: '南充'
},
335: {
2862: '市中区',
2863: '东兴区',
2864: '威远县',
2865: '资中县',
2866: '隆昌县',
name: '内江'
},
336: {
2867: '东 区',
2868: '西 区',
2869: '仁和区',
2870: '米易县',
2871: '盐边县',
name: '攀枝花'
},
337: {
2872: '船山区',
2873: '安居区',
2874: '蓬溪县',
2875: '射洪县',
2876: '大英县',
name: '遂宁'
},
338: {
2877: '雨城区',
2878: '名山县',
2879: '荥经县',
2880: '汉源县',
2881: '石棉县',
2882: '天全县',
2883: '芦山县',
2884: '宝兴县',
name: '雅安'
},
339: {
2885: '翠屏区',
2886: '宜宾县',
2887: '南溪县',
2888: '江安县',
2889: '长宁县',
2890: '高县',
2891: '珙县',
2892: '筠连县',
2893: '兴文县',
2894: '屏山县',
name: '宜宾'
},
340: {
2895: '雁江区',
2896: '简阳市',
2897: '安岳县',
2898: '乐至县',
name: '资阳'
},
341: {
2899: '大安区',
2900: '自流井区',
2901: '贡井区',
2902: '沿滩区',
2903: '荣县',
2904: '富顺县',
name: '自贡'
},
342: {
2905: '江阳区',
2906: '纳溪区',
2907: '龙马潭区',
2908: '泸县',
2909: '合江县',
2910: '叙永县',
2911: '古蔺县',
name: '泸州'
},
name: '四川'
},
27: {
343: {
2912: '和平区',
2913: '河西区',
2914: '南开区',
2915: '河北区',
2916: '河东区',
2917: '红桥区',
2918: '东丽区',
2919: '津南区',
2920: '西青区',
2921: '北辰区',
2922: '塘沽区',
2923: '汉沽区',
2924: '大港区',
2925: '武清区',
2926: '宝坻区',
2927: '经济开发区',
2928: '宁河县',
2929: '静海县',
2930: '蓟县',
name: '天津'
},
name: '天津'
},
28: {
344: {
2931: '城关区',
2932: '林周县',
2933: '当雄县',
2934: '尼木县',
2935: '曲水县',
2936: '堆龙德庆县',
2937: '达孜县',
2938: '墨竹工卡县',
name: '拉萨'
},
345: {
2939: '噶尔县',
2940: '普兰县',
2941: '札达县',
2942: '日土县',
2943: '革吉县',
2944: '改则县',
2945: '措勤县',
name: '阿里'
},
346: {
2946: '昌都县',
2947: '江达县',
2948: '贡觉县',
2949: '类乌齐县',
2950: '丁青县',
2951: '察雅县',
2952: '八宿县',
2953: '左贡县',
2954: '芒康县',
2955: '洛隆县',
2956: '边坝县',
name: '昌都'
},
347: {
2957: '林芝县',
2958: '工布江达县',
2959: '米林县',
2960: '墨脱县',
2961: '波密县',
2962: '察隅县',
2963: '朗县',
name: '林芝'
},
348: {
2964: '那曲县',
2965: '嘉黎县',
2966: '比如县',
2967: '聂荣县',
2968: '安多县',
2969: '申扎县',
2970: '索县',
2971: '班戈县',
2972: '巴青县',
2973: '尼玛县',
name: '那曲'
},
349: {
2974: '日喀则市',
2975: '南木林县',
2976: '江孜县',
2977: '定日县',
2978: '萨迦县',
2979: '拉孜县',
2980: '昂仁县',
2981: '谢通门县',
2982: '白朗县',
2983: '仁布县',
2984: '康马县',
2985: '定结县',
2986: '仲巴县',
2987: '亚东县',
2988: '吉隆县',
2989: '聂拉木县',
2990: '萨嘎县',
2991: '岗巴县',
name: '日喀则'
},
350: {
2992: '乃东县',
2993: '扎囊县',
2994: '贡嘎县',
2995: '桑日县',
2996: '琼结县',
2997: '曲松县',
2998: '措美县',
2999: '洛扎县',
3000: '加查县',
3001: '隆子县',
3002: '错那县',
3003: '浪卡子县',
name: '山南'
},
name: '西藏'
},
29: {
351: {
3004: '天山区',
3005: '沙依巴克区',
3006: '新市区',
3007: '水磨沟区',
3008: '头屯河区',
3009: '达坂城区',
3010: '米东区',
3011: '乌鲁木齐县',
name: '乌鲁木齐'
},
352: {
3012: '阿克苏市',
3013: '温宿县',
3014: '库车县',
3015: '沙雅县',
3016: '新和县',
3017: '拜城县',
3018: '乌什县',
3019: '阿瓦提县',
3020: '柯坪县',
name: '阿克苏'
},
353: {
3021: '阿拉尔市',
name: '阿拉尔'
},
354: {
3022: '库尔勒市',
3023: '轮台县',
3024: '尉犁县',
3025: '若羌县',
3026: '且末县',
3027: '焉耆',
3028: '和静县',
3029: '和硕县',
3030: '博湖县',
name: '巴音郭楞'
},
355: {
3031: '博乐市',
3032: '精河县',
3033: '温泉县',
name: '博尔塔拉'
},
356: {
3034: '呼图壁县',
3035: '米泉市',
3036: '昌吉市',
3037: '阜康市',
3038: '玛纳斯县',
3039: '奇台县',
3040: '吉木萨尔县',
3041: '木垒',
name: '昌吉'
},
357: {
3042: '哈密市',
3043: '伊吾县',
3044: '巴里坤',
name: '哈密'
},
358: {
3045: '和田市',
3046: '和田县',
3047: '墨玉县',
3048: '皮山县',
3049: '洛浦县',
3050: '策勒县',
3051: '于田县',
3052: '民丰县',
name: '和田'
},
359: {
3053: '喀什市',
3054: '疏附县',
3055: '疏勒县',
3056: '英吉沙县',
3057: '泽普县',
3058: '莎车县',
3059: '叶城县',
3060: '麦盖提县',
3061: '岳普湖县',
3062: '伽师县',
3063: '巴楚县',
3064: '塔什库尔干',
name: '喀什'
},
360: {
3065: '克拉玛依市',
name: '克拉玛依'
},
361: {
3066: '阿图什市',
3067: '阿克陶县',
3068: '阿合奇县',
3069: '乌恰县',
name: '克孜勒苏'
},
362: {
3070: '石河子市',
name: '石河子'
},
363: {
3071: '图木舒克市',
name: '图木舒克'
},
364: {
3072: '吐鲁番市',
3073: '鄯善县',
3074: '托克逊县',
name: '吐鲁番'
},
365: {
3075: '五家渠市',
name: '五家渠'
},
366: {
3076: '阿勒泰市',
3077: '布克赛尔',
3078: '伊宁市',
3079: '布尔津县',
3080: '奎屯市',
3081: '乌苏市',
3082: '额敏县',
3083: '富蕴县',
3084: '伊宁县',
3085: '福海县',
3086: '霍城县',
3087: '沙湾县',
3088: '巩留县',
3089: '哈巴河县',
3090: '托里县',
3091: '青河县',
3092: '新源县',
3093: '裕民县',
3094: '和布克赛尔',
3095: '吉木乃县',
3096: '昭苏县',
3097: '特克斯县',
3098: '尼勒克县',
3099: '察布查尔',
name: '伊犁'
},
name: '新疆'
},
30: {
367: {
3100: '盘龙区',
3101: '五华区',
3102: '官渡区',
3103: '西山区',
3104: '东川区',
3105: '安宁市',
3106: '呈贡县',
3107: '晋宁县',
3108: '富民县',
3109: '宜良县',
3110: '嵩明县',
3111: '石林县',
3112: '禄劝',
3113: '寻甸',
name: '昆明'
},
368: {
3114: '兰坪',
3115: '泸水县',
3116: '福贡县',
3117: '贡山',
name: '怒江'
},
369: {
3118: '宁洱',
3119: '思茅区',
3120: '墨江',
3121: '景东',
3122: '景谷',
3123: '镇沅',
3124: '江城',
3125: '孟连',
3126: '澜沧',
3127: '西盟',
name: '普洱'
},
370: {
3128: '古城区',
3129: '宁蒗',
3130: '玉龙',
3131: '永胜县',
3132: '华坪县',
name: '丽江'
},
371: {
3133: '隆阳区',
3134: '施甸县',
3135: '腾冲县',
3136: '龙陵县',
3137: '昌宁县',
name: '保山'
},
372: {
3138: '楚雄市',
3139: '双柏县',
3140: '牟定县',
3141: '南华县',
3142: '姚安县',
3143: '大姚县',
3144: '永仁县',
3145: '元谋县',
3146: '武定县',
3147: '禄丰县',
name: '楚雄'
},
373: {
3148: '大理市',
3149: '祥云县',
3150: '宾川县',
3151: '弥渡县',
3152: '永平县',
3153: '云龙县',
3154: '洱源县',
3155: '剑川县',
3156: '鹤庆县',
3157: '漾濞',
3158: '南涧',
3159: '巍山',
name: '大理'
},
374: {
3160: '潞西市',
3161: '瑞丽市',
3162: '梁河县',
3163: '盈江县',
3164: '陇川县',
name: '德宏'
},
375: {
3165: '香格里拉县',
3166: '德钦县',
3167: '维西',
name: '迪庆'
},
376: {
3168: '泸西县',
3169: '蒙自县',
3170: '个旧市',
3171: '开远市',
3172: '绿春县',
3173: '建水县',
3174: '石屏县',
3175: '弥勒县',
3176: '元阳县',
3177: '红河县',
3178: '金平',
3179: '河口',
3180: '屏边',
name: '红河'
},
377: {
3181: '临翔区',
3182: '凤庆县',
3183: '云县',
3184: '永德县',
3185: '镇康县',
3186: '双江',
3187: '耿马',
3188: '沧源',
name: '临沧'
},
378: {
3189: '麒麟区',
3190: '宣威市',
3191: '马龙县',
3192: '陆良县',
3193: '师宗县',
3194: '罗平县',
3195: '富源县',
3196: '会泽县',
3197: '沾益县',
name: '曲靖'
},
379: {
3198: '文山县',
3199: '砚山县',
3200: '西畴县',
3201: '麻栗坡县',
3202: '马关县',
3203: '丘北县',
3204: '广南县',
3205: '富宁县',
name: '文山'
},
380: {
3206: '景洪市',
3207: '勐海县',
3208: '勐腊县',
name: '西双版纳'
},
381: {
3209: '红塔区',
3210: '江川县',
3211: '澄江县',
3212: '通海县',
3213: '华宁县',
3214: '易门县',
3215: '峨山',
3216: '新平',
3217: '元江',
name: '玉溪'
},
382: {
3218: '昭阳区',
3219: '鲁甸县',
3220: '巧家县',
3221: '盐津县',
3222: '大关县',
3223: '永善县',
3224: '绥江县',
3225: '镇雄县',
3226: '彝良县',
3227: '威信县',
3228: '水富县',
name: '昭通'
},
name: '云南'
},
31: {
383: {
3229: '西湖区',
3230: '上城区',
3231: '下城区',
3232: '拱墅区',
3233: '滨江区',
3234: '江干区',
3235: '萧山区',
3236: '余杭区',
3237: '市郊',
3238: '建德市',
3239: '富阳市',
3240: '临安市',
3241: '桐庐县',
3242: '淳安县',
name: '杭州'
},
384: {
3243: '吴兴区',
3244: '南浔区',
3245: '德清县',
3246: '长兴县',
3247: '安吉县',
name: '湖州'
},
385: {
3248: '南湖区',
3249: '秀洲区',
3250: '海宁市',
3251: '嘉善县',
3252: '平湖市',
3253: '桐乡市',
3254: '海盐县',
name: '嘉兴'
},
386: {
3255: '婺城区',
3256: '金东区',
3257: '兰溪市',
3258: '市区',
3259: '佛堂镇',
3260: '上溪镇',
3261: '义亭镇',
3262: '大陈镇',
3263: '苏溪镇',
3264: '赤岸镇',
3265: '东阳市',
3266: '永康市',
3267: '武义县',
3268: '浦江县',
3269: '磐安县',
name: '金华'
},
387: {
3270: '莲都区',
3271: '龙泉市',
3272: '青田县',
3273: '缙云县',
3274: '遂昌县',
3275: '松阳县',
3276: '云和县',
3277: '庆元县',
3278: '景宁',
name: '丽水'
},
388: {
3279: '海曙区',
3280: '江东区',
3281: '江北区',
3282: '镇海区',
3283: '北仑区',
3284: '鄞州区',
3285: '余姚市',
3286: '慈溪市',
3287: '奉化市',
3288: '象山县',
3289: '宁海县',
name: '宁波'
},
389: {
3290: '越城区',
3291: '上虞市',
3292: '嵊州市',
3293: '绍兴县',
3294: '新昌县',
3295: '诸暨市',
name: '绍兴'
},
390: {
3296: '椒江区',
3297: '黄岩区',
3298: '路桥区',
3299: '温岭市',
3300: '临海市',
3301: '玉环县',
3302: '三门县',
3303: '天台县',
3304: '仙居县',
name: '台州'
},
391: {
3305: '鹿城区',
3306: '龙湾区',
3307: '瓯海区',
3308: '瑞安市',
3309: '乐清市',
3310: '洞头县',
3311: '永嘉县',
3312: '平阳县',
3313: '苍南县',
3314: '文成县',
3315: '泰顺县',
name: '温州'
},
392: {
3316: '定海区',
3317: '普陀区',
3318: '岱山县',
3319: '嵊泗县',
name: '舟山'
},
393: {
3320: '衢州市',
3321: '江山市',
3322: '常山县',
3323: '开化县',
3324: '龙游县',
name: '衢州'
},
name: '浙江'
},
32: {
394: {
3325: '合川区',
3326: '江津区',
3327: '南川区',
3328: '永川区',
3329: '南岸区',
3330: '渝北区',
3331: '万盛区',
3332: '大渡口区',
3333: '万州区',
3334: '北碚区',
3335: '沙坪坝区',
3336: '巴南区',
3337: '涪陵区',
3338: '江北区',
3339: '九龙坡区',
3340: '渝中区',
3341: '黔江开发区',
3342: '长寿区',
3343: '双桥区',
3344: '綦江县',
3345: '潼南县',
3346: '铜梁县',
3347: '大足县',
3348: '荣昌县',
3349: '璧山县',
3350: '垫江县',
3351: '武隆县',
3352: '丰都县',
3353: '城口县',
3354: '梁平县',
3355: '开县',
3356: '巫溪县',
3357: '巫山县',
3358: '奉节县',
3359: '云阳县',
3360: '忠县',
3361: '石柱',
3362: '彭水',
3363: '酉阳',
3364: '秀山',
name: '重庆'
},
name: '重庆'
},
33: {
395: {
3365: '沙田区',
3366: '东区',
3367: '观塘区',
3368: '黄大仙区',
3369: '九龙城区',
3370: '屯门区',
3371: '葵青区',
3372: '元朗区',
3373: '深水埗区',
3374: '西贡区',
3375: '大埔区',
3376: '湾仔区',
3377: '油尖旺区',
3378: '北区',
3379: '南区',
3380: '荃湾区',
3381: '中西区',
3382: '离岛区',
name: '香港'
},
name: '香港'
},
34: {
396: {
3383: '澳门',
name: '澳门'
},
name: '澳门'
},
35: {
397: {
3384: '台北',
3385: '高雄',
3386: '基隆',
3387: '台中',
3388: '台南',
3389: '新竹',
3390: '嘉义',
3391: '宜兰县',
3392: '桃园县',
3393: '苗栗县',
3394: '彰化县',
3395: '南投县',
3396: '云林县',
3397: '屏东县',
3398: '台东县',
3399: '花莲县',
3400: '澎湖县',
name: '台湾'
},
name: '台湾'
}
}
<template>
<div class="city-select-form">
<el-form-item
:key="item.model"
:prop="item.model"
:label="item.label || ''"
:label-width="item.labelWidth || item['label-width'] || ''"
:required="item.required || false"
:rules="item.rules || []"
:size="item.size"
>
<template v-for="(select, index) in selects">
<el-select
v-bind:key="index"
:style="{ 'width': item.modelWidth || item['model-width'] || '100px', 'float': 'left', 'marginRight': '10px' }"
v-bind="item['attrs' + index]"
v-on="$listeners"
v-model="select['model']"
:placeholder="item['placeholder' + index]"
:disabled="item.disabled || false"
@change="isSelectChange(index)"
>
<el-option
v-for="option in select.arr"
:label="option.label"
:value="option.value"
:key="option.value"
></el-option>
</el-select>
</template>
<template
v-if="formData[item.model] !== null && formData[item.model] !== '' && formData[item.model] !== undefined"
>
<div class="self-icon el-icon-circle-check" style="color: #237f00;"></div>
</template>
<div class="self-icon el-icon-circle-close" style="color: #b01c40;"></div>
</el-form-item>
</div>
</template>
<script>
import address from './address'
export default {
name: 'CitySelectForm',
componentName: 'CitySelectForm',
props: {
item: {
type: Object,
default() {
return {}
}
},
formData: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
str: '', // 记录一下
selects: [] // 动态添加,当前显示的选择框个数
}
},
mounted() {
if (this.str === '') {
/* 按照配置项,解析返回数据 */
const _data = this.formData[this.item.model]
let arr = []
if (_data) {
arr = _data.split(this.item.separator)
}
/* 回显 */
this.analysisAddress(address, 0, arr[0] || '')
/* 第一个选项为空 */
for (let i = 0; i <= arr.length; i++) {
this.isSelectChange(i, arr[i + 1] || '')
}
}
},
methods: {
/* 解析地址 */
analysisAddress(json, i, val) {
const arr = []
for (const k in json) {
k !== 'name' && arr.push({ label: json[k].name || json[k], value: k })
}
if (arr.length) {
this.selects.push({ arr: arr, index: i, model: val || '' })
}
},
/* 是否选择 */
isSelectChange(index, val) {
let json = address
let i = 0
for (; i <= index; i++) {
/* 当前选中的 value值 */
const tempVal = this.selects[i] && this.selects[i].model
if (tempVal && json[tempVal] && json[tempVal].name) {
json = json[tempVal]
} else {
break
}
}
if (i <= index) {
/* 重新给 formData赋值 - 双向绑定 */
const arr = []
for (let k = 0; k < this.selects.length; k++) {
arr.push(this.selects[k].model)
}
this.formData[this.item.model] = this.str = arr.join(this.item.separator)
return
}
/* 删除后续selects数据 */
for (let j = index + 1; j < this.selects.length;) {
this.selects.splice(j)
}
/* 如果有,则重新添加 */
if (json.name) {
this.analysisAddress(json, index + 1, val || '')
}
/* 重新给 formData赋值 - 双向绑定 */
const arr = []
for (let k = 0; k < this.selects.length; k++) {
arr.push(this.selects[k].model)
}
this.formData[this.item.model] = this.str = arr.join(this.item.separator)
}
},
watch: {
formData: {
immediate: true,
deep: true,
handler(value) {
/* 单独处理 - ajax结果在组件渲染之后 */
if (value[this.item.model] && this.str === '' && value[this.item.model] !== this.str) {
this.str = value[this.item.model]
const _data = this.str
this.selects = []
let arr = []
if (_data) {
arr = _data.split(this.item.separator)
}
/* 回显 */
this.analysisAddress(address, 0, arr[0] || '')
/* 第一个选项为空 */
for (let i = 0; i <= arr.length; i++) {
this.isSelectChange(i, arr[i + 1] || '')
}
}
}
}
}
}
</script>
<style lang="scss">
.self-icon {
display: none !important;
vertical-align: middle;
margin-left: 10px;
font-size: 21px;
line-height: 22px;
}
.is-error .self-icon.el-icon-circle-close {
display: inline-block !important;
}
.is-success .self-icon.el-icon-circle-check {
display: inline-block !important;
}
</style>
## 组件简介
| 字段值 | 说明 | 字段属性 | 默认值 |
| ------- | ------------------------- | ------- | ----- |
| `type` | 类型:`String`; 说明:组件类型名 | 自定义字段 | `date-picker-form` |
| `elemType` | 类型:`String`; 说明:组件类型选择 | element-ui el-date-picker对应字段 | `date` |
| `label` | 类型:`String`; 说明:组件左侧显示名称 | element-ui el-form-item对应字段 | `''` |
| `label-width` | 类型:`String`; 说明:组件左侧显示名称宽度(加单位),父级设置可以子级继承 | element-ui el-form-item对应字段 | `''` |
| `required` | 类型:`Boolean`; 说明:标识是否必填 | element-ui el-form-item对应字段 | `false` |
| `disabled` | 类型:`Boolean`; 说明:标识是否只读 | element-ui el-form-item对应字段 | `false` |
| `model` | 类型:`String`; 说明:表单提交name值和回显对照字段 | 自定义字段 | `''` |
| `model-width` | 类型:`String`; 说明:右侧输入组件宽度(加单位) | 自定义字段 | `'89%'` |
| `placeholder` | 类型:`String`; 说明:组件input框中,默认提示文字 | element-ui el-input对应字段 | `''` |
| `attrs` | 类型:`Object`; 说明:定义标签上Data属性值 | element-ui对应字段 | `{}` |
| `rules` | 类型:`Array`; 说明:组件错误提示规则 | element-ui el-form-item对应字段 | `[]` |
### Demo:
``` js
return {
type: 'date-picker-form',
elemType: '',
label: '出生日期',
labelWidth: '160px',
required: true,
disabled: false,
model: 'birthday',
modelWidth: '',
placeholder: '请选择出生日期',
attrs: { 'value-format': 'yyyy-MM-dd' },
rules: []
}
```
* 其他属性 [参考文档]([https://](https://element.eleme.cn/#/zh-CN/component/input))
import DatePicker from './src/datePickerForm'
/* istanbul ignore next */
DatePicker.install = function (Vue) {
Vue.component(DatePicker.name, DatePicker)
}
export default DatePicker
<template>
<div class="date-picker-form">
<el-form-item
:key="item.model"
:prop="item.model"
:label="item.label || ''"
:label-width="item.labelWidth || item['label-width'] || ''"
:required="item.required || false"
:rules="item.rules || []"
:size="item.size"
>
<el-date-picker :style="{ width: item.modelWidth || item['model-width'] || '89%' }"
:type="item.elemType || 'date'"
v-bind="item.attrs"
v-on="$listeners"
v-model="formData[item.model]"
:disabled="item.disabled || false"
:placeholder="item.placeholder"
></el-date-picker>
<template v-if="formData[item.model] !== null && formData[item.model] !== '' && formData[item.model] !== undefined">
<div class="self-icon el-icon-circle-check" style="color: #237f00;"></div>
</template>
<div class="self-icon el-icon-circle-close" style="color: #b01c40;"></div>
</el-form-item>
</div>
</template>
<script>
export default {
name: 'DatePickerForm',
componentName: 'DatePickerForm',
props: {
item: {
type: Object,
default () {
return {}
}
},
formData: {
type: Object,
default () {
return {}
}
}
},
data () {
return {}
}
}
</script>
<style lang="scss">
.self-icon {
display: none !important;
vertical-align: middle;
margin-left: 10px;
font-size: 21px;
line-height: 22px;
}
.is-error .self-icon.el-icon-circle-close { display: inline-block !important; }
.is-success .self-icon.el-icon-circle-check { display: inline-block !important; }
</style>
## 组件简介
| 字段值 | 说明 | 字段属性 | 默认值 |
| ------- | ------------------------- | ------- | ----- |
| `type` | 类型:`String`; 说明:组件类型名 | 自定义字段 | `date-picker-from-to-form` |
| `elemType` | 类型:`String`; 说明:组件类型选择 | element-ui el-date-picker对应字段 | `daterange` |
| `label` | 类型:`String`; 说明:组件左侧显示名称 | element-ui el-form-item对应字段 | `''` |
| `label-width` | 类型:`String`; 说明:组件左侧显示名称宽度(加单位),父级设置可以子级继承 | element-ui el-form-item对应字段 | `''` |
| `required` | 类型:`Boolean`; 说明:标识是否必填 | element-ui el-form-item对应字段 | `false` |
| `disabled` | 类型:`Boolean`; 说明:标识是否只读 | element-ui el-form-item对应字段 | `false` |
| `model` | 类型:`String`; 说明:表单提交name值和回显对照字段 | 自定义字段 | `''` |
| `model-width` | 类型:`String`; 说明:右侧输入组件宽度(加单位) | 自定义字段 | `'89%'` |
| `rangeSeparator` | 类型:`String`; 说明:中间分隔符 | 自定义字段 | `'-'` |
| `startPlaceholder` | 类型:`String`; 说明:开始时间提示 | 自定义字段 | `''` |
| `endPlaceholder` | 类型:`String`; 说明:结束时间提示 | 自定义字段 | `''` |
| `attrs` | 类型:`Object`; 说明:定义标签上Data属性值 | element-ui对应字段 | `{}` |
| `rules` | 类型:`Array`; 说明:组件错误提示规则 | element-ui el-form-item对应字段 | `[]` |
### Demo:
``` js
return {
type: 'date-picker-from-to-form',
elemType: '',
label: '出生日期',
required: true,
disabled: false,
labelWidth: '160px',
model: 'work_time',
modelWidth: '',
rangeSeparator: '至',
startPlaceholder: '请选择开始时间',
endPlaceholder: '请选择结束时间',
attrs: { 'value-format': 'yyyy-MM-dd' },
rules: []
}
```
* 其他属性 [参考文档]([https://](https://element.eleme.cn/#/zh-CN/component/input))
import DatePickerFromTo from './src/datePickerFromToForm'
/* istanbul ignore next */
DatePickerFromTo.install = function (Vue) {
Vue.component(DatePickerFromTo.name, DatePickerFromTo)
}
export default DatePickerFromTo
<template>
<div class="date-picker-from-to-form">
<el-form-item
:key="item.model"
:prop="item.model"
:label="item.label || ''"
:label-width="item.labelWidth || item['label-width'] || ''"
:required="item.required || false"
:rules="item.rules || []"
:size="item.size"
>
<el-date-picker :style="{ width: item.modelWidth || item['model-width'] || '89%' }"
:type="item.elemType || 'daterange'"
v-bind="item.attrs"
v-on="$listeners"
v-model="formData[item.model]"
:disabled="item.disabled || false"
:range-separator="item.rangeSeparator"
:start-placeholder="item.startPlaceholder"
:end-placeholder="item.endPlaceholder"
></el-date-picker>
<template v-if="formData[item.model] !== null && formData[item.model] !== '' && formData[item.model] !== undefined">
<div class="self-icon el-icon-circle-check" style="color: #237f00;"></div>
</template>
<div class="self-icon el-icon-circle-close" style="color: #b01c40;"></div>
</el-form-item>
</div>
</template>
<script>
export default {
name: 'DatePickerFromToForm',
componentName: 'DatePickerFromToForm',
props: {
item: {
type: Object,
default () {
return {}
}
},
formData: {
type: Object,
default () {
return {}
}
}
},
data () {
return {}
}
}
</script>
<style lang="scss">
.self-icon {
display: none !important;
vertical-align: middle;
margin-left: 10px;
font-size: 21px;
line-height: 22px;
}
.is-error .self-icon.el-icon-circle-close { display: inline-block !important; }
.is-success .self-icon.el-icon-circle-check { display: inline-block !important; }
</style>
/* Automatically generated by './build/bin/build-entry.js' */
import {
Input,
InputNumber,
Radio,
RadioGroup,
Checkbox,
CheckboxGroup,
Switch,
Select,
Option,
OptionGroup,
Button,
ButtonGroup,
DatePicker,
TimeSelect,
TimePicker,
Form,
FormItem,
Tabs,
TabPane,
Upload,
Avatar,
Progress,
ColorPicker
} from 'element-ui'
import InputForm from './input-form'
import TextareaForm from './textarea-form'
import SelectForm from './select-form'
import CitySelectForm from './city-select-form'
import DatePickerForm from './date-picker-form'
import DatePickerFromToForm from './date-picker-from-to-form'
import RadioGroupForm from './radio-group-form'
import CheckboxGroupForm from './checkbox-group-form'
import UploadForm from './upload-form'
const components = [
InputForm,
TextareaForm,
SelectForm,
CitySelectForm,
DatePickerForm,
DatePickerFromToForm,
RadioGroupForm,
CheckboxGroupForm,
UploadForm
]
const install = function(Vue) {
// locale.use(opts.locale);
// locale.i18n(opts.i18n);
Vue.use(Input)
Vue.use(InputNumber)
Vue.use(Radio)
Vue.use(RadioGroup)
Vue.use(Checkbox)
Vue.use(CheckboxGroup)
Vue.use(Switch)
Vue.use(Select)
Vue.use(Option)
Vue.use(OptionGroup)
Vue.use(Button)
Vue.use(ButtonGroup)
Vue.use(DatePicker)
Vue.use(TimeSelect)
Vue.use(TimePicker)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Tabs)
Vue.use(TabPane)
Vue.use(Upload)
Vue.use(Avatar)
Vue.use(Progress)
Vue.use(ColorPicker)
components.forEach(component => {
Vue.component(component.name, component)
})
// Vue.use(Loading.directive);
// Vue.prototype.$ELEMENT = {
// size: opts.size || '',
// zIndex: opts.zIndex || 2000
// };
// Vue.prototype.$message = Message;
}
/* istanbul ignore if */
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
export default {
install,
InputForm,
TextareaForm,
SelectForm,
CitySelectForm,
DatePickerForm,
DatePickerFromToForm,
RadioGroupForm,
CheckboxGroupForm,
UploadForm
}
## 组件简介
| 字段值 | 说明 | 字段属性 | 默认值 |
| ------- | ------------------------- | ------- | ----- |
| `type` | 类型:`String`; 说明:组件类型名 | 自定义字段 | `input-form` |
| `label` | 类型:`String`; 说明:组件左侧显示名称 | element-ui el-form-item对应字段 | `''` |
| `label-width` | 类型:`String`; 说明:组件左侧显示名称宽度(加单位),父级设置可以子级继承 | element-ui el-form-item对应字段 | `''` |
| `required` | 类型:`Boolean`; 说明:标识是否必填 | element-ui el-form-item对应字段 | `false` |
| `disabled` | 类型:`Boolean`; 说明:标识是否只读 | element-ui el-form-item对应字段 | `false` |
| `model` | 类型:`String`; 说明:表单提交name值和回显对照字段 | 自定义字段 | `''` |
| `model-width` | 类型:`String`; 说明:右侧输入组件宽度(加单位) | 自定义字段 | `'89%'` |
| `placeholder` | 类型:`String`; 说明:组件input框中,默认提示文字 | element-ui el-input对应字段 | `''` |
| `attrs` | 类型:`Object`; 说明:定义标签上Data属性值 | element-ui对应字段 | `{}` |
| `rules` | 类型:`Array`; 说明:组件错误提示规则 | element-ui el-form-item对应字段 | `[]` |
### Demo Example:
``` js
return {
type: 'input-form',
label: '姓名',
labelWidth: '160px',
required: true,
disabled: false,
model: 'real_name_cn',
modelWidth: '',
placeholder: '请输入姓名',
attrs: {},
rules: [
{
required: true,
message: '请输入姓名',
trigger: 'blur'
},
{
min: 3,
max: 5,
message: '长度在 3 到 5 个字符',
trigger: 'blur'
}
]
}
```
* 其他属性 [参考文档]([https://](https://element.eleme.cn/#/zh-CN/component/input))
import Input from './src/inputForm'
/* istanbul ignore next */
Input.install = function (Vue) {
Vue.component(Input.name, Input)
}
export default Input
<template>
<div class="input-form">
<el-form-item
:key="item.model"
:prop="item.model"
:label="item.label || ''"
:label-width="item.labelWidth || item['label-width'] || ''"
:required="item.required || false"
:rules="item.rules || []"
:size="item.size"
>
<el-input
:style="{ width: item.modelWidth || item['model-width'] || '89%' }"
v-bind="item.attrs || {}"
v-on="$listeners"
v-model.trim="formData[item.model]"
:disabled="item.disabled || false"
:placeholder="item.placeholder || ''"
>
</el-input>
<template
v-if="formData[item.model] !== null && formData[item.model] !== '' && formData[item.model] !== undefined"
>
<div class="self-icon el-icon-circle-check" style="color: #237f00"></div>
</template>
<div class="self-icon el-icon-circle-close" style="color: #b01c40"></div>
</el-form-item>
</div>
</template>
<script>
export default {
name: 'InputForm',
componentName: 'InputForm',
props: {
item: {
type: Object,
default() {
return {}
}
},
formData: {
type: Object,
default() {
return {}
}
}
},
data() {
return {}
}
}
</script>
<style lang="scss">
.self-icon {
display: none !important;
vertical-align: middle;
margin-left: 10px;
font-size: 21px;
line-height: 22px;
}
.is-error .self-icon.el-icon-circle-close {
display: inline-block !important;
}
.is-success .self-icon.el-icon-circle-check {
display: inline-block !important;
}
</style>
## 组件简介
| 字段值 | 说明 | 字段属性 | 默认值 |
| ------- | ------------------------- | ------- | ----- |
| `type` | 类型:`String`; 说明:组件类型名 | 自定义字段 | `radio-group-form` |
| `label` | 类型:`String`; 说明:组件左侧显示名称 | element-ui el-form-item对应字段 | `''` |
| `label-width` | 类型:`String`; 说明:组件左侧显示名称宽度(加单位),父级设置可以子级继承 | element-ui el-form-item对应字段 | `''` |
| `required` | 类型:`Boolean`; 说明:标识是否必填 | element-ui el-form-item对应字段 | `false` |
| `disabled` | 类型:`Boolean`; 说明:标识是否只读 | element-ui el-form-item对应字段 | `false` |
| `model` | 类型:`String`; 说明:表单提交name值和回显对照字段 | 自定义字段 | `''` |
| `model-width` | 类型:`String`; 说明:右侧输入组件宽度(加单位) | 自定义字段 | `'89%'` |
| `placeholder` | 类型:`String`; 说明:组件input框中,默认提示文字 | element-ui el-input对应字段 | `''` |
| `values` | 类型:`Array`; 说明:里面是选择类型值label和value(值可以是 int 或 str),选择组 | 自定义字段 | `[]` |
| `attrs` | 类型:`Object`; 说明:定义标签上Data属性值 | element-ui对应字段 | `{}` |
| `rules` | 类型:`Array`; 说明:组件错误提示规则 | element-ui el-form-item对应字段 | `[]` |
### Demo:
``` js
return {
type: 'radio-group-form',
label: '性别',
labelWidth: '160px',
required: true,
disabled: false,
model: 'gender',
modelWidth: '',
values: [{ label: '男', value: 1 }, { label: '女', value: 2 }],
attrs: {},
rules: []
}
```
* 其他属性 [参考文档]([https://](https://element.eleme.cn/#/zh-CN/component/input))
import RadioGroup from './src/radioGroupForm'
/* istanbul ignore next */
RadioGroup.install = function (Vue) {
Vue.component(RadioGroup.name, RadioGroup)
}
export default RadioGroup
<template>
<div class="radio-group-form">
<el-form-item
:key="item.model"
:prop="item.model"
:label="item.label || ''"
:label-width="item.labelWidth || item['label-width'] || ''"
:required="item.required || false"
:rules="item.rules || []"
:size="item.size"
>
<el-radio-group
v-bind="item.attrs"
v-on="$listeners"
v-model="formData[item.model]"
:style="{ width: item.modelWidth || item['model-width'] || '89%' }"
:disabled="item.disabled || false"
>
<el-radio
v-for="radio in item.values"
:label="radio.value"
:key="radio.value"
>{{radio.label}}</el-radio>
</el-radio-group>
<template v-if="formData[item.model] !== null && formData[item.model] !== '' && formData[item.model] !== undefined">
<div class="self-icon el-icon-circle-check" style="color: #237f00;"></div>
</template>
<div class="self-icon el-icon-circle-close" style="color: #b01c40;"></div>
</el-form-item>
</div>
</template>
<script>
export default {
name: 'RadioGroupForm',
componentName: 'RadioGroupForm',
props: {
item: {
type: Object,
default () {
return {}
}
},
formData: {
type: Object,
default () {
return {}
}
}
},
data () {
return {}
}
}
</script>
<style lang="scss">
.self-icon {
display: none !important;
vertical-align: middle;
margin-left: 10px;
font-size: 21px;
line-height: 22px;
}
.is-error .self-icon.el-icon-circle-close { display: inline-block !important; }
.is-success .self-icon.el-icon-circle-check { display: inline-block !important; }
</style>
## 组件简介
| 字段值 | 说明 | 字段属性 | 默认值 |
| ------- | ------------------------- | ------- | ----- |
| `type` | 类型:`String`; 说明:组件类型名 | 自定义字段 | `select-form` |
| `label` | 类型:`String`; 说明:组件左侧显示名称 | element-ui el-form-item对应字段 | `''` |
| `label-width` | 类型:`String`; 说明:组件左侧显示名称宽度(加单位),父级设置可以子级继承 | element-ui el-form-item对应字段 | `''` |
| `required` | 类型:`Boolean`; 说明:标识是否必填 | element-ui el-form-item对应字段 | `false` |
| `disabled` | 类型:`Boolean`; 说明:标识是否只读 | element-ui el-form-item对应字段 | `false` |
| `model` | 类型:`String`; 说明:表单提交name值和回显对照字段 | 自定义字段 | `''` |
| `model-width` | 类型:`String`; 说明:右侧输入组件宽度(加单位) | 自定义字段 | `'89%'` |
| `placeholder` | 类型:`String`; 说明:组件input框中,默认提示文字 | element-ui el-input对应字段 | `''` |
| `values` | 类型:`Array`; 说明:里面是选择类型值label和value(值可以是 int 或 str) | 自定义字段 | `[]` |
| `attrs` | 类型:`Object`; 说明:定义标签上Data属性值 | element-ui对应字段 | `{}` |
| `rules` | 类型:`Array`; 说明:组件错误提示规则 | element-ui el-form-item对应字段 | `[]` |
### Demo Example:
``` js
return {
type: 'select-form',
label: '证件类型',
labelWidth: '160px',
required: true,
disabled: false,
model: 'id_type',
modelWidth: '',
placeholder: '请选择证件类型',
values: [
{ label: '居民身份证', value: 0 },
{ label: '港澳台身份证', value: 1 },
{ label: '护照号', value: 2 },
{ label: '军官证', value: 3 },
{ label: '其他', value: 9 }
],
attrs: {},
rules: []
}
```
* 其他属性 [参考文档]([https://](https://element.eleme.cn/#/zh-CN/component/input))
import Select from './src/selectForm'
/* istanbul ignore next */
Select.install = function (Vue) {
Vue.component(Select.name, Select)
}
export default Select
<template>
<div class="select-form">
<el-form-item
:key="item.model"
:prop="item.model"
:label="item.label || ''"
:label-width="item.labelWidth || item['label-width'] || ''"
:required="item.required || false"
:rules="item.rules || []"
:size="item.size"
>
<el-select :style="{ width: item.modelWidth || item['model-width'] || '89%' }"
v-bind="item.attrs"
v-on="$listeners"
v-model="formData[item.model]"
:placeholder="item.placeholder"
:disabled="item.disabled || false"
>
<el-option
v-for="option in item.values"
:label="option.label"
:value="option.value"
:key="option.value"
></el-option>
</el-select>
<template v-if="formData[item.model] !== null && formData[item.model] !== '' && formData[item.model] !== undefined">
<div class="self-icon el-icon-circle-check" style="color: #237f00;"></div>
</template>
<div class="self-icon el-icon-circle-close" style="color: #b01c40;"></div>
</el-form-item>
</div>
</template>
<script>
export default {
name: 'SelectForm',
componentName: 'SelectForm',
props: {
item: {
type: Object,
default () {
return {}
}
},
formData: {
type: Object,
default () {
return {}
}
}
},
data () {
return {}
}
}
</script>
<style lang="scss">
.self-icon {
display: none !important;
vertical-align: middle;
margin-left: 10px;
font-size: 21px;
line-height: 22px;
}
.is-error .self-icon.el-icon-circle-close { display: inline-block !important; }
.is-success .self-icon.el-icon-circle-check { display: inline-block !important; }
</style>
## 组件简介
| 字段值 | 说明 | 字段属性 | 默认值 |
| ------- | ------------------------- | ------- | ----- |
| `type` | 类型:`String`; 说明:组件类型名 | 自定义字段 | `textarea-form` |
| `label` | 类型:`String`; 说明:组件左侧显示名称 | element-ui el-form-item对应字段 | `''` |
| `label-width` | 类型:`String`; 说明:组件左侧显示名称宽度(加单位),父级设置可以子级继承 | element-ui el-form-item对应字段 | `''` |
| `required` | 类型:`Boolean`; 说明:标识是否必填 | element-ui el-form-item对应字段 | `false` |
| `disabled` | 类型:`Boolean`; 说明:标识是否只读 | element-ui el-form-item对应字段 | `false` |
| `model` | 类型:`String`; 说明:表单提交name值和回显对照字段 | 自定义字段 | `''` |
| `model-width` | 类型:`String`; 说明:右侧输入组件宽度(加单位) | 自定义字段 | `'89%'` |
| `placeholder` | 类型:`String`; 说明:组件input框中,默认提示文字 | element-ui el-input对应字段 | `''` |
| `attrs` | 类型:`Object`; 说明:定义标签上Data属性值 | element-ui对应字段 | `{}` |
| `rules` | 类型:`Array`; 说明:组件错误提示规则 | element-ui el-form-item对应字段 | `[]` |
### Demo:
``` js
return {
type: 'textarea-form',
label: '工作描述',
required: true,
disabled: false,
labelWidth: '160px',
model: 'work_info',
modelWidth: '',
placeholder: '请详细描述您的职责范围,工作任务以及取得的成绩等,填写文字在100个字以上评定等级,少于不计算,内容越详细,等级越高。(字限3000字以内)',
attrs: {
rows: '8',
maxlength: '1000',
'show-word-limit': true
},
rules: [
{
required: true,
message: '请输入内容',
trigger: 'blur'
},
{
min: 60,
max: 1000,
message: '长度在 60 到 1000 个字符',
trigger: 'blur'
}
]
}
```
* 其他属性 [参考文档]([https://](https://element.eleme.cn/#/zh-CN/component/input))
import Textarea from './src/textareaForm'
/* istanbul ignore next */
Textarea.install = function (Vue) {
Vue.component(Textarea.name, Textarea)
}
export default Textarea
<template>
<div class="textarea-form">
<el-form-item
:key="item.model"
:prop="item.model"
:label="item.label || ''"
:label-width="item.labelWidth || item['label-width'] || ''"
:required="item.required || false"
:rules="item.rules || []"
:size="item.size"
>
<el-input :style="{ width: item.modelWidth || item['model-width'] || '89%' }"
type="textarea"
v-bind="item.attrs || {}"
v-on="$listeners"
v-model="formData[item.model]"
:placeholder="item.placeholder || ''"
:disabled="item.disabled || false"
></el-input>
</el-form-item>
</div>
</template>
<script>
export default {
name: 'TextareaForm',
componentName: 'TextareaForm',
props: {
item: {
type: Object,
default () {
return {}
}
},
formData: {
type: Object,
default () {
return {}
}
}
},
data () {
return {}
}
}
</script>
## 组件简介
| 字段值 | 说明 | 字段属性 | 默认值 |
| ------- | ------------------------- | ------- | ----- |
| `type` | 类型:`String`; 说明:组件类型名 | 自定义字段 | `upload-form` |
| `action` | 类型:`String`; 说明:上传请求接口path | 自定义字段 | `` |
| `deleteAction` | 类型:`String`; 说明:删除请求接口path | 自定义字段 | `` |
| `html` | 类型:`String`; 说明:上传说明,支持html | 自定义字段 | `` |
| `label` | 类型:`String`; 说明:组件左侧显示名称 | element-ui el-form-item对应字段 | `''` |
| `label-width` | 类型:`String`; 说明:组件左侧显示名称宽度(加单位),父级设置可以子级继承 | element-ui el-form-item对应字段 | `''` |
| `required` | 类型:`Boolean`; 说明:标识是否必填 | element-ui el-form-item对应字段 | `false` |
| `disabled` | 类型:`Boolean`; 说明:标识是否只读 | element-ui el-form-item对应字段 | `false` |
| `model` | 类型:`String`; 说明:表单提交name值和回显对照字段 | 自定义字段 | `''` |
| `placeholder` | 类型:`String`; 说明:组件input框中,默认提示文字 | element-ui el-input对应字段 | `''` |
| `attrs` | 类型:`Object`; 说明:定义标签上Data属性值 | element-ui对应字段 | `{}` |
| `rules` | 类型:`Array`; 说明:组件错误提示规则 | element-ui el-form-item对应字段 | `[]` |
### Demo Example:
``` js
return {
type: 'upload-form',
label: '姓名',
labeWidth: '160px',
required: true,
disabled: false,
model: 'uploadArrs',
action: '',
data: {
},
deleteAction: '',
deleteData: {
},
html: `
<div style="color: #72818c; font-size: 14px;">
<p style="margin: 0;">申请者需要将有效身份证件原件扫描或者拍照后提交。</p>
<p style="margin: 0;">请您提供有效身份证件的扫描件,身份证与台港澳居民大陆通行证应包括正反两面扫描件。</p>
<p style="margin: 0;">只上传一个文件,多份文件需合并到一个文件后打印出来检查无误后再上传。</p>
<p style="margin: 0;">上传文件仅限“jpg,jpeg,gif,png”格式,文件小于10MB。</p>
</div>
`,
attrs: {
multiple: false,
limit: 1
},
rules: [
{
required: true,
message: '请上传',
trigger: 'blur'
}
]
}
```
* 其他属性 [参考文档]([https://](https://element.eleme.cn/#/zh-CN/component/input))
import Upload from './src/uploadForm'
/* istanbul ignore next */
Upload.install = function (Vue) {
Vue.component(Upload.name, Upload)
}
export default Upload
function getError(action, option, xhr) {
let msg
if (xhr.response) {
msg = `${xhr.response.error || xhr.response}`
} else if (xhr.responseText) {
msg = `${xhr.responseText}`
} else {
msg = `fail to post ${action} ${xhr.status}`
}
const err = new Error(msg)
err.status = xhr.status
err.method = 'post'
err.url = action
return err
}
function getBody(xhr) {
const text = xhr.responseText || xhr.response
if (!text) {
return text
}
try {
return JSON.parse(text)
} catch (e) {
return text
}
}
export function deleteFile (option) {
if (typeof XMLHttpRequest === 'undefined') {
return
}
const xhr = new XMLHttpRequest()
const action = option.action
xhr.onerror = function error(e) {
option.onError(e)
}
xhr.onload = function onload() {
if (xhr.status < 200 || xhr.status >= 300) {
return option.onError(getError(action, option, xhr))
}
option.onSuccess(getBody(xhr))
}
xhr.open('delete', action, true)
if (option.withCredentials && 'withCredentials' in xhr) {
xhr.withCredentials = true
}
const headers = option.headers || {}
for (const item in headers) {
if (headers.hasOwnProperty(item) && headers[item] !== null) {
xhr.setRequestHeader(item, headers[item])
}
}
xhr.send()
return xhr
}
export default function upload(option) {
if (typeof XMLHttpRequest === 'undefined') {
return
}
const xhr = new XMLHttpRequest()
const action = option.action
if (xhr.upload) {
xhr.upload.onprogress = function progress(e) {
if (e.total > 0) {
e.percent = e.loaded / e.total * 100
}
option.onProgress(e)
}
}
const formData = new FormData()
if (option.data) {
Object.keys(option.data).forEach(key => {
formData.append(key, option.data[key])
})
}
formData.append(option.filename, option.file, option.file.name)
xhr.onerror = function error(e) {
option.onError(e)
}
xhr.onload = function onload() {
if (xhr.status < 200 || xhr.status >= 300) {
return option.onError(getError(action, option, xhr))
}
option.onSuccess(getBody(xhr))
}
xhr.open('post', action, true)
if (option.withCredentials && 'withCredentials' in xhr) {
xhr.withCredentials = true
}
const headers = option.headers || {}
for (const item in headers) {
if (headers.hasOwnProperty(item) && headers[item] !== null) {
xhr.setRequestHeader(item, headers[item])
}
}
xhr.send(formData)
return xhr
}
<template>
<div class="upload-form">
<el-form-item
:key="item.model"
:prop="item.model"
:label="item.label || ''"
:label-width="item.labelWidth || item['label-width'] || ''"
:required="item.required || false"
:rules="item.rules || []"
:size="item.size"
>
<div v-html="item.prepend"></div>
<el-upload
:action="item.action"
:data="item.data"
:before-upload="beforeUploadFile"
:on-success="onSuccessFile"
:with-credentials="true"
:show-file-list="false"
:file-list="formData[item.model]"
:disabled="item.disabled || false"
v-bind="item.attrs || {}"
>
<el-button type="primary" size="mini">点击上传</el-button>
<template
v-if="formData[item.model] !== null && formData[item.model] !== '' && formData[item.model] !== undefined"
>
<div class="self-icon el-icon-circle-check" style="color: #237f00"></div>
</template>
<div class="self-icon el-icon-circle-close" style="color: #b01c40"></div>
</el-upload>
<div style="overflow: hidden; padding: 20px 0 0 0">
<template v-if="filesArr.length">
<!-- 遍历显示文件 -->
<template v-for="(item, index) in filesArr">
<template v-if="/(jpeg)|(jpg)|(png)|(gif)/gi.test(item.url)">
<div v-bind:key="item.id" class="show-file">
<template v-if="!(item.disabled || false)">
<div class="close" @click="deleteFiles(index)">X</div>
</template>
<el-avatar shape="square" :size="100" fit="contain" :src="item.url"></el-avatar>
<span class="title">{{ item.sso_file_name }}</span>
<div class="hover">
<a target="_blank" :href="item.url">下载</a>
</div>
</div>
</template>
<template v-else>
<div v-bind:key="item.id" class="show-file">
<template v-if="!(item.disabled || false)">
<div class="close" @click="deleteFiles(index)">X</div>
</template>
<el-avatar shape="square" :size="100" fit="contain" :src="item.url"></el-avatar>
<span class="title">{{ item.sso_file_name }}</span>
<div class="hover">
<a target="_blank" :href="item.url">下载</a>
</div>
</div>
</template>
</template>
</template>
</div>
<div class="info" style="line-height: 1.5" v-html="item.html"></div>
<div v-html="item.append"></div>
</el-form-item>
</div>
</template>
<script>
import { deleteFile } from './ajax'
export default {
name: 'UploadForm',
componentName: 'UploadForm',
props: {
item: {
type: Object,
default() {
return {}
}
},
formData: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
project_id: '',
filesArr: []
}
},
methods: {
beforeUploadFile() {},
onSuccessFile(response, file) {
response.url = response.file || ''
response.sso_file_name = file.name
this.filesArr.push(response)
// this.$emit('onSubmit')
},
deleteFiles(index) {
const temp = this.filesArr[index]
deleteFile({
action: this.item.deleteAction + '/' + temp.id + '?project_id=' + this.item.data.project_id,
onError: () => {},
onSuccess: res => {
if (res.status === 200) {
this.filesArr.splice(index, 1)
}
}
})
}
},
watch: {
formData: {
immediate: true,
deep: true,
handler(value) {
/* 单独处理 - ajax结果在组件渲染之后 */
if (value[this.item.model] && value[this.item.model].length && !this.filesArr.length) {
this.filesArr = value[this.item.model]
this.project_id = this.item.data.project_id
}
}
}
}
}
</script>
<style lang="scss">
.self-icon {
display: none !important;
vertical-align: middle;
margin-left: 10px;
font-size: 21px;
line-height: 22px;
}
.is-error .self-icon.el-icon-circle-close {
display: inline-block !important;
}
.is-success .self-icon.el-icon-circle-check {
display: inline-block !important;
}
.show-file {
position: relative;
float: left;
margin-right: 10px;
.close {
position: absolute;
z-index: 10;
right: -10px;
top: -10px;
width: 20px;
height: 20px;
color: #fff;
font-size: 12px;
line-height: 20px;
text-align: center;
background: #efefef;
border-radius: 50%;
cursor: pointer;
}
.el-avatar {
img {
width: 100%;
}
}
.title {
position: absolute;
left: 0;
bottom: 16px;
width: 100%;
padding-left: 5px;
font-size: 12px;
line-height: 20px;
background: #efefef;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-break: break-all;
box-sizing: border-box;
}
.hover {
display: none;
position: absolute;
z-index: 9;
top: 0;
left: 0;
height: 100px;
width: 100%;
background: rgba(0, 0, 0, 0.2);
line-height: 100px;
text-align: center;
a {
color: #f1f1f1;
}
}
&:hover {
.hover {
display: block;
}
}
}
</style>
import { // import ElementUI from 'element-ui'
Dialog, import VueForm from './VueForm.vue'
Input,
Radio,
RadioGroup,
Checkbox,
CheckboxGroup,
Switch,
Select,
Option,
OptionGroup,
Button,
ButtonGroup,
DatePicker,
TimeSelect,
TimePicker,
Form,
FormItem,
Tabs,
TabPane,
Icon,
Upload,
Message,
Image
} from 'element-ui'
import VueForm from './VueForm' const components = [VueForm]
import VInput from './packages/input'
import VSelect from './packages/select'
import VRadio from './packages/radio'
import VCheckbox from './packages/checkbox'
import VDatepicker from './packages/datepicker'
import VUpload from './packages/upload'
const components = [VueForm, VInput, VSelect, VRadio, VCheckbox, VDatepicker, VUpload] const install = function (Vue) {
const install = function(Vue) {
if (install.installed) return if (install.installed) return
Vue.use(Dialog) // Vue.use(ElementUI)
Vue.use(Input)
Vue.use(Radio)
Vue.use(RadioGroup)
Vue.use(Checkbox)
Vue.use(CheckboxGroup)
Vue.use(Switch)
Vue.use(Select)
Vue.use(Option)
Vue.use(OptionGroup)
Vue.use(Button)
Vue.use(ButtonGroup)
Vue.use(DatePicker)
Vue.use(TimeSelect)
Vue.use(TimePicker)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Tabs)
Vue.use(TabPane)
Vue.use(Icon)
Vue.use(Upload)
Vue.use(Image)
Vue.prototype.$message = Message
// 遍历注册全局组件 // 遍历注册全局组件
components.map(component => Vue.component(component.name, component)) components.map(component => Vue.component(component.name, component))
} }
......
import VCheckbox from './src/main.vue'
VCheckbox.install = function(Vue) {
Vue.component(VCheckbox.name, VCheckbox)
}
export default VCheckbox
import VDatepicker from './src/main.vue'
VDatepicker.install = function(Vue) {
Vue.component(VDatepicker.name, VDatepicker)
}
export default VDatepicker
import VFormPane from '../form/src/form-pane.vue'
VFormPane.install = function(Vue) {
Vue.component(VFormPane.name, VFormPane)
}
export default VFormPane
import VForm from './form.vue'
VForm.install = function(Vue) {
Vue.component(VForm.name, VForm)
}
export default VForm
<template>
<div class="v-form">
<div class="v-form__prepend" v-html="options.prepend" v-if="options.prepend"></div>
<el-form
:disabled="disabled || options.disabled"
v-bind="options"
ref="form"
:model="ruleForm"
@submit.native.prevent
v-on="$listeners"
>
<template v-for="item in currentItems">
<el-form-item v-bind="item" :prop="item.model" :key="item.model">
<template v-if="item.slotName">
<slot :name="item.slotName" v-bind="{ item, items, form: ruleForm }"></slot>
</template>
<template v-else>
<slot
:name="item.prependSlotName"
v-bind="{ item, items, form: ruleForm }"
v-if="item.prependSlotName"
></slot>
<div class="v-form-item__prepend" v-html="item.prepend" v-if="item.prepend"></div>
<component
:is="item.type"
:options="item"
:data="ruleForm"
v-on="$listeners"
v-bind="item.attrs"
></component>
<div class="v-form-item__append" v-html="item.append" v-if="item.append"></div>
<slot
:name="item.appendSlotName"
v-bind="{ item, items, form: ruleForm }"
v-if="item.appendSlotName"
></slot>
</template>
</el-form-item>
</template>
<el-form-item v-if="hasButton">
<slot name="button">
<el-button type="primary" @click="onSubmit">{{ submitText }}</el-button>
</slot>
</el-form-item>
</el-form>
<div class="v-form__append" v-html="options.append" v-if="options.append"></div>
</div>
</template>
<script>
export default {
name: 'VForm',
props: {
disabled: { type: Boolean, default: false },
options: {
type: Object,
default() {
return {}
}
},
model: {
type: Object,
default() {
return {}
}
},
items: { type: Array, default: () => [] },
hasButton: { type: Boolean, default: true },
submitText: { type: String, default: '保存' }
},
data() {
return {
ruleForm: {}
}
},
watch: {
model: {
immediate: true,
deep: true,
handler(value) {
this.ruleForm = value
}
}
},
computed: {
$form() {
return this.$refs.form
},
currentItems() {
return this.items.filter(item => {
if (Object.prototype.hasOwnProperty.call(item, 'isShow')) {
return item.isShow(this.ruleForm)
}
return true
})
}
},
methods: {
validate() {
return this.$form.validate(...arguments)
},
validateField() {
return this.$form.validateField(...arguments)
},
resetFields() {
return this.$form.resetFields(...arguments)
},
clearValidate() {
return this.$form.clearValidate(...arguments)
},
// 提交
onSubmit() {
this.validate().then(() => {
this.$emit('onSubmit', this.model)
})
}
}
}
</script>
import VInput from './src/main.vue'
VInput.install = function(Vue) {
Vue.component(VInput.name, VInput)
}
export default VInput
<template>
<div class="v-form-card">
<div class="v-form-card__hd">
<slot name="header">
<h1 class="v-form-card__title">{{ title }}</h1>
<div class="v-form-card__back" @click="$emit('back')">
<i class="el-icon-arrow-left"></i>
<span>{{ backText }}</span>
</div>
</slot>
</div>
<div class="v-form-card__bd">
<v-form-pane v-bind="$attrs" v-on="$listeners"></v-form-pane>
</div>
</div>
</template>
<script>
import VFormPane from '../../form/src/form-pane'
export default {
name: 'VCardForm',
props: {
title: { type: String },
backText: { type: String, default: '返回报名系统' }
},
components: { VFormPane }
}
</script>
<style lang="scss">
.v-form-card {
padding: 20px;
background: #fff;
border-radius: 5px;
}
.v-form-card__hd {
padding-bottom: 10px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #f5f6fa;
}
.v-form-card__title {
font-size: 14px;
font-weight: bold;
line-height: 1;
color: #222;
}
.v-form-card__back {
font-size: 14px;
line-height: 1;
color: #57acff;
cursor: pointer;
}
.v-form-card__bd {
margin-top: 20px;
}
</style>
\ No newline at end of file
<template>
<div class="v-menu">
<template v-for="item in datalist">
<div :class="{ 'v-menu__item': true, 'is-active': item.isActive }" :key="item.id">
<div class="v-menu__title" @click="handleSelect(item.id, item)">
<span>{{ item.title }}</span>
</div>
<template v-if="item.children">
<!-- 子菜单 -->
<v-submenu :datalist="item.children" @select="handleSelect"></v-submenu>
</template>
</div>
</template>
</div>
</template>
<script>
import VSubmenu from './submenu'
export default {
name: 'VMenu',
components: { VSubmenu },
props: {
datalist: { type: Array, default: () => [] },
router: { type: Boolean, default: false },
defaultActive: { type: String },
beforePageChange: { type: Function }
},
data() {
return {
currentActive: null,
activeIds: []
}
},
watch: {
defaultActive: {
immediate: true,
handler(value) {
this.currentActive = value
// 设置选中的ID,包含父级的ID
this.activeIds = this.setActiveIds(this.datalist, value)
// 更新选中状态
this.changeActiveStatus(this.datalist, this.activeIds)
}
}
},
methods: {
handleSelect(id, menu) {
if (this.beforePageChange && !this.beforePageChange(id, menu)) return
// 有子节点的,选中子节点中的第一个
id = this.getFirstMenuId(menu)
// 当前ID
this.currentActive = id
// 设置选中的ID,包含父级的ID
this.activeIds = this.setActiveIds(this.datalist, id)
// 更新选中状态
this.changeActiveStatus(this.datalist, this.activeIds)
this.$emit('select', id)
},
// 更新菜单数据isActve的状态
changeActiveStatus(menus, selected) {
menus.forEach(item => {
// item.isActive = selected.includes(item.id)
this.$set(item, 'isActive', selected.includes(item.id))
item.children && this.changeActiveStatus(item.children, selected)
})
},
// 设置选中的id
setActiveIds(arr, id) {
let result = []
for (const item of arr) {
if (item.id === id || id === undefined) {
result.push(item.id)
break
}
if (item.children) {
result.push(item.id)
const childrenResult = this.setActiveIds(item.children, id)
result = result.concat(childrenResult)
if (childrenResult.length) {
break
} else {
result.length = 0
}
}
}
return result
},
getFirstMenuId(menu) {
if (menu.children && menu.children.length) {
const [first] = menu.children
if (first.children && first.children) {
return this.getFirstMenuId(first)
} else {
return first.id
}
}
return menu.id
}
},
beforeMount() {
// 没有设置默认选中的,
if (!this.defaultActive && this.datalist.length) {
const [first] = this.datalist
this.handleSelect(first.id, first)
}
}
}
</script>
<style lang="scss">
.v-menu {
margin: 20px 0;
}
.v-menu__item {
margin-bottom: 10px;
}
.v-menu__title {
padding-left: 60px;
height: 44px;
font-size: 14px;
font-weight: bold;
line-height: 44px;
color: #222;
background: #fff4ee;
border-left-style: solid;
border-left-width: 4px;
border-left-color: var(--main-color);
}
</style>
import VRadio from './src/main.vue'
VRadio.install = function(Vue) {
Vue.component(VRadio.name, VRadio)
}
export default VRadio
<template>
<div class="v-select-city"></div>
</template>
<script>
export default {
name: 'VSelectCity',
data() {
return {}
},
methods: {}
}
</script>
\ No newline at end of file
import VSelect from './src/main.vue'
VSelect.install = function(Vue) {
Vue.component(VSelect.name, VSelect)
}
export default VSelect
import VUpload from './src/main.vue'
VUpload.install = function(Vue) {
Vue.component(VUpload.name, VUpload)
}
export default VUpload
...@@ -7,42 +7,24 @@ const httpRequest = axios.create({ ...@@ -7,42 +7,24 @@ const httpRequest = axios.create({
// 请求拦截 // 请求拦截
httpRequest.interceptors.request.use( httpRequest.interceptors.request.use(
function(config) { function (config) {
// 文件上传
if (config.headers['Content-Type'] === 'multipart/form-data') {
let formData = new FormData()
const data = config.data
for (const key in data) {
formData.append(key, data[key])
}
config.data = formData
}
return config
},
function(error) {
return Promise.reject(error)
}
)
// 请求拦截
httpRequest.interceptors.request.use(
function(config) {
return config return config
}, },
function(error) { function (error) {
return Promise.reject(error) return Promise.reject(error)
} }
) )
// 响应拦截 // 响应拦截
httpRequest.interceptors.response.use( httpRequest.interceptors.response.use(
function(response) { function (response) {
const { data } = response const { data } = response
if (data.error.toString() === '1') { if (data.error.toString() === '1') {
return Promise.reject(data) return Promise.reject(data)
} }
return response.data return response.data
}, },
function(error) { function (error) {
if (error.response) { if (error.response) {
return Promise.reject(error.response.data) return Promise.reject(error.response.data)
} else { } else {
......
import fs from 'node:fs'
import { resolve } from 'path'
import { fileURLToPath, URL } from 'node:url'
import vue from '@vitejs/plugin-vue2'
import Components from 'unplugin-vue-components/vite'
import { ElementUiResolver } from 'unplugin-vue-components/resolvers'
export default {
plugins: [
vue()
// Components({
// resolvers: [ElementUiResolver()]
// })
],
server: {
open: true,
host: 'dev.ezijing.com',
https: {
key: fs.readFileSync(resolve(__dirname, './https/ezijing.com.key')),
cert: fs.readFileSync(resolve(__dirname, './https/ezijing.com.pem'))
},
proxy: {
'/api': 'https://project-api.ezijing.com'
}
},
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
build: {
lib: {
entry: resolve(__dirname, 'src/index.js'),
name: 'VueForm',
fileName: 'vue-form'
},
rollupOptions: {
external: ['vue', 'axios'],
output: {
globals: {
vue: 'Vue',
axios: 'axios'
}
}
}
}
}
const fs = require('fs')
const path = require('path')
module.exports = {
pages: {
index: {
entry: 'examples/main.js'
}
},
devServer: {
host: 'dev.ezijing.com',
https: {
key: fs.readFileSync(path.join(__dirname, './cert/dev.ezijing.com.key')),
cert: fs.readFileSync(path.join(__dirname, './cert/dev.ezijing.com.pem'))
},
proxy: {
'/api/enrollment': {
target: 'https://enrollment.ezijing.com',
ws: true,
changeOrigin: true,
pathRewrite: {
'/api/enrollment': '/'
}
}
}
// proxy: 'http://enrollment-test.c3f0f1f4826b94e23a2c355a9dac8a299.cn-beijing.alicontainer.com'
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论