diff --git a/src/Scoped.tsx b/src/Scoped.tsx index f96ca47f4..bf1f40936 100644 --- a/src/Scoped.tsx +++ b/src/Scoped.tsx @@ -1,43 +1,42 @@ /** -* @file 用来创建一个域,在这个域里面会把里面的运行时实例注册进来,方便组件之间的通信。 -* @author fex -*/ + * @file 用来创建一个域,在这个域里面会把里面的运行时实例注册进来,方便组件之间的通信。 + * @author fex + */ import React from 'react'; import find = require('lodash/find'); import PropTypes from 'prop-types'; import hoistNonReactStatic = require('hoist-non-react-statics'); import qs from 'qs'; -import { dataMapping } from './utils/tpl-builtin'; -import { RendererEnv, RendererProps } from './factory'; -import { noop, autobind } from './utils/helper'; -import { RendererData, Action } from './types'; +import {dataMapping} from './utils/tpl-builtin'; +import {RendererEnv, RendererProps} from './factory'; +import {noop, autobind} from './utils/helper'; +import {RendererData, Action} from './types'; interface ScopedComponentType extends React.Component { doAction?: (action: Action, data: RendererData, throwErrors?: boolean) => void; receive?: (values: RendererData, subPath?: string) => void; - reload?: (subPath?:string, query?:RendererData | null, ctx?: RendererData) => void; + reload?: (subPath?: string, query?: RendererData | null, ctx?: RendererData) => void; } - export interface IScopedContext { parent?: AlisIScopedContext; - registerComponent: (component:ScopedComponentType) => void; - unRegisterComponent: (component:ScopedComponentType) => void; - getComponentByName: (name:string) => ScopedComponentType | void; + registerComponent: (component: ScopedComponentType) => void; + unRegisterComponent: (component: ScopedComponentType) => void; + getComponentByName: (name: string) => ScopedComponentType | void; getComponents: () => Array; - reload: (target:string, ctx: RendererData) => void; - send: (target:string, ctx: RendererData) => void; -}; + reload: (target: string, ctx: RendererData) => void; + send: (target: string, ctx: RendererData) => void; +} type AlisIScopedContext = IScopedContext; export const ScopedContext = React.createContext(createScopedTools('')); -function createScopedTools(path?:string, parent?:AlisIScopedContext, env?: RendererEnv):IScopedContext { - const components:Array = []; +function createScopedTools(path?: string, parent?: AlisIScopedContext, env?: RendererEnv): IScopedContext { + const components: Array = []; return { parent, - registerComponent(component:ScopedComponentType) { + registerComponent(component: ScopedComponentType) { // 不要把自己注册在自己的 Scoped 上,自己的 Scoped 是给孩子们注册的。 if (component.props.$path === path && parent) { return parent.registerComponent(component); @@ -48,7 +47,7 @@ function createScopedTools(path?:string, parent?:AlisIScopedContext, env?: Rende } }, - unRegisterComponent(component:ScopedComponentType) { + unRegisterComponent(component: ScopedComponentType) { // 自己本身实际上注册在父级 Scoped 上。 if (component.props.$path === path && parent) { return parent.unRegisterComponent(component); @@ -61,7 +60,7 @@ function createScopedTools(path?:string, parent?:AlisIScopedContext, env?: Rende } }, - getComponentByName(name:string) { + getComponentByName(name: string) { if (~name.indexOf('.')) { const paths = name.split('.'); const len = paths.length; @@ -69,22 +68,25 @@ function createScopedTools(path?:string, parent?:AlisIScopedContext, env?: Rende return paths.reduce((scope, name, idx) => { if (scope && scope.getComponentByName) { const result = scope.getComponentByName(name); - return result && idx < (len - 1) ? result.context : result; + return result && idx < len - 1 ? result.context : result; } return null; }, this); } - const resolved = find(components, component => component.props.name === name || component.props.id === name); - return resolved || parent && parent.getComponentByName(name); + const resolved = find( + components, + component => component.props.name === name || component.props.id === name + ); + return resolved || (parent && parent.getComponentByName(name)); }, getComponents() { return components.concat(); }, - reload(target:string, ctx:any) { + reload(target: string, ctx: any) { const scoped = this; if (target === 'window') { @@ -114,7 +116,7 @@ function createScopedTools(path?:string, parent?:AlisIScopedContext, env?: Rende }); }, - send(receive:string, values:object) { + send(receive: string, values: object) { const scoped = this; let receives = typeof receive === 'string' ? receive.split(/\s*,\s*/) : receive; @@ -131,10 +133,10 @@ function createScopedTools(path?:string, parent?:AlisIScopedContext, env?: Rende const component = scoped.getComponentByName(name); if (component && component.receive) { - component.receive(values, subPath) + component.receive(values, subPath); } else if (name === 'window' && env && env.updateLocation) { - const query = { - ...location.search ? qs.parse(location.search.substring(1)) : {}, + const query = { + ...(location.search ? qs.parse(location.search.substring(1)) : {}), ...values }; const link = location.pathname + '?' + qs.stringify(query); @@ -142,24 +144,32 @@ function createScopedTools(path?:string, parent?:AlisIScopedContext, env?: Rende } }); } - } + }; } -export function HocScoped(ComposedComponent: React.ComponentType):React.ComponentType void -}> & { +export function HocScoped< + T extends { + $path?: string; + env: RendererEnv; + } +>( ComposedComponent: React.ComponentType +): React.ComponentType< + T & { + scopeRef?: (ref: any) => void; + } +> & { + ComposedComponent: React.ComponentType; } { - class ScopedComponent extends React.Component< T & { - scopeRef?: (ref: any) => void - }> { + class ScopedComponent extends React.Component< + T & { + scopeRef?: (ref: any) => void; + } + > { static displayName = `Scoped(${ComposedComponent.displayName || ComposedComponent.name})`; static contextType = ScopedContext; static ComposedComponent = ComposedComponent; - ref:any; + ref: any; getWrappedInstance() { return this.ref; @@ -174,7 +184,7 @@ export function HocScoped - ) + ); } } hoistNonReactStatic(ScopedComponent, ComposedComponent); return ScopedComponent; -}; +} export default HocScoped; diff --git a/src/compat.ts b/src/compat.ts index 76ac154dd..d7a8d67bb 100644 --- a/src/compat.ts +++ b/src/compat.ts @@ -2,39 +2,20 @@ * @file 兼容配置,对于一些老的 api 设计的得不合理的地方做一些适配。 * @author fex */ -import { - SchemaNode, - Schema -} from './types'; -import { - RendererProps, - RendererConfig, - addSchemaFilter -} from './factory'; -import { - CheckboxControlRenderer -} from './renderers/Form/Checkbox'; -import { - FormRenderer -} from './renderers/Form/index'; -import { - FieldSetRenderer -} from './renderers/Form/FieldSet'; -import { - TabsRenderer -} from './renderers/Form/Tabs'; -import { - CardRenderer -} from './renderers/Card'; -import { - ListItemRenderer -} from './renderers/List'; -import { ButtonGroupControlRenderer } from './renderers/Form/ButtonGroup'; -import { getLevelFromClassName } from './utils/helper'; -import { ServiceRenderer } from './renderers/Form/Service'; +import {SchemaNode, Schema} from './types'; +import {RendererProps, RendererConfig, addSchemaFilter} from './factory'; +import {CheckboxControlRenderer} from './renderers/Form/Checkbox'; +import {FormRenderer} from './renderers/Form/index'; +import {FieldSetRenderer} from './renderers/Form/FieldSet'; +import {TabsRenderer} from './renderers/Form/Tabs'; +import {CardRenderer} from './renderers/Card'; +import {ListItemRenderer} from './renderers/List'; +import {ButtonGroupControlRenderer} from './renderers/Form/ButtonGroup'; +import {getLevelFromClassName} from './utils/helper'; +import {ServiceRenderer} from './renderers/Form/Service'; // 兼容老的用法,老用法 label 用在 checkbox 的右侧内容,新用法用 option 来代替。 -addSchemaFilter(function CheckboxPropsFilter(schema:Schema, renderer) { +addSchemaFilter(function CheckboxPropsFilter(schema: Schema, renderer) { if (renderer.component !== CheckboxControlRenderer) { return schema; } @@ -50,12 +31,12 @@ addSchemaFilter(function CheckboxPropsFilter(schema:Schema, renderer) { return schema; }); -function convertFieldSetTabs2Controls(schema:any) { - const toUpdate:any = {}; +function convertFieldSetTabs2Controls(schema: any) { + const toUpdate: any = {}; let flag = false; toUpdate.controls = Array.isArray(schema.controls) ? schema.controls.concat() : []; - toUpdate.controls = toUpdate.controls.map((control:any) => { + toUpdate.controls = toUpdate.controls.map((control: any) => { if (Array.isArray(control)) { let converted = convertFieldSetTabs2Controls({ type: 'group', @@ -67,23 +48,26 @@ function convertFieldSetTabs2Controls(schema:any) { } return converted; - } + } return control; }); - schema.fieldSet && (Array.isArray(schema.fieldSet) ? schema.fieldSet : [schema.fieldSet]).forEach((fieldSet:any) => { - flag = true; - toUpdate.controls.push({ - ...convertFieldSetTabs2Controls(fieldSet), - type: 'fieldSet', - collapsable: schema.collapsable + schema.fieldSet && + (Array.isArray(schema.fieldSet) ? schema.fieldSet : [schema.fieldSet]).forEach((fieldSet: any) => { + flag = true; + toUpdate.controls.push({ + ...convertFieldSetTabs2Controls(fieldSet), + type: 'fieldSet', + collapsable: schema.collapsable + }); }); - }); - schema.tabs && (flag = true) && toUpdate.controls.push({ - type: 'tabs', - tabs: schema.tabs.map((tab:any) => convertFieldSetTabs2Controls(tab)) - }); + schema.tabs && + (flag = true) && + toUpdate.controls.push({ + type: 'tabs', + tabs: schema.tabs.map((tab: any) => convertFieldSetTabs2Controls(tab)) + }); if (flag) { schema = { @@ -98,7 +82,7 @@ function convertFieldSetTabs2Controls(schema:any) { // Form 中,把 fieldSet 和 tabs 转成 {type: 'fieldSet', controls: []} // 同时把数组用法转成 {type: 'group', controls: []} -addSchemaFilter(function FormPropsFilter(schema:Schema, renderer) { +addSchemaFilter(function FormPropsFilter(schema: Schema, renderer) { if (renderer.component !== FormRenderer) { return schema; } @@ -108,7 +92,7 @@ addSchemaFilter(function FormPropsFilter(schema:Schema, renderer) { schema = convertFieldSetTabs2Controls(schema); } else if (Array.isArray(schema.controls)) { let flag = false; - let converted = schema.controls.map((control:any) => { + let converted = schema.controls.map((control: any) => { if (Array.isArray(control)) { let converted = convertFieldSetTabs2Controls({ type: 'group', @@ -119,7 +103,7 @@ addSchemaFilter(function FormPropsFilter(schema:Schema, renderer) { flag = true; } return converted; - } + } return control; }); @@ -135,14 +119,14 @@ addSchemaFilter(function FormPropsFilter(schema:Schema, renderer) { }); // FieldSet 中把 controls 里面的数组用法转成 {type: 'group', controls: []} -addSchemaFilter(function FormPropsFilter(schema:Schema, renderer) { +addSchemaFilter(function FormPropsFilter(schema: Schema, renderer) { if (renderer.component !== FieldSetRenderer) { return schema; } if (Array.isArray(schema.controls)) { let flag = false; - let converted = schema.controls.map((control:any) => { + let converted = schema.controls.map((control: any) => { if (Array.isArray(control)) { let converted = convertFieldSetTabs2Controls({ type: 'group', @@ -153,7 +137,7 @@ addSchemaFilter(function FormPropsFilter(schema:Schema, renderer) { flag = true; } return converted; - } + } return control; }); @@ -169,16 +153,16 @@ addSchemaFilter(function FormPropsFilter(schema:Schema, renderer) { }); // Form 里面的 Tabs 中把 controls 里面的数组用法转成 {type: 'group', controls: []} -addSchemaFilter(function FormPropsFilter(schema:Schema, renderer) { +addSchemaFilter(function FormPropsFilter(schema: Schema, renderer) { if (renderer.component !== TabsRenderer) { return schema; } if (Array.isArray(schema.tabs)) { let flag = false; - let converted = schema.tabs.map((tab:any) => { + let converted = schema.tabs.map((tab: any) => { let flag2 = false; - let converted = (tab.controls || []).map((control:any) => { + let converted = (tab.controls || []).map((control: any) => { if (Array.isArray(control)) { let converted = convertFieldSetTabs2Controls({ type: 'group', @@ -189,7 +173,7 @@ addSchemaFilter(function FormPropsFilter(schema:Schema, renderer) { flag2 = true; } return converted; - } + } return control; }); @@ -215,9 +199,9 @@ addSchemaFilter(function FormPropsFilter(schema:Schema, renderer) { return schema; }); -function convertArray2Hbox(arr:Array):any { +function convertArray2Hbox(arr: Array): any { let flag = false; - let converted = arr.map((item:any) => { + let converted = arr.map((item: any) => { if (Array.isArray(item)) { flag = true; return convertArray2Hbox(item); @@ -233,22 +217,21 @@ function convertArray2Hbox(arr:Array):any { type: 'hbox', columns: converted }; - } // CRUD/List 和 CRUD/Card 的 body 中的数组用法转成 hbox -addSchemaFilter(function(schema:Schema, renderer) { +addSchemaFilter(function(schema: Schema, renderer) { if (renderer.component !== CardRenderer && renderer.component !== ListItemRenderer) { return schema; } if (Array.isArray(schema.body)) { let flag = false; - let converted = schema.body.map((item:any) => { + let converted = schema.body.map((item: any) => { if (Array.isArray(item)) { flag = true; return convertArray2Hbox(item); - } + } return item; }); @@ -264,7 +247,7 @@ addSchemaFilter(function(schema:Schema, renderer) { }); // button group 的 btnClassName 和 btnActiveClassName 改成 btnLevel 和 btnActiveLevel 了 -addSchemaFilter(function(scheam:Schema, renderer) { +addSchemaFilter(function(scheam: Schema, renderer) { if (renderer.component !== ButtonGroupControlRenderer) { return scheam; } @@ -284,7 +267,7 @@ addSchemaFilter(function(scheam:Schema, renderer) { }); // FieldSet className 定制样式方式改成 size 来配置 -addSchemaFilter(function(scheam:Schema, renderer) { +addSchemaFilter(function(scheam: Schema, renderer) { if (renderer.component !== FieldSetRenderer) { return scheam; } @@ -304,7 +287,7 @@ addSchemaFilter(function(scheam:Schema, renderer) { }); // FieldSet className 定制样式方式改成 size 来配置 -addSchemaFilter(function(scheam:Schema, renderer) { +addSchemaFilter(function(scheam: Schema, renderer) { if (renderer.component !== ServiceRenderer) { return scheam; } @@ -318,4 +301,4 @@ addSchemaFilter(function(scheam:Schema, renderer) { } return scheam; -}); \ No newline at end of file +}); diff --git a/src/components/Alert.tsx b/src/components/Alert.tsx index 711210780..ff411bc0f 100644 --- a/src/components/Alert.tsx +++ b/src/components/Alert.tsx @@ -49,7 +49,7 @@ export class Alert extends React.Component { show: false, title: '', content: '', - confirm: false, + confirm: false }; constructor(props: AlertProps) { super(props); @@ -66,7 +66,7 @@ export class Alert extends React.Component { cancelText: '取消', title: '系统消息', alertBtnLevel: 'primary', - confirmBtnLevel: 'danger', + confirmBtnLevel: 'danger' }; componentWillMount() { @@ -100,7 +100,7 @@ export class Alert extends React.Component { this.setState( { - show: false, + show: false }, isConfirm ? () => this._resolve(confirmed) /*this._reject()*/ : undefined ); @@ -111,7 +111,7 @@ export class Alert extends React.Component { title, content, show: true, - confirm: false, + confirm: false }); } @@ -120,7 +120,7 @@ export class Alert extends React.Component { title, content, show: true, - confirm: true, + confirm: true }); return new Promise(resolve => { @@ -146,7 +146,7 @@ export class Alert extends React.Component { confirmBtnLevel, alertBtnLevel, classnames: cx, - classPrefix, + classPrefix } = this.props; return ( diff --git a/src/components/Alert2.tsx b/src/components/Alert2.tsx index 9759188dc..97b20257b 100644 --- a/src/components/Alert2.tsx +++ b/src/components/Alert2.tsx @@ -23,7 +23,7 @@ export class Alert extends React.Component { static defaultProps: Pick = { level: 'info', className: '', - showCloseButton: false, + showCloseButton: false }; static propsList: Array = ['level', 'className', 'showCloseButton', 'onClose']; @@ -32,14 +32,14 @@ export class Alert extends React.Component { this.handleClick = this.handleClick.bind(this); this.state = { - show: true, + show: true }; } handleClick() { this.setState( { - show: false, + show: false }, this.props.onClose ); diff --git a/src/components/AsideNav.tsx b/src/components/AsideNav.tsx index 20c4f3e2c..f1e0548eb 100644 --- a/src/components/AsideNav.tsx +++ b/src/components/AsideNav.tsx @@ -65,7 +65,7 @@ export class AsideNav extends React.Component {
{link.label}
) : null, isActive: (link: LinkItem) => link.open, - isOpen: (item: LinkItemProps) => (item.children ? item.children.some(item => item.open) : false), + isOpen: (item: LinkItemProps) => (item.children ? item.children.some(item => item.open) : false) }; constructor(props: AsideNavProps) { @@ -84,12 +84,12 @@ export class AsideNav extends React.Component { ...item, id: id++, active: isActive, - open: isActive || isOpen(item as LinkItemProps), + open: isActive || isOpen(item as LinkItemProps) }; }, 1, true - ), + ) }; this.renderLink = this.renderLink.bind(this); @@ -113,12 +113,12 @@ export class AsideNav extends React.Component { ...item, id: id++, active: isActive, - open: isActive || isOpen(item as LinkItemProps), + open: isActive || isOpen(item as LinkItemProps) }; }, 1, true - ), + ) }); } } @@ -134,11 +134,11 @@ export class AsideNav extends React.Component { this.state.navigations, (item: Navigation) => ({ ...item, - open: link.id === item.id ? !item.open : item.open, + open: link.id === item.id ? !item.open : item.open }), 1, true - ), + ) }); } @@ -152,7 +152,7 @@ export class AsideNav extends React.Component { toggleExpand: this.toggleExpand, depth, classnames: cx, - ...others, + ...others }); if (!dom) { @@ -165,7 +165,7 @@ export class AsideNav extends React.Component { key={key} className={cx(`AsideNav-item`, link.className, { [`is-open`]: link.open, - [`is-active`]: link.active, + [`is-active`]: link.active })} > {dom} @@ -188,7 +188,7 @@ export class AsideNav extends React.Component { links.push( React.cloneElement(prefix, { ...prefix.props, - key: `${index}-prefix`, + key: `${index}-prefix` }) ); } @@ -211,7 +211,7 @@ export class AsideNav extends React.Component { links.push( React.cloneElement(affix, { ...affix.props, - key: `${index}-affix`, + key: `${index}-affix` }) ); } diff --git a/src/components/Button.tsx b/src/components/Button.tsx index 198c5e4e7..b85bbc275 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -41,7 +41,7 @@ export class Button extends React.Component { type: 'button', placement: 'top', tooltipTrigger: ['hover', 'focus'], - tooltipRootClose: false, + tooltipRootClose: false }; renderButton() { @@ -79,7 +79,7 @@ export class Button extends React.Component { [`Button--block`]: block, [`Button--iconOnly`]: iconOnly, 'is-disabled': disabled, - 'is-active': active, + 'is-active': active }, className )} @@ -100,7 +100,7 @@ export class Button extends React.Component { disabled, disabledTip, classPrefix, - classnames: cx, + classnames: cx } = this.props; return ( diff --git a/src/components/Checkbox.tsx b/src/components/Checkbox.tsx index fc02243b5..e0384fc44 100644 --- a/src/components/Checkbox.tsx +++ b/src/components/Checkbox.tsx @@ -12,7 +12,7 @@ const sizeMap = { sm: 'i-checks-sm', lg: 'i-checks-lg', small: 'i-checks-sm', - large: 'i-checks-lg', + large: 'i-checks-lg' }; interface CheckboxProps { @@ -42,7 +42,7 @@ export class Checkbox extends React.Component { static defaultProps = { trueValue: true, falseValue: false, - type: 'checkbox', + type: 'checkbox' }; @autobind @@ -70,7 +70,7 @@ export class Checkbox extends React.Component { readOnly, checked, type, - name, + name } = this.props; className = (className ? className : '') + (size && sizeMap[size] ? ` ${sizeMap[size]}` : ''); @@ -80,7 +80,7 @@ export class Checkbox extends React.Component { className={cx( `${ns}Checkbox ${ns}Checkbox--${type}`, { - [`${ns}Checkbox--full`]: !partial, + [`${ns}Checkbox--full`]: !partial }, className )} @@ -106,4 +106,4 @@ export class Checkbox extends React.Component { } } -export default themeable(Checkbox); \ No newline at end of file +export default themeable(Checkbox); diff --git a/src/components/Checkboxes.tsx b/src/components/Checkboxes.tsx index e2c396658..fb12454d4 100644 --- a/src/components/Checkboxes.tsx +++ b/src/components/Checkboxes.tsx @@ -120,7 +120,7 @@ export class Checkboxes extends React.PureComponent { extractValue: false, inline: false, delimiter: ',', - columnsCount: 1, // 一行显示一个 + columnsCount: 1 // 一行显示一个 }; toggleOption(option: Option) { @@ -130,7 +130,7 @@ export class Checkboxes extends React.PureComponent { multiple: true, valueField, delimiter, - options, + options }); let idx = valueArray.indexOf(option); @@ -140,7 +140,7 @@ export class Checkboxes extends React.PureComponent { multiple: true, valueField, delimiter, - options, + options })[0] || option; idx = valueArray.indexOf(option); } @@ -172,14 +172,14 @@ export class Checkboxes extends React.PureComponent { placeholder, columnsCount, disabled, - inline, + inline } = this.props; let valueArray = value2array(value, { multiple: true, valueField, delimiter, - options, + options }); let body: Array = []; @@ -219,6 +219,6 @@ export class Checkboxes extends React.PureComponent { export default themeable( uncontrollable(Checkboxes, { - value: 'onChange', + value: 'onChange' }) ); diff --git a/src/components/Collapse.tsx b/src/components/Collapse.tsx index 25ae005ad..120e044d4 100644 --- a/src/components/Collapse.tsx +++ b/src/components/Collapse.tsx @@ -7,8 +7,8 @@ import React from 'react'; import css = require('dom-helpers/style'); import {ClassNamesFn, themeable} from '../theme'; -import Transition, { EXITED, ENTERING, EXITING } from 'react-transition-group/Transition'; -import { autobind } from '../utils/helper'; +import Transition, {EXITED, ENTERING, EXITING} from 'react-transition-group/Transition'; +import {autobind} from '../utils/helper'; const collapseStyles: { [propName: string]: string; @@ -19,23 +19,20 @@ const collapseStyles: { }; export interface CollapseProps { - show?: boolean, - mountOnEnter?: boolean, - unmountOnExit?: boolean, - className?: string, + show?: boolean; + mountOnEnter?: boolean; + unmountOnExit?: boolean; + className?: string; classPrefix: string; classnames: ClassNamesFn; } export class Collapse extends React.Component { - static defaultProps: Pick< - CollapseProps, - 'show' | 'mountOnEnter' | 'unmountOnExit' - > = { + static defaultProps: Pick = { show: false, mountOnEnter: false, unmountOnExit: false - } + }; contentDom: any; contentRef = (ref: any) => (this.contentDom = ref); @@ -71,13 +68,7 @@ export class Collapse extends React.Component { } render() { - const { - show, - children, - classnames: cx, - mountOnEnter, - unmountOnExit - } = this.props; + const {show, children, classnames: cx, mountOnEnter, unmountOnExit} = this.props; return ( { onExit={this.handleExit} onExiting={this.handleExiting} > - {(status:string) => { + {(status: string) => { if (status === ENTERING) { this.contentDom.offsetWidth; } @@ -103,11 +94,11 @@ export class Collapse extends React.Component { (children as React.ReactElement).props.className, collapseStyles[status] ) - })} - } + }); + }} ); } } -export default themeable(Collapse); \ No newline at end of file +export default themeable(Collapse); diff --git a/src/components/ColorPicker.tsx b/src/components/ColorPicker.tsx index c05665839..c12c44ef8 100644 --- a/src/components/ColorPicker.tsx +++ b/src/components/ColorPicker.tsx @@ -40,13 +40,13 @@ export class ColorControl extends React.PureComponent { const dom: HTMLElement = this.preview.current as HTMLElement; @@ -148,7 +148,7 @@ export class ColorControl extends React.PureComponent = []; - if ( this.props.input ) { + // TODO: Make a function or clean up this code, + // logic right now is really hard to follow + let className = + 'rdt' + + (this.props.className + ? Array.isArray(this.props.className) + ? ' ' + this.props.className.join(' ') + : ' ' + this.props.className + : ''), + children: Array = []; + + if (this.props.input) { var finalInputProps = { type: 'text', className: 'form-control', @@ -69,23 +73,18 @@ class BaseDatePicker extends ReactDatePicker { ...this.props.inputProps }; - if ( this.props.renderInput ) { - children = [( -
- {this.props.renderInput(finalInputProps, this.openCalendar, this.closeCalendar)} -
- )]; - } else { - children= [ - + if (this.props.renderInput) { + children = [ +
{this.props.renderInput(finalInputProps, this.openCalendar, this.closeCalendar)}
]; + } else { + children = []; } } else { className += ' rdtStatic'; } - if ( this.state.open ) - className += ' rdtOpen'; + if (this.state.open) className += ' rdtOpen'; return (
@@ -127,7 +126,7 @@ interface CustomDaysViewProps { class CustomDaysView extends React.Component { static defaultProps = { - classPrefix: 'a-', + classPrefix: 'a-' }; constructor(props: CustomDaysViewProps) { @@ -183,7 +182,7 @@ class CustomDaysView extends React.Component { this.props.setDateTimeState({ viewDate, - selectedDate: viewDate.clone(), + selectedDate: viewDate.clone() }); return; } @@ -206,7 +205,7 @@ class CustomDaysView extends React.Component { viewDate: viewDate .clone() .month(option.value) - .startOf('month'), + .startOf('month') }); } @@ -223,7 +222,7 @@ class CustomDaysView extends React.Component { const viewDate = this.props.viewDate; const newDate = viewDate.clone().year(option.value); this.props.setDateTimeState({ - viewDate: newDate[newDate.isBefore(viewDate) ? 'endOf' : 'startOf']('year'), + viewDate: newDate[newDate.isBefore(viewDate) ? 'endOf' : 'startOf']('year') }); } @@ -233,7 +232,7 @@ class CustomDaysView extends React.Component { this.props.setDateTimeState({ viewDate: date.clone(), - selectedDate: date.clone(), + selectedDate: date.clone() }); if (!this.props.requiredConfirm) { @@ -245,7 +244,7 @@ class CustomDaysView extends React.Component { const date = this.props.viewDate.clone(); this.props.setDateTimeState({ - selectedDate: date, + selectedDate: date }); this.props.onChange(date); this.props.onClose && this.props.onClose(); @@ -276,12 +275,12 @@ class CustomDaysView extends React.Component { let currentYear = date.clone().set({ year: year, month: irrelevantMonth, - date: irrelevantDate, + date: irrelevantDate }); const noOfDaysInYear = parseInt(currentYear.endOf('year').format('DDD'), 10); const daysInYear = Array.from( { - length: noOfDaysInYear, + length: noOfDaysInYear }, (e, i) => i + 1 ); @@ -303,12 +302,12 @@ class CustomDaysView extends React.Component { let currentYear = date.clone().set({ year: year, month: irrelevantMonth, - date: irrelevantDate, + date: irrelevantDate }); const noOfDaysInYear = parseInt(currentYear.endOf('year').format('DDD'), 10); const daysInYear = Array.from( { - length: noOfDaysInYear, + length: noOfDaysInYear }, (e, i) => i + 1 ); @@ -327,7 +326,7 @@ class CustomDaysView extends React.Component { value={date.year()} options={years.map(year => ({ label: `${year}`, - value: year, + value: year }))} onChange={this.handleYearChange} clearable={false} @@ -348,7 +347,7 @@ class CustomDaysView extends React.Component { const currentMonth = date.clone().set({ year, month: i, - date: 1, + date: 1 }); const noOfDaysInMonth = parseInt(currentMonth.endOf('month').format('D'), 10); @@ -369,7 +368,7 @@ class CustomDaysView extends React.Component { value={date.month()} options={days.map(day => ({ label: `${day + 1}`, - value: day, + value: day }))} onChange={this.handleMonthChange} clearable={false} @@ -484,7 +483,7 @@ class CustomDaysView extends React.Component { dayProps = { key: prevMonth.format('M_D'), 'data-value': prevMonth.date(), - className: classes, + className: classes }; if (!isDisabled) dayProps.onClick = this.handleDayChange; @@ -532,7 +531,7 @@ class CustomDaysView extends React.Component { , - {this.renderDays()}, + {this.renderDays()} ]; footer && tableChildren.push(footer); @@ -545,13 +544,12 @@ class CustomDaysView extends React.Component { } } - const availableShortcuts: {[propName: string]: any} = { today: { label: '今天', date: (now: moment.Moment) => { return now.startOf('day'); - }, + } }, yesterday: { @@ -586,15 +584,13 @@ const availableShortcuts: {[propName: string]: any} = { label: '90天前', date: (now: moment.Moment) => { return now.add(-90, 'days'); - }, + } }, thisweek: { label: '本周一', date: (now: moment.Moment) => { - return now - .startOf('week') - .add(-1, 'weeks'); + return now.startOf('week').add(-1, 'weeks'); } }, @@ -602,7 +598,7 @@ const availableShortcuts: {[propName: string]: any} = { label: '本月初', date: (now: moment.Moment) => { return now.startOf('month'); - }, + } }, prevmonth: { @@ -616,7 +612,7 @@ const availableShortcuts: {[propName: string]: any} = { label: '上个季节初', date: (now: moment.Moment) => { return now.startOf('quarter').add(-1, 'quarter'); - }, + } }, thisquarter: { @@ -658,14 +654,13 @@ const availableShortcuts: {[propName: string]: any} = { label: '90天后', date: (now: moment.Moment) => { return now.add(90, 'days'); - }, + } }, endofthisweek: { label: '本周日', date: (now: moment.Moment) => { - return now - .endOf('week'); + return now.endOf('week'); } }, @@ -673,7 +668,7 @@ const availableShortcuts: {[propName: string]: any} = { label: '本月底', date: (now: moment.Moment) => { return now.endOf('month'); - }, + } } }; @@ -711,12 +706,14 @@ export interface DatePickerState { export class DatePicker extends React.Component { static defaultProps: Pick = { viewMode: 'days', - shortcuts: '', + shortcuts: '' }; state: DatePickerState = { isOpened: false, isFocused: false, - value: this.props.value ? (this.props.utc ? moment.utc : moment)(this.props.value, this.props.format) : undefined, + value: this.props.value + ? (this.props.utc ? moment.utc : moment)(this.props.value, this.props.format) + : undefined }; constructor(props: DateProps) { super(props); @@ -741,7 +738,9 @@ export class DatePicker extends React.Component { componentWillReceiveProps(nextProps: DateProps) { if (this.props.value !== nextProps.value) { this.setState({ - value: nextProps.value ? (nextProps.utc ? moment.utc : moment)(nextProps.value, nextProps.format) : undefined, + value: nextProps.value + ? (nextProps.utc ? moment.utc : moment)(nextProps.value, nextProps.format) + : undefined }); } } @@ -756,13 +755,13 @@ export class DatePicker extends React.Component { handleFocus() { this.setState({ - isFocused: true, + isFocused: true }); } handleBlur() { this.setState({ - isFocused: false, + isFocused: false }); } @@ -785,7 +784,7 @@ export class DatePicker extends React.Component { this.props.disabled || this.setState( { - isOpened: true, + isOpened: true }, fn ); @@ -793,7 +792,7 @@ export class DatePicker extends React.Component { close() { this.setState({ - isOpened: false, + isOpened: false }); } @@ -824,7 +823,7 @@ export class DatePicker extends React.Component { } } - selectRannge(item:any) { + selectRannge(item: any) { const now = moment(); this.handleChange(item.date(now)); this.close(); @@ -886,7 +885,7 @@ export class DatePicker extends React.Component { `${ns}DatePicker`, { 'is-disabled': disabled, - 'is-focused': this.state.isFocused, + 'is-focused': this.state.isFocused }, className )} @@ -942,7 +941,7 @@ export class DatePicker extends React.Component { ))} ) : null} - + { return now; - }, + } }, yesterday: { @@ -61,7 +61,7 @@ const availableRanges: {[propName: string]: any} = { }, endDate: (now: moment.Moment) => { return now.add(-1, 'days').endOf('day'); - }, + } }, '1dayago': { @@ -71,7 +71,7 @@ const availableRanges: {[propName: string]: any} = { }, endDate: (now: moment.Moment) => { return now; - }, + } }, '7daysago': { @@ -81,7 +81,7 @@ const availableRanges: {[propName: string]: any} = { }, endDate: (now: moment.Moment) => { return now; - }, + } }, '90daysago': { @@ -91,22 +91,20 @@ const availableRanges: {[propName: string]: any} = { }, endDate: (now: moment.Moment) => { return now; - }, + } }, prevweek: { label: '上周', startDate: (now: moment.Moment) => { - return now - .startOf('week') - .add(-1, 'weeks'); + return now.startOf('week').add(-1, 'weeks'); }, endDate: (now: moment.Moment) => { return now .startOf('week') .add(-1, 'days') .endOf('day'); - }, + } }, thismonth: { @@ -116,7 +114,7 @@ const availableRanges: {[propName: string]: any} = { }, endDate: (now: moment.Moment) => { return now; - }, + } }, prevmonth: { @@ -129,7 +127,7 @@ const availableRanges: {[propName: string]: any} = { .startOf('month') .add(-1, 'day') .endOf('day'); - }, + } }, prevquarter: { @@ -142,7 +140,7 @@ const availableRanges: {[propName: string]: any} = { .startOf('quarter') .add(-1, 'day') .endOf('day'); - }, + } }, thisquarter: { @@ -152,8 +150,8 @@ const availableRanges: {[propName: string]: any} = { }, endDate: (now: moment.Moment) => { return now; - }, - }, + } + } }; export class DateRangePicker extends React.Component { @@ -166,7 +164,7 @@ export class DateRangePicker extends React.Component diff --git a/src/components/Drawer.tsx b/src/components/Drawer.tsx index cf7bd0d38..47f2d872b 100644 --- a/src/components/Drawer.tsx +++ b/src/components/Drawer.tsx @@ -38,20 +38,20 @@ const fadeStyles: { [propName: string]: string; } = { [ENTERING]: 'in', - [ENTERED]: 'in', + [ENTERED]: 'in' }; export class Drawer extends React.Component { static defaultProps: Pick< DrawerProps, 'container' | 'position' | 'size' | 'overlay' | 'disableOnClickOutside' | 'enableOnClickOutside' > = { - container: document.body, - position: 'left', - size: 'md', - overlay: true, - disableOnClickOutside: noop, - enableOnClickOutside: noop, - }; + container: document.body, + position: 'left', + size: 'md', + overlay: true, + disableOnClickOutside: noop, + enableOnClickOutside: noop + }; contentDom: any; @@ -111,7 +111,7 @@ export class Drawer extends React.Component { size, onHide, disabled, - overlay, + overlay } = this.props; return ( @@ -141,7 +141,7 @@ export class Drawer extends React.Component { { [`${ns}Drawer--${position}`]: position, [`${ns}Drawer--${size}`]: size, - [`${ns}Drawer--noOverlay`]: !overlay, + [`${ns}Drawer--noOverlay`]: !overlay }, className )} diff --git a/src/components/Html.tsx b/src/components/Html.tsx index 2ab142277..23f7925a3 100644 --- a/src/components/Html.tsx +++ b/src/components/Html.tsx @@ -20,7 +20,7 @@ export interface HtmlProps { export class Html extends React.Component { static defaultProps = { - inline: true, + inline: true }; dom: any; diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index 7b41de74a..48d9a10ca 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -53,7 +53,7 @@ export function Layout({ boxed, classnames: cx, bodyClassName -}:LayoutProps) { +}: LayoutProps) { let body =
{children}
; if (aside) { @@ -68,7 +68,7 @@ export function Layout({ bodyClassName && document.body.classList.add(bodyClassName); return () => { - bodyClassName && document.body.classList.remove(bodyClassName) + bodyClassName && document.body.classList.remove(bodyClassName); }; }, [bodyClassName]); @@ -82,7 +82,7 @@ export function Layout({ 'Layout--folded': folded, 'Layout--offScreen': offScreen, [`Layout--${size}`]: size, - 'Layout--noFooter': !footer, + 'Layout--noFooter': !footer })} > {header ?
{header}
: null} @@ -111,7 +111,7 @@ Layout.defaultProps = { asideClassName: '', headerFixed: true, offScreen: false, - footer: false, + footer: false }; -export default themeable(Layout); \ No newline at end of file +export default themeable(Layout); diff --git a/src/components/LazyComponent.tsx b/src/components/LazyComponent.tsx index c640526f8..8f65d2a8a 100644 --- a/src/components/LazyComponent.tsx +++ b/src/components/LazyComponent.tsx @@ -26,10 +26,10 @@ export default class LazyComponent extends React.Component - this.mounted && typeof component === 'function' && this.setState({ - component: component, - }) + .then( + component => + this.mounted && + typeof component === 'function' && + this.setState({ + component: component + }) ) - .catch(reason => - this.mounted && this.setState({ - component: () =>
{String(reason)}
, - }) + .catch( + reason => + this.mounted && + this.setState({ + component: () =>
{String(reason)}
+ }) ); } diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx index 2ababdb60..f419a8b22 100644 --- a/src/components/Modal.tsx +++ b/src/components/Modal.tsx @@ -30,13 +30,13 @@ const fadeStyles: { [propName: string]: string; } = { [ENTERING]: 'in', - [ENTERED]: 'in', + [ENTERED]: 'in' }; export class Modal extends React.Component { static defaultProps = { container: document.body, size: '', - overlay: true, + overlay: true }; contentDom: any; @@ -105,7 +105,7 @@ export class Modal extends React.Component { className={cx( `amis-dialog-widget ${ns}Modal`, { - [`${ns}Modal--${size}`]: size, + [`${ns}Modal--${size}`]: size }, className )} diff --git a/src/components/Overlay.tsx b/src/components/Overlay.tsx index 142293970..86068d37b 100644 --- a/src/components/Overlay.tsx +++ b/src/components/Overlay.tsx @@ -19,7 +19,7 @@ Position.prototype.updatePosition = function(target: any) { positionLeft: 0, positionTop: 0, arrowOffsetLeft: null, - arrowOffsetTop: null, + arrowOffsetTop: null }); } diff --git a/src/components/PopOver.tsx b/src/components/PopOver.tsx index e50521887..057b77134 100644 --- a/src/components/PopOver.tsx +++ b/src/components/PopOver.tsx @@ -7,7 +7,7 @@ import React from 'react'; import {findDOMNode} from 'react-dom'; import {ClassNamesFn, themeable} from '../theme'; -import { camel } from '../utils/helper'; +import {camel} from '../utils/helper'; export interface Offset { x: number; @@ -41,18 +41,18 @@ export class PopOver extends React.PureComponent { className: '', offset: { x: 0, - y: 0, + y: 0 }, overlay: false, - placement: 'bottom', + placement: 'bottom' }; state = { xOffset: 0, - yOffset: 0, + yOffset: 0 }; - parent:HTMLElement; + parent: HTMLElement; componentDidMount() { this.mayUpdateOffset(); @@ -79,14 +79,14 @@ export class PopOver extends React.PureComponent { offset = getOffset((findDOMNode(this) as HTMLElement).getBoundingClientRect(), { x, y, - placement, + placement }); } else { offset = getOffset as Offset; } this.setState({ - xOffset: (offset && offset.x) ? (offset as Offset).x : 0, - yOffset: (offset && offset.y) ? (offset as Offset).y : 0, + xOffset: offset && offset.x ? (offset as Offset).x : 0, + yOffset: offset && offset.y ? (offset as Offset).y : 0 }); } @@ -114,11 +114,15 @@ export class PopOver extends React.PureComponent { display: 'block', ...style, top: (positionTop as number) + yOffset, - left: (positionLeft as number) + xOffset, + left: (positionLeft as number) + xOffset }; return ( -
+
{overlay ?
: null} {children}
diff --git a/src/components/Radios.tsx b/src/components/Radios.tsx index 2326f35d8..a612fa979 100644 --- a/src/components/Radios.tsx +++ b/src/components/Radios.tsx @@ -39,24 +39,17 @@ export class Radios extends React.Component { static defaultProps = { joinValues: true, clearable: false, - columnsCount: 1, // 一行显示一个 + columnsCount: 1 // 一行显示一个 }; toggleOption(option: Option) { - const { - value, - onChange, - valueField, - clearable, - delimiter, - options - } = this.props; + const {value, onChange, valueField, clearable, delimiter, options} = this.props; let valueArray = value2array(value, { multiple: false, delimiter, valueField, - options, + options }); const idx = valueArray.indexOf(option); @@ -71,36 +64,26 @@ export class Radios extends React.Component { onChange && onChange(newValue); } - renderGroup(option:Option, index:number, valueArray: Array
- +
+ - { - option.children && option.children.length - ? option.children.map((option, index) => this.renderItem(option, index, valueArray)) - : null - } + {option.children && option.children.length + ? option.children.map((option, index) => this.renderItem(option, index, valueArray)) + : null}
); } - renderItem(option:Option, index:number, valueArray: Array
); diff --git a/src/components/Switch.tsx b/src/components/Switch.tsx index 35e62e434..8fd45f91e 100644 --- a/src/components/Switch.tsx +++ b/src/components/Switch.tsx @@ -13,13 +13,13 @@ const sizeMap = { md: 'i-switch-md', lg: 'i-switch-lg', middle: 'i-switch-md', - large: 'i-switch-lg', + large: 'i-switch-lg' }; const levelMap = { info: 'bg-info', primary: 'bg-primary', - danger: 'bg-danger', + danger: 'bg-danger' }; interface SwitchProps { @@ -42,7 +42,7 @@ interface SwitchProps { export class Switch extends React.PureComponent { static defaultProps = { trueValue: true, - falseValue: false, + falseValue: false }; constructor(props: SwitchProps) { diff --git a/src/components/Tabs.tsx b/src/components/Tabs.tsx index d32da8785..1f92e3a86 100644 --- a/src/components/Tabs.tsx +++ b/src/components/Tabs.tsx @@ -5,9 +5,9 @@ */ import React from 'react'; -import { Schema } from '../types'; +import {Schema} from '../types'; import Transition, {ENTERED, ENTERING} from 'react-transition-group/Transition'; -import { ClassNamesFn, themeable } from '../theme'; +import {ClassNamesFn, themeable} from '../theme'; const transitionStyles: { [propName: string]: string; @@ -28,7 +28,7 @@ export interface TabProps { mountOnEnter?: boolean; unmountOnExit?: boolean; toolbar?: React.ReactNode; -}; +} export interface TabsProps { mode?: '' | 'line' | 'card' | 'radio'; @@ -45,13 +45,13 @@ export interface TabsProps { } export class Tabs extends React.Component { - static defaultProps:Pick = { + static defaultProps: Pick = { mode: '', contentClassName: '' }; handleSelect(key: any) { - const { handleSelect } = this.props; + const {handleSelect} = this.props; handleSelect && handleSelect(key); } @@ -60,31 +60,29 @@ export class Tabs extends React.Component { return; } - const { classnames: cx, activeKey } = this.props; - const { eventKey, disabled, icon, title, toolbar } = child.props; + const {classnames: cx, activeKey} = this.props; + const {eventKey, disabled, icon, title, toolbar} = child.props; return (
  • disabled ? '' : this.handleSelect(eventKey)} + onClick={() => (disabled ? '' : this.handleSelect(eventKey))} > - {icon ? : null} {title} + + {icon ? : null} {title} + {React.isValidElement(toolbar) ? toolbar : null}
  • ); } - renderTab(child:any, index:number) { + renderTab(child: any, index: number) { if (!child) { return; } - const { activeKey, classnames} = this.props; + const {activeKey, classnames} = this.props; return React.cloneElement(child, { ...child.props, @@ -95,15 +93,7 @@ export class Tabs extends React.Component { } render() { - const { - classnames: cx, - contentClassName, - className, - mode: dMode, - tabsMode, - children, - additionBtns - } = this.props; + const {classnames: cx, contentClassName, className, mode: dMode, tabsMode, children, additionBtns} = this.props; if (!Array.isArray(children)) { return null; @@ -116,21 +106,17 @@ export class Tabs extends React.Component { className={cx( `Tabs`, { - [`Tabs--${mode}`]: mode, + [`Tabs--${mode}`]: mode }, className )} >
      - {children.map((tab, index) => ( - this.renderNav(tab, index) - ))} + {children.map((tab, index) => this.renderNav(tab, index))} {additionBtns}
    -
    +
    {children.map((child, index) => { return this.renderTab(child, index); })} @@ -163,27 +149,30 @@ export class Tab extends React.PureComponent { unmountOnExit={typeof reload === 'boolean' ? reload : unmountOnExit} timeout={500} > - {(status:string) => { + {(status: string) => { if (status === ENTERING) { this.contentDom.offsetWidth; } return (
    {children}
    - ) + ); }} - ) + ); } } -export default themeable(Tabs); \ No newline at end of file +export default themeable(Tabs); diff --git a/src/components/TitleBar.tsx b/src/components/TitleBar.tsx index e770a0ba1..5331b815b 100644 --- a/src/components/TitleBar.tsx +++ b/src/components/TitleBar.tsx @@ -26,7 +26,7 @@ export class TitleBar extends React.PureComponent { className: 'bg-light lter b-b', title: '标题', titleClassName: 'm-n font-thin h3', - right: false, + right: false }; render(): JSX.Element { diff --git a/src/components/Toast.tsx b/src/components/Toast.tsx index 266f7f2cb..75e2caadc 100644 --- a/src/components/Toast.tsx +++ b/src/components/Toast.tsx @@ -17,7 +17,7 @@ const fadeStyles: { [ENTERING]: 'in', [ENTERED]: '', [EXITING]: 'out', - [EXITED]: 'hidden', + [EXITED]: 'hidden' }; let toastRef: any = null; @@ -56,17 +56,17 @@ interface ToastComponentState { } export class ToastComponent extends React.Component { - static defaultProps:Pick = { + static defaultProps: Pick = { position: 'top-right', closeButton: false, timeOut: 5000, - extendedTimeOut: 3000, + extendedTimeOut: 3000 }; // 当前ToastComponent是否真正render了 hasRendered = false; state: ToastComponentState = { - items: [], + items: [] }; componentWillMount() { @@ -74,7 +74,7 @@ export class ToastComponent extends React.Component { classPrefix: '', position: 'top-right', allowHtml: true, - level: 'info', + level: 'info' }; state = { - visible: false, + visible: false }; content: React.RefObject; @@ -210,7 +210,7 @@ export class ToastMessage extends React.Component { componentDidMount() { this.setState({ - visible: true, + visible: true }); } @@ -230,7 +230,7 @@ export class ToastMessage extends React.Component { close() { clearTimeout(this.timer); this.setState({ - visible: false, + visible: false }); } @@ -277,5 +277,5 @@ export const toast = { success: (content: string, title?: string, conf?: any) => show(content, title, conf, 'success'), error: (content: string, title?: string, conf?: any) => show(content, title, conf, 'error'), info: (content: string, title?: string, conf?: any) => show(content, title, conf, 'info'), - warning: (content: string, title?: string, conf?: any) => show(content, title, conf, 'warning'), + warning: (content: string, title?: string, conf?: any) => show(content, title, conf, 'warning') }; diff --git a/src/components/Tooltip.tsx b/src/components/Tooltip.tsx index 7110f591a..95fd00978 100644 --- a/src/components/Tooltip.tsx +++ b/src/components/Tooltip.tsx @@ -23,7 +23,7 @@ interface TooltipProps extends React.HTMLProps { export class Tooltip extends React.Component { static defaultProps = { - className: '', + className: '' }; render() { diff --git a/src/components/TooltipWrapper.tsx b/src/components/TooltipWrapper.tsx index cef9e2cb9..8e85e5e05 100644 --- a/src/components/TooltipWrapper.tsx +++ b/src/components/TooltipWrapper.tsx @@ -36,14 +36,14 @@ interface TooltipWrapperState { show?: boolean; } -let waitToHide:Function|null = null; +let waitToHide: Function | null = null; export class TooltipWrapper extends React.Component { static defaultProps: Pick = { placement: 'top', trigger: ['hover', 'focus'], rootClose: false, - delay: 200, + delay: 200 }; target: HTMLElement; @@ -64,7 +64,7 @@ export class TooltipWrapper extends React.Component - , + ]; } } export default themeable( uncontrollable(TooltipWrapper, { - show: 'onVisibleChange', + show: 'onVisibleChange' }) ); diff --git a/src/components/Tree.tsx b/src/components/Tree.tsx index 1c638f92d..161d031e2 100644 --- a/src/components/Tree.tsx +++ b/src/components/Tree.tsx @@ -83,7 +83,7 @@ export class TreeSelector extends React.Component { const {joinValues, rootValue, onChange} = this.props; @@ -180,7 +180,7 @@ export class TreeSelector extends React.Component { const {joinValues, valueField, onChange} = this.props; @@ -257,7 +257,7 @@ export class TreeSelector extends React.Component { const {joinValues, extractValue, valueField, delimiter, onChange} = this.props; @@ -332,11 +332,9 @@ export class TreeSelector extends React.Component= maxLength) - || (minLength && selfChecked && this.state.value.length <= minLength) - ) + !nodeDisabled && + ((maxLength && !selfChecked && this.state.value.length >= maxLength) || + (minLength && selfChecked && this.state.value.length <= minLength)) ) { nodeDisabled = true; } @@ -369,7 +367,7 @@ export class TreeSelector extends React.Component @@ -377,7 +375,7 @@ export class TreeSelector extends React.Component this.toggleUnfolded(item)} className={cx('Tree-itemArrow', { - 'is-folded': !this.state.unfolded[item[valueField]], + 'is-folded': !this.state.unfolded[item[valueField]] })} /> ) : null} @@ -397,7 +395,7 @@ export class TreeSelector extends React.Component !nodeDisabled && @@ -410,7 +408,7 @@ export class TreeSelector extends React.Component {childrenItems} @@ -422,7 +420,7 @@ export class TreeSelector extends React.Component diff --git a/src/components/icons.tsx b/src/components/icons.tsx index 849b91f28..150ae7b47 100644 --- a/src/components/icons.tsx +++ b/src/components/icons.tsx @@ -26,39 +26,37 @@ import LeftArrowIcon from '../icons/left-arrow.svg'; // @ts-ignore import RightArrowIcon from '../icons/right-arrow.svg'; - // 兼容原来的用法,后续不直接试用。 // @ts-ignore -export const closeIcon = (); +export const closeIcon = ; // @ts-ignore -export const unDoIcon = (); +export const unDoIcon = ; // @ts-ignore -export const reDoIcon = (); +export const reDoIcon = ; // @ts-ignore -export const enterIcon = (); +export const enterIcon = ; // @ts-ignore -export const volumeIcon = (); +export const volumeIcon = ; // @ts-ignore -export const muteIcon = (); +export const muteIcon = ; // @ts-ignore -export const playIcon = (); +export const playIcon = ; // @ts-ignore -export const pauseIcon = (); +export const pauseIcon = ; // @ts-ignore -export const leftArrowIcon = (); +export const leftArrowIcon = ; // @ts-ignore -export const rightArrowIcon = (); +export const rightArrowIcon = ; -const iconFactory:{ - [propName:string]: React.ReactType<{}> +const iconFactory: { + [propName: string]: React.ReactType<{}>; } = {}; - -export function getIcon(key:string) { +export function getIcon(key: string) { return iconFactory[key]; } -export function registerIcon(key:string, component:React.ReactType<{}>) { +export function registerIcon(key: string, component: React.ReactType<{}>) { iconFactory[key] = component; } @@ -76,15 +74,11 @@ registerIcon('right-arrow', RightArrowIcon); export function Icon({ icon, ...rest -}:{ - icon: string +}: { + icon: string; } & React.ComponentProps) { const Component = getIcon(icon); - return Component ? ( - - ) : ( - 没有 icon {icon} - ); + return Component ? : 没有 icon {icon}; } export { @@ -98,4 +92,4 @@ export { PauseIcon, LeftArrowIcon, RightArrowIcon -} \ No newline at end of file +}; diff --git a/src/components/index.tsx b/src/components/index.tsx index 013060d5a..fb48077bf 100644 --- a/src/components/index.tsx +++ b/src/components/index.tsx @@ -75,5 +75,5 @@ export { toast, Tooltip, TooltipWrapper, - Tree, + Tree }; diff --git a/src/factory.tsx b/src/factory.tsx index 8ea08651b..6484203ba 100644 --- a/src/factory.tsx +++ b/src/factory.tsx @@ -1,19 +1,9 @@ -import React from "react"; +import React from 'react'; import qs from 'qs'; -import { - RendererStore, - IRendererStore, - IIRendererStore -} from "./store/index"; -import { - getEnv -} from 'mobx-state-tree'; -import { - Location, parsePath -} from 'history'; -import { - wrapFetcher -} from './utils/api'; +import {RendererStore, IRendererStore, IIRendererStore} from './store/index'; +import {getEnv} from 'mobx-state-tree'; +import {Location, parsePath} from 'history'; +import {wrapFetcher} from './utils/api'; import { createObject, extendObject, @@ -39,20 +29,24 @@ import { PlainObject, RendererData } from './types'; -import { observer } from "mobx-react"; +import {observer} from 'mobx-react'; import getExprProperties from './utils/filter-schema'; import hoistNonReactStatic = require('hoist-non-react-statics'); import omit = require('lodash/omit'); import difference = require('lodash/difference'); import isPlainObject = require('lodash/isPlainObject'); import Scoped from './Scoped'; -import { getTheme, ThemeInstance, ClassNamesFn, ThemeContext } from "./theme"; -import find = require("lodash/find"); -import Alert from "./components/Alert2"; -import { LazyComponent } from './components'; +import {getTheme, ThemeInstance, ClassNamesFn, ThemeContext} from './theme'; +import find = require('lodash/find'); +import Alert from './components/Alert2'; +import {LazyComponent} from './components'; export interface TestFunc { - (path: string, schema?: Schema, resolveRenderer?: (path:string, schema?:Schema, props?:any) => null | RendererConfig): boolean; + ( + path: string, + schema?: Schema, + resolveRenderer?: (path: string, schema?: Schema, props?: any) => null | RendererConfig + ): boolean; } export interface RendererBasicConfig { @@ -67,47 +61,51 @@ export interface RendererBasicConfig { } export interface RendererEnv { - fetcher: (api:Api, data?:any, options?: object) => Promise; - isCancel: (val:any) => boolean; - notify: (type: "error" | "success", msg: string) => void; - jumpTo: (to:string, action?: Action, ctx?: object) => void; - alert: (msg:string) => void; - confirm: (msg:string, title?: string) => Promise; - updateLocation: (location:any, replace?:boolean) => void; - isCurrentUrl: (link:string) => boolean; - rendererResolver?: (path:string, schema:Schema, props:any) => null | RendererConfig; - copy?: (contents:string) => void; + fetcher: (api: Api, data?: any, options?: object) => Promise; + isCancel: (val: any) => boolean; + notify: (type: 'error' | 'success', msg: string) => void; + jumpTo: (to: string, action?: Action, ctx?: object) => void; + alert: (msg: string) => void; + confirm: (msg: string, title?: string) => Promise; + updateLocation: (location: any, replace?: boolean) => void; + isCurrentUrl: (link: string) => boolean; + rendererResolver?: (path: string, schema: Schema, props: any) => null | RendererConfig; + copy?: (contents: string) => void; getModalContainer?: () => HTMLElement; theme: ThemeInstance; affixOffsetTop: number; affixOffsetBottom: number; richTextToken: string; - loadRenderer: (schema:Schema, path:string, reRender:Function) => Promise | React.ReactType | JSX.Element | void; - [propName:string]: any; -}; + loadRenderer: ( + schema: Schema, + path: string, + reRender: Function + ) => Promise | React.ReactType | JSX.Element | void; + [propName: string]: any; +} export interface RendererProps { - render: (region: string, node:SchemaNode, props?:any) => JSX.Element; + render: (region: string, node: SchemaNode, props?: any) => JSX.Element; env: RendererEnv; classPrefix: string; classnames: ClassNamesFn; $path: string; // 当前组件所在的层级信息 store?: IIRendererStore; data: { - [propName:string]: any; + [propName: string]: any; }; defaultData?: object; className?: string; - [propName:string]: any; + [propName: string]: any; } export interface renderChildProps extends Partial { env: RendererEnv; -}; +} export type RendererComponent = React.ComponentType & { propsList?: Array; -} +}; export interface RendererConfig extends RendererBasicConfig { component: RendererComponent; @@ -115,72 +113,74 @@ export interface RendererConfig extends RendererBasicConfig { } export interface RenderSchemaFilter { - (schema:Schema, renderer: RendererConfig, props?:object): SchemaNode; -}; + (schema: Schema, renderer: RendererConfig, props?: object): SchemaNode; +} export interface RootRenderProps { location?: Location; theme?: string; - [propName:string]: any; -}; - + [propName: string]: any; +} export interface RenderOptions { - session?: string, - fetcher?: (config: fetcherConfig) => Promise, - isCancel?: (value:any) => boolean; - notify?: (type: "error" | "success", msg: string) => void, - jumpTo?: (to:string) => void, - alert?: (msg:string) => void, - confirm?: (msg:string, title?: string) => boolean | Promise; - rendererResolver?: (path:string, schema:Schema, props:any) => null | RendererConfig; - copy?: (contents:string) => void; + session?: string; + fetcher?: (config: fetcherConfig) => Promise; + isCancel?: (value: any) => boolean; + notify?: (type: 'error' | 'success', msg: string) => void; + jumpTo?: (to: string) => void; + alert?: (msg: string) => void; + confirm?: (msg: string, title?: string) => boolean | Promise; + rendererResolver?: (path: string, schema: Schema, props: any) => null | RendererConfig; + copy?: (contents: string) => void; getModalContainer?: () => HTMLElement; - loadRenderer?: (schema:Schema, path: string, reRender:Function) => Promise | React.ReactType | JSX.Element | void; + loadRenderer?: ( + schema: Schema, + path: string, + reRender: Function + ) => Promise | React.ReactType | JSX.Element | void; affixOffsetTop?: number; affixOffsetBottom?: number; richTextToken?: string; - [propName: string]: any + [propName: string]: any; } -export interface fetcherConfig { +export interface fetcherConfig { url: string; method: 'get' | 'post' | 'put' | 'patch' | 'delete'; data?: any; config?: any; -}; +} export type ReactElement = React.ReactNode[] | JSX.Element | null | false; - -const renderers:Array = []; -const rendererNames:Array = []; -const schemaFilters:Array = []; +const renderers: Array = []; +const rendererNames: Array = []; +const schemaFilters: Array = []; let anonymousIndex = 1; -export function addSchemaFilter(fn:RenderSchemaFilter) { +export function addSchemaFilter(fn: RenderSchemaFilter) { schemaFilters.push(fn); } -export function filterSchema(schema:Schema, render:RendererConfig, props?:any) { +export function filterSchema(schema: Schema, render: RendererConfig, props?: any) { return schemaFilters.reduce((schema, filter) => filter(schema, render, props), schema) as Schema; } -export function Renderer(config:RendererBasicConfig) { - return function(component:T):T { +export function Renderer(config: RendererBasicConfig) { + return function(component: T): T { const renderer = registerRenderer({ ...config, component: component }); return renderer.component as T; - } + }; } -export function registerRenderer(config:RendererConfig):RendererConfig { +export function registerRenderer(config: RendererConfig): RendererConfig { if (!config.test) { - throw new TypeError("config.test is required"); + throw new TypeError('config.test is required'); } else if (!config.component) { - throw new TypeError("config.component is required"); + throw new TypeError('config.component is required'); } config.weight = config.weight || 0; @@ -208,45 +208,47 @@ export function registerRenderer(config:RendererConfig):RendererConfig { return config; } -export function unRegisterRenderer(config:RendererConfig | string) { - let idx = typeof config === 'string' ? findIndex(renderers, item => item.name === config) : renderers.indexOf(config); +export function unRegisterRenderer(config: RendererConfig | string) { + let idx = + typeof config === 'string' ? findIndex(renderers, item => item.name === config) : renderers.indexOf(config); ~idx && renderers.splice(idx, 1); // 清空渲染器定位缓存 cache = {}; } -export function renderChildren(prefix: string, node: SchemaNode, props:renderChildProps):ReactElement { +export function renderChildren(prefix: string, node: SchemaNode, props: renderChildProps): ReactElement { if (Array.isArray(node)) { - return node.map((node, index) => renderChild(`${prefix}/${index}`, node, { - ...props, - key: `${props.key ? `${props.key}-` : ''}${index}` - })); + return node.map((node, index) => + renderChild(`${prefix}/${index}`, node, { + ...props, + key: `${props.key ? `${props.key}-` : ''}${index}` + }) + ); } return renderChild(prefix, node, props); } -export function renderChild(prefix:string, node:SchemaNode, props:renderChildProps):ReactElement { +export function renderChild(prefix: string, node: SchemaNode, props: renderChildProps): ReactElement { if (Array.isArray(node)) { return renderChildren(prefix, node, props); } const typeofnode = typeof node; - let schema:Schema = typeofnode === 'string' || typeofnode === 'number' ? {type: 'tpl', tpl: String(node)} : node as Schema; + let schema: Schema = + typeofnode === 'string' || typeofnode === 'number' ? {type: 'tpl', tpl: String(node)} : (node as Schema); const detectData = schema.detectField === '&' ? props : props[schema.detectField || 'data']; const exprProps = detectData ? getExprProperties(schema, detectData) : null; if ( - exprProps - && ( - exprProps.hidden - || exprProps.visible === false - || schema.hidden - || schema.visible === false - || props.hidden - || props.visible === false - ) + exprProps && + (exprProps.hidden || + exprProps.visible === false || + schema.hidden || + schema.visible === false || + props.hidden || + props.visible === false) ) { return null; } @@ -256,10 +258,10 @@ export function renderChild(prefix:string, node:SchemaNode, props:renderChildPro {...props} {...exprProps} schema={schema} - $path={`${prefix ? `${prefix}/` : ''}${schema && schema.type || ''}`} + $path={`${prefix ? `${prefix}/` : ''}${(schema && schema.type) || ''}`} /> ); -}; +} export interface RootRendererProps { schema: SchemaNode; @@ -267,8 +269,8 @@ export interface RootRendererProps { env: RendererEnv; theme: string; pathPrefix?: string; - [propName:string]: any; -}; + [propName: string]: any; +} const RootStoreContext = React.createContext(undefined as any); @@ -276,9 +278,9 @@ export class RootRenderer extends React.Component { state = { error: null, errorInfo: null - } + }; - componentDidCatch(error:any, errorInfo:any) { + componentDidCatch(error: any, errorInfo: any) { this.setState({ error: error, errorInfo: errorInfo @@ -286,7 +288,7 @@ export class RootRenderer extends React.Component { } @autobind - resolveDefinitions(name:string) { + resolveDefinitions(name: string) { const definitions = (this.props.schema as Schema).definitions; if (!name || isEmpty(definitions)) { return {}; @@ -299,42 +301,48 @@ export class RootRenderer extends React.Component { if (errorInfo) { return errorRenderer(error, errorInfo); } - const { - schema, - rootStore, - env, - pathPrefix, - location, - data, - ...rest - } = this.props; + const {schema, rootStore, env, pathPrefix, location, data, ...rest} = this.props; const theme = env.theme; - const query = location && location.query - || location && location.search && qs.parse(location.search.substring(1)) - || window.location.search && qs.parse(window.location.search.substring(1)); + const query = + (location && location.query) || + (location && location.search && qs.parse(location.search.substring(1))) || + (window.location.search && qs.parse(window.location.search.substring(1))); - const finalData = query ? createObject({ - ...(data && data.__super ? data.__super: null), - ...query, - query - }, data) : data; + const finalData = query + ? createObject( + { + ...(data && data.__super ? data.__super : null), + ...query, + query + }, + data + ) + : data; return ( - {renderChild(pathPrefix || '', isPlainObject(schema) ? { - type: 'page', - ...(schema as Schema) - } : schema, { - ...rest, - resolveDefinitions: this.resolveDefinitions, - location: location, - data: finalData, - env, - classnames: theme.classnames, - classPrefix: theme.classPrefix - }) as JSX.Element} + { + renderChild( + pathPrefix || '', + isPlainObject(schema) + ? { + type: 'page', + ...(schema as Schema) + } + : schema, + { + ...rest, + resolveDefinitions: this.resolveDefinitions, + location: location, + data: finalData, + env, + classnames: theme.classnames, + classPrefix: theme.classPrefix + } + ) as JSX.Element + } ); @@ -347,22 +355,33 @@ interface SchemaRendererProps extends Partial { schema: Schema; $path: string; env: RendererEnv; -}; +} const defaultOmitList = [ - 'type', 'name', '$ref', 'className', 'data', 'children', - 'ref', 'visible', 'visibleOn', 'hidden', - 'hiddenOn', 'disabled', 'disabledOn', - 'children', 'detectField' + 'type', + 'name', + '$ref', + 'className', + 'data', + 'children', + 'ref', + 'visible', + 'visibleOn', + 'hidden', + 'hiddenOn', + 'disabled', + 'disabledOn', + 'children', + 'detectField' ]; class SchemaRenderer extends React.Component { - static displayName:string = 'Renderer'; + static displayName: string = 'Renderer'; - renderer:RendererConfig | null; + renderer: RendererConfig | null; ref: any; - constructor(props:SchemaRendererProps) { + constructor(props: SchemaRendererProps) { super(props); this.refFn = this.refFn.bind(this); this.renderChild = this.renderChild.bind(this); @@ -373,34 +392,28 @@ class SchemaRenderer extends React.Component { this.resolveRenderer(this.props); } - componentWillReceiveProps(nextProps:SchemaRendererProps) { + componentWillReceiveProps(nextProps: SchemaRendererProps) { const props = this.props; - if ( - props.schema.type !== nextProps.schema.type || - props.schema.$$id !== nextProps.schema.$$id - ) { + if (props.schema.type !== nextProps.schema.type || props.schema.$$id !== nextProps.schema.$$id) { this.resolveRenderer(nextProps); } } // 限制:只有 schema 除外的 props 变化,或者 schema 里面的某个成员值发生变化才更新。 - shouldComponentUpdate(nextProps:SchemaRendererProps) { + shouldComponentUpdate(nextProps: SchemaRendererProps) { const props = this.props; - const list:Array = difference(Object.keys(nextProps), ['schema']); + const list: Array = difference(Object.keys(nextProps), ['schema']); if ( - difference(Object.keys(props), ['schema']).length !== list.length - || anyChanged(list, this.props, nextProps) + difference(Object.keys(props), ['schema']).length !== list.length || + anyChanged(list, this.props, nextProps) ) { return true; } else { - const list:Array = Object.keys(nextProps.schema); + const list: Array = Object.keys(nextProps.schema); - if ( - Object.keys(props.schema).length !== list.length - || anyChanged(list, props.schema, nextProps.schema) - ) { + if (Object.keys(props.schema).length !== list.length || anyChanged(list, props.schema, nextProps.schema)) { return true; } } @@ -408,7 +421,7 @@ class SchemaRenderer extends React.Component { return false; } - resolveRenderer(props:SchemaRendererProps):any { + resolveRenderer(props: SchemaRendererProps): any { let schema = props.schema; let path = props.$path; const rendererResolver = props.env.rendererResolver || resolveRenderer; @@ -436,20 +449,19 @@ class SchemaRenderer extends React.Component { return this.ref; } - refFn(ref:any) { + refFn(ref: any) { this.ref = ref; } - renderChild(region: string, node?:SchemaNode, subProps: { - data?: object; - [propName: string]: any; - } = {}) { - let { - schema, - $path, - env, - ...rest - } = this.props; + renderChild( + region: string, + node?: SchemaNode, + subProps: { + data?: object; + [propName: string]: any; + } = {} + ) { + let {schema, $path, env, ...rest} = this.props; const omitList = defaultOmitList.concat(); if (this.renderer) { @@ -470,12 +482,8 @@ class SchemaRenderer extends React.Component { this.forceUpdate(); } - render():JSX.Element | null { - let { - $path, - schema, - ...rest - } = this.props; + render(): JSX.Element | null { + let {$path, schema, ...rest} = this.props; if (schema.$ref) { schema = this.resolveRenderer(this.props); @@ -486,25 +494,27 @@ class SchemaRenderer extends React.Component { if (Array.isArray(schema)) { return renderChildren($path, schema, rest) as JSX.Element; } else if (schema.children) { - return React.isValidElement(schema.children) ? schema.children : React.createElement(schema.children as any, { - ...rest, - $path: $path, - render: this.renderChild - }); + return React.isValidElement(schema.children) + ? schema.children + : React.createElement(schema.children as any, { + ...rest, + $path: $path, + render: this.renderChild + }); } else if (!this.renderer) { return ( { const result = await rest.env.loadRenderer(schema, $path, this.reRender); - if (result && typeof result === "function") { + if (result && typeof result === 'function') { return result; } else if (result && React.isValidElement(result)) { return () => result; } this.reRender(); - return () => loadRenderer(schema, $path) + return () => loadRenderer(schema, $path); }} $path={$path} retry={this.reRender} @@ -514,10 +524,7 @@ class SchemaRenderer extends React.Component { const renderer = this.renderer as RendererConfig; schema = filterSchema(schema, renderer, rest); - const { - data: defaultData, - ...restSchema - } = schema; + const {data: defaultData, ...restSchema} = schema; const Component = renderer.component; return ( @@ -534,13 +541,9 @@ class SchemaRenderer extends React.Component { } } -export function HocStoreFactory(renderer:{ - storeType: string; - extendsData?: boolean; -}):any { - return function >(Component:T) { - - type Props = Omit & { +export function HocStoreFactory(renderer: {storeType: string; extendsData?: boolean}): any { + return function>(Component: T) { + type Props = Omit & { store?: IIRendererStore; data?: RendererData; scope?: RendererData; @@ -551,23 +554,23 @@ export function HocStoreFactory(renderer:{ static displayName = `WithStore(${Component.displayName || Component.name})`; static ComposedComponent = Component; static contextType = RootStoreContext; - store:IIRendererStore; + store: IIRendererStore; context!: React.ContextType; - ref:any; + ref: any; getWrappedInstance() { return this.ref; } - refFn(ref:any) { + refFn(ref: any) { this.ref = ref; } - formatData(data:any):object { + formatData(data: any): object { if (Array.isArray(data)) { return { items: data - } + }; } return data as object; @@ -578,28 +581,34 @@ export function HocStoreFactory(renderer:{ this.renderChild = this.renderChild.bind(this); this.refFn = this.refFn.bind(this); - const store = this.store = rootStore.addStore({ + const store = (this.store = rootStore.addStore({ id: guid(), path: this.props.$path, storeType: renderer.storeType, parentId: this.props.store ? this.props.store.id : '' - }); + })); if (renderer.extendsData === false) { - store.initData(createObject((this.props.data as any) ? (this.props.data as any).__super : null, { - ...this.formatData(this.props.defaultData), - ...this.formatData(this.props.data) - })); - } else if (this.props.scope || this.props.data && (this.props.data as any).__super) { - if (this.props.store && this.props.data === this.props.store.data) { - store.initData(createObject(this.props.store.data, { - ...this.formatData(this.props.defaultData) - })) - } else { - store.initData(createObject((this.props.data as any).__super || this.props.scope, { + store.initData( + createObject((this.props.data as any) ? (this.props.data as any).__super : null, { ...this.formatData(this.props.defaultData), ...this.formatData(this.props.data) - })) + }) + ); + } else if (this.props.scope || (this.props.data && (this.props.data as any).__super)) { + if (this.props.store && this.props.data === this.props.store.data) { + store.initData( + createObject(this.props.store.data, { + ...this.formatData(this.props.defaultData) + }) + ); + } else { + store.initData( + createObject((this.props.data as any).__super || this.props.scope, { + ...this.formatData(this.props.defaultData), + ...this.formatData(this.props.data) + }) + ); } } else { store.initData({ @@ -609,26 +618,33 @@ export function HocStoreFactory(renderer:{ } } - componentWillReceiveProps(nextProps:RendererProps) { + componentWillReceiveProps(nextProps: RendererProps) { const props = this.props; const store = this.store; if (renderer.extendsData === false) { - ( - props.defaultData !== nextProps.defaultData - || isObjectShallowModified(props.data, nextProps.data) + (props.defaultData !== nextProps.defaultData || + isObjectShallowModified(props.data, nextProps.data) || // CRUD 中 toolbar 里面的 data 是空对象,但是 __super 会不一样 - || nextProps.data && props.data && nextProps.data.__super !== props.data.__super - ) - && store.initData(extendObject(nextProps.data, { - ...store.hasRemoteData ? store.data : null, // todo 只保留 remote 数据 - ...this.formatData(nextProps.defaultData), - ...this.formatData(nextProps.data) - })); + (nextProps.data && props.data && nextProps.data.__super !== props.data.__super)) && + store.initData( + extendObject(nextProps.data, { + ...(store.hasRemoteData ? store.data : null), // todo 只保留 remote 数据 + ...this.formatData(nextProps.defaultData), + ...this.formatData(nextProps.data) + }) + ); } else if (isObjectShallowModified(props.data, nextProps.data)) { if (nextProps.store && nextProps.store.data === nextProps.data) { - const newData = createObject(nextProps.store.data, syncDataFromSuper(store.data, - nextProps.store.data, props.scope, nextProps.dataUpdatedAt !== props.dataUpdatedAt)); + const newData = createObject( + nextProps.store.data, + syncDataFromSuper( + store.data, + nextProps.store.data, + props.scope, + nextProps.dataUpdatedAt !== props.dataUpdatedAt + ) + ); // todo fix: dialog 种数据从孩子 form 同步过来后,会走这个逻辑让 form 更新 data,会导致里面的 __prev 丢失。 store.initData(newData); @@ -637,18 +653,26 @@ export function HocStoreFactory(renderer:{ } else { store.initData(createObject(nextProps.scope, nextProps.data)); } - } else if ((!nextProps.store || nextProps.data !== nextProps.store.data) && nextProps.data && nextProps.data.__super) { + } else if ( + (!nextProps.store || nextProps.data !== nextProps.store.data) && + nextProps.data && + nextProps.data.__super + ) { // 这个用法很少,当 data.__super 值发生变化时,更新 store.data - (!props.data || isObjectShallowModified(nextProps.data.__super, props.data.__super, false)) - && store.initData(createObject(nextProps.data.__super, { + (!props.data || isObjectShallowModified(nextProps.data.__super, props.data.__super, false)) && + store.initData( + createObject(nextProps.data.__super, { + ...nextProps.data, + ...store.data + }) + ); + } else if (nextProps.scope !== props.scope) { + store.initData( + createObject(nextProps.scope, { ...nextProps.data, ...store.data - })); - } else if (nextProps.scope !== props.scope) { - store.initData(createObject(nextProps.scope, { - ...nextProps.data, - ...store.data - })); + }) + ); } } @@ -659,13 +683,15 @@ export function HocStoreFactory(renderer:{ delete this.store; } - renderChild(region: string, node:SchemaNode, subProps: { - data?: object; - [propName: string]: any; - } = {}) { - let { - render, - } = this.props; + renderChild( + region: string, + node: SchemaNode, + subProps: { + data?: object; + [propName: string]: any; + } = {} + ) { + let {render} = this.props; return render(region, node, { data: this.store.data, @@ -677,13 +703,10 @@ export function HocStoreFactory(renderer:{ } render() { - const { - detectField, - ...rest - } = this.props; + const {detectField, ...rest} = this.props; - let exprProps:any = {}; - if (!detectField || detectField === "data") { + let exprProps: any = {}; + if (!detectField || detectField === 'data') { exprProps = getExprProperties(rest, this.store.data); if (exprProps.hidden || exprProps.visible === false) { @@ -693,7 +716,9 @@ export function HocStoreFactory(renderer:{ return (

    Error: 找不到对应的渲染器

    Path: {path}

    -
    {JSON.stringify(schema, null, 2)}
    +
    +                {JSON.stringify(schema, null, 2)}
    +            
    ); } -function errorRenderer(error:any, errorInfo:any) { +function errorRenderer(error: any, errorInfo: any) { return (

    {error && error.toString()}

    -
    {errorInfo.componentStack}
    +
    +                {errorInfo.componentStack}
    +            
    - ) + ); } -const defaultOptions:RenderOptions = { +const defaultOptions: RenderOptions = { session: 'global', affixOffsetTop: 50, affixOffsetBottom: 0, @@ -741,46 +769,62 @@ const defaultOptions:RenderOptions = { return Promise.reject('fetcher is required'); }, isCancel() { - console.error('Please implements this. see https://baidu.github.io/amis/docs/getting-started#%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8'); + console.error( + 'Please implements this. see https://baidu.github.io/amis/docs/getting-started#%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8' + ); return false; }, - alert(msg:string) { + alert(msg: string) { alert(msg); }, updateLocation() { - console.error('Please implements this. see https://baidu.github.io/amis/docs/getting-started#%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8'); + console.error( + 'Please implements this. see https://baidu.github.io/amis/docs/getting-started#%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8' + ); }, - confirm(msg:string) { - return confirm(msg) + confirm(msg: string) { + return confirm(msg); }, notify(msg) { alert(msg); }, jumpTo() { - console.error('Please implements this. see https://baidu.github.io/amis/docs/getting-started#%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8'); + console.error( + 'Please implements this. see https://baidu.github.io/amis/docs/getting-started#%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8' + ); }, isCurrentUrl() { return false; }, - copy(contents:string) { - console.error('copy contents', contents) + copy(contents: string) { + console.error('copy contents', contents); }, rendererResolver: resolveRenderer }; -let stores:{ - [propName:string]: IRendererStore +let stores: { + [propName: string]: IRendererStore; } = {}; -export function render(schema:SchemaNode, props:RootRenderProps = {}, options:RenderOptions = {}, pathPrefix:string = ''):JSX.Element { +export function render( + schema: SchemaNode, + props: RootRenderProps = {}, + options: RenderOptions = {}, + pathPrefix: string = '' +): JSX.Element { options = { ...defaultOptions, ...options }; - let store = stores[options.session || 'global'] || (stores[options.session || 'global'] = RendererStore.create({}, { - ...options, - fetcher: options.fetcher ? wrapFetcher(options.fetcher) : defaultOptions.fetcher, - confirm: options.confirm ? promisify(options.confirm) : defaultOptions.confirm, - })); + let store = + stores[options.session || 'global'] || + (stores[options.session || 'global'] = RendererStore.create( + {}, + { + ...options, + fetcher: options.fetcher ? wrapFetcher(options.fetcher) : defaultOptions.fetcher, + confirm: options.confirm ? promisify(options.confirm) : defaultOptions.confirm + } + )); (window as any).amisStore = store; // 为了方便 debug. const env = getEnv(store); @@ -799,7 +843,7 @@ export function render(schema:SchemaNode, props:RootRenderProps = {}, options:Re ); } -export function clearStoresCache(sessions?:Array) { +export function clearStoresCache(sessions?: Array) { if (Array.isArray(sessions) && sessions.length) { sessions.forEach(key => delete stores[key]); } else { @@ -807,20 +851,20 @@ export function clearStoresCache(sessions?:Array) { } } -let cache:{[propName: string]: RendererConfig} = {}; -export function resolveRenderer(path:string, schema?:Schema, props?:any): null | RendererConfig { +let cache: {[propName: string]: RendererConfig} = {}; +export function resolveRenderer(path: string, schema?: Schema, props?: any): null | RendererConfig { if (cache[path]) { return cache[path]; } else if (path && path.length > 1024) { throw new Error('Path太长是不是死循环了?'); } - let renderer:null | RendererConfig = null; + let renderer: null | RendererConfig = null; renderers.some(item => { let matched = false; - if (typeof item.test === "function") { + if (typeof item.test === 'function') { matched = item.test(path, schema, resolveRenderer); } else if (item.test instanceof RegExp) { matched = item.test.test(path); @@ -834,22 +878,22 @@ export function resolveRenderer(path:string, schema?:Schema, props?:any): null | }); // 只能缓存纯正则表达式的后者方法中没有用到第二个参数的,因为自定义 test 函数的有可能依赖 schema 的结果 - if (renderer !== null && - ( - (renderer as RendererConfig).test instanceof RegExp - || typeof (renderer as RendererConfig).test === 'function' && ((renderer as RendererConfig).test as Function).length < 2 - )) { + if ( + renderer !== null && + ((renderer as RendererConfig).test instanceof RegExp || + (typeof (renderer as RendererConfig).test === 'function' && + ((renderer as RendererConfig).test as Function).length < 2)) + ) { cache[path] = renderer; } return renderer; } - export function getRenderers() { return renderers.concat(); } -export function getRendererByName(name:string) { +export function getRendererByName(name: string) { return find(renderers, item => item.name === name); } diff --git a/src/renderers/Action.tsx b/src/renderers/Action.tsx index f58141ca8..c2a814a76 100644 --- a/src/renderers/Action.tsx +++ b/src/renderers/Action.tsx @@ -54,7 +54,7 @@ export interface ActionProps { level?: 'info' | 'success' | 'warning' | 'danger' | 'link'; onAction?: (e: React.MouseEvent | void | null, action: object) => void; isCurrentUrl?: (link: string) => boolean; - onClick?: (e: React.MouseEvent, props:any) => void; + onClick?: (e: React.MouseEvent, props: any) => void; primary?: boolean; activeClassName: string; componentClass: React.ReactType; @@ -80,7 +80,7 @@ export class Action extends React.Component { type: 'button', componentClass: 'button', tooltipPlacement: 'bottom', - activeClassName: 'is-active', + activeClassName: 'is-active' }; dom: any; @@ -89,7 +89,7 @@ export class Action extends React.Component { handleAction(e: React.MouseEvent) { const {onAction, onClick, disabled} = this.props; - const result:any = onClick && onClick(e, this.props); + const result: any = onClick && onClick(e, this.props); if (disabled || e.isDefaultPrevented() || result === false || !onAction) { return; @@ -125,7 +125,7 @@ export class Action extends React.Component { active, activeLevel, tooltipContainer, - classnames: cx, + classnames: cx } = this.props; let isActive = !!active; @@ -138,7 +138,7 @@ export class Action extends React.Component {
    @@ -148,7 +148,7 @@ export class Action extends React.Component { ) : (
    ) : showCloseButton !== false && !store.loading ? ( @@ -419,8 +419,8 @@ export default class Dialog extends React.Component { {header ? render('header', header, { - data: store.formData, - }) + data: store.formData + }) : null} {!this.state.entered && lazyRender ? ( @@ -433,40 +433,40 @@ export default class Dialog extends React.Component { {body ? render( - 'drawer', - { - // 支持嵌套 - ...((store.action as Action) && ((store.action as Action).drawer as object)), - type: 'drawer', - }, - { - key: 'drawer', - data: store.drawerData, - onConfirm: this.handleDrawerConfirm, - onClose: this.handleDrawerClose, - show: store.drawerOpen, - onAction: this.handleAction, - } - ) + 'drawer', + { + // 支持嵌套 + ...((store.action as Action) && ((store.action as Action).drawer as object)), + type: 'drawer' + }, + { + key: 'drawer', + data: store.drawerData, + onConfirm: this.handleDrawerConfirm, + onClose: this.handleDrawerClose, + show: store.drawerOpen, + onAction: this.handleAction + } + ) : null} {body ? render( - 'dialog', - { - // 支持嵌套 - ...((store.action as Action) && ((store.action as Action).dialog as object)), - type: 'dialog', - }, - { - key: 'dialog', - data: store.dialogData, - onConfirm: this.handleDialogConfirm, - onClose: this.handleDialogClose, - show: store.dialogOpen, - onAction: this.handleAction, - } - ) + 'dialog', + { + // 支持嵌套 + ...((store.action as Action) && ((store.action as Action).dialog as object)), + type: 'dialog' + }, + { + key: 'dialog', + data: store.dialogData, + onConfirm: this.handleDialogConfirm, + onClose: this.handleDialogClose, + show: store.dialogOpen, + onAction: this.handleAction + } + ) : null} ); @@ -478,7 +478,7 @@ export default class Dialog extends React.Component { storeType: ModalStore.name, storeExtendsData: false, name: 'dialog', - isolateScope: true, + isolateScope: true }) export class DialogRenderer extends Dialog { static contextType = ScopedContext; @@ -504,7 +504,7 @@ export class DialogRenderer extends Dialog { const components = scoped.getComponents(); const targets: Array = []; - const { onConfirm, store } = this.props; + const {onConfirm, store} = this.props; if (action.target) { targets.push( @@ -532,7 +532,7 @@ export class DialogRenderer extends Dialog { target.doAction( { ...action, - from: this.$$id, + from: this.$$id }, ctx, true @@ -568,9 +568,9 @@ export class DialogRenderer extends Dialog { action: Action, data: object, throwErrors: boolean = false, - delegate?: boolean, + delegate?: boolean ) { - const { onAction, store, onConfirm, env } = this.props; + const {onAction, store, onConfirm, env} = this.props; if (action.from === this.$$id) { return onAction ? onAction(e, action, data, throwErrors, true) : false; @@ -587,7 +587,7 @@ export class DialogRenderer extends Dialog { this.tryChildrenToHandle( { ...action, - actionType: 'submit', + actionType: 'submit' }, data, action @@ -597,7 +597,7 @@ export class DialogRenderer extends Dialog { this.tryChildrenToHandle( { ...action, - actionType: 'submit', + actionType: 'submit' }, data, action @@ -616,8 +616,8 @@ export class DialogRenderer extends Dialog { } else if (action.actionType === 'ajax') { store .saveRemote(action.api as string, data, { - successMessage: (action.messages && action.messages.success) , - errorMessage: (action.messages && action.messages.failed), + successMessage: action.messages && action.messages.success, + errorMessage: action.messages && action.messages.failed }) .then(async () => { if (action.feedback && isVisible(action.feedback, store.data)) { diff --git a/src/renderers/Divider.tsx b/src/renderers/Divider.tsx index 8800c4c9b..b1303def0 100644 --- a/src/renderers/Divider.tsx +++ b/src/renderers/Divider.tsx @@ -5,27 +5,23 @@ import {filter} from '../utils/tpl'; import cx from 'classnames'; export interface DividerProps extends RendererProps { - lineStyle: 'dashed' | 'solid' + lineStyle: 'dashed' | 'solid'; } export default class Divider extends React.Component { - static defaultProps:Pick = { + static defaultProps: Pick = { className: '', lineStyle: 'dashed' }; render() { - const { - classnames: cx, - className, - lineStyle - } = this.props; + const {classnames: cx, className, lineStyle} = this.props; return
    ; } } @Renderer({ test: /(^|\/)(?:divider|hr)$/, - name: 'divider', + name: 'divider' }) export class DividerRenderer extends Divider {} diff --git a/src/renderers/Drawer.tsx b/src/renderers/Drawer.tsx index 1ed867075..f89860129 100644 --- a/src/renderers/Drawer.tsx +++ b/src/renderers/Drawer.tsx @@ -12,7 +12,7 @@ import {guid, chainFunctions, isVisible} from '../utils/helper'; import {reaction} from 'mobx'; import {findDOMNode} from 'react-dom'; import {IModalStore, ModalStore} from '../store/modal'; -import { filter } from '../utils/tpl'; +import {filter} from '../utils/tpl'; export interface DrawerProps extends RendererProps { title?: string; // 标题 @@ -58,14 +58,14 @@ export default class Drawer extends React.Component { position: 'right', resizable: false, overlay: true, - closeOnEsc: false, + closeOnEsc: false }; reaction: any; $$id: string = guid(); drawer: any; state = { - resizeCoord: 0, + resizeCoord: 0 }; constructor(props: DrawerProps) { super(props); @@ -116,7 +116,7 @@ export default class Drawer extends React.Component { ret.push({ type: 'button', actionType: 'close', - label: '取消', + label: '取消' }); if (confirm) { @@ -124,7 +124,7 @@ export default class Drawer extends React.Component { type: 'button', actionType: 'confirm', label: '确认', - primary: true, + primary: true }); } @@ -230,7 +230,7 @@ export default class Drawer extends React.Component { store.setFormData({ ...data, - ...response, + ...response }); } @@ -251,7 +251,7 @@ export default class Drawer extends React.Component { key, disabled: store.loading, onAction: this.handleAction, - onFinished: this.handleChildFinished, + onFinished: this.handleChildFinished }; if (schema.type === 'form') { @@ -259,7 +259,7 @@ export default class Drawer extends React.Component { mode: 'horizontal', wrapWithPanel: false, submitText: null, - ...schema, + ...schema }; // 同步数据到 Dialog 层,方便 actions 根据表单数据联动。 @@ -288,10 +288,10 @@ export default class Drawer extends React.Component { ? render( 'info', { - type: 'spinner', + type: 'spinner' }, { - key: 'info', + key: 'info' } ) : null} @@ -303,7 +303,7 @@ export default class Drawer extends React.Component { onAction: this.handleAction, data: store.formData, key, - disabled: action.disabled || store.loading, + disabled: action.disabled || store.loading }) )}
    @@ -348,7 +348,7 @@ export default class Drawer extends React.Component { e.clientY - resizeCtrl.offsetHeight - parseInt(drawerHeight.substring(0, drawerHeight.length - 2))) || - 0, + 0 }); document.body.addEventListener('mousemove', this.bindResize); @@ -388,7 +388,7 @@ export default class Drawer extends React.Component { store.setCurrentAction({ type: 'button', actionType: 'dialog', - dialog: dialog, + dialog: dialog }); store.openDialog(ctx, undefined, confirmed => { resolve(confirmed); @@ -415,7 +415,7 @@ export default class Drawer extends React.Component { overlay, closeOnOutside, classPrefix: ns, - classnames: cx, + classnames: cx } = this.props; const Container = wrapperComponent || DrawerContainer; @@ -439,13 +439,13 @@ export default class Drawer extends React.Component { {title ? (
    {render('title', title, { - data: store.formData, + data: store.formData })}
    ) : null} {header ? render('header', header, { - data: store.formData, + data: store.formData }) : null}
    @@ -459,7 +459,7 @@ export default class Drawer extends React.Component { 'dialog', { ...((store.action as Action) && ((store.action as Action).dialog as object)), - type: 'dialog', + type: 'dialog' }, { key: 'dialog', @@ -467,7 +467,7 @@ export default class Drawer extends React.Component { onConfirm: this.handleDialogConfirm, onClose: this.handleDialogClose, onAction: this.handleAction, - show: store.dialogOpen, + show: store.dialogOpen } ) : null} @@ -477,7 +477,7 @@ export default class Drawer extends React.Component { 'drawer', { ...((store.action as Action) && ((store.action as Action).drawer as object)), - type: 'drawer', + type: 'drawer' }, { key: 'drawer', @@ -485,7 +485,7 @@ export default class Drawer extends React.Component { onConfirm: this.handleDrawerConfirm, onClose: this.handleDrawerClose, onAction: this.handleAction, - show: store.drawerOpen, + show: store.drawerOpen } ) : null} @@ -501,7 +501,7 @@ export default class Drawer extends React.Component { storeType: ModalStore.name, storeExtendsData: false, name: 'drawer', - isolateScope: true, + isolateScope: true }) export class DrawerRenderer extends Drawer { static contextType = ScopedContext; @@ -555,7 +555,7 @@ export class DrawerRenderer extends Drawer { target.doAction( { ...action, - from: this.$$id, + from: this.$$id }, ctx, true @@ -617,8 +617,8 @@ export class DrawerRenderer extends Drawer { } else if (action.actionType === 'ajax') { store .saveRemote(action.api as string, data, { - successMessage: (action.messages && action.messages.success) , - errorMessage: (action.messages && action.messages.failed), + successMessage: action.messages && action.messages.success, + errorMessage: action.messages && action.messages.failed }) .then(async () => { if (action.feedback && isVisible(action.feedback, store.data)) { diff --git a/src/renderers/DropDownButton.tsx b/src/renderers/DropDownButton.tsx index ac1f931a2..2457e2f7c 100644 --- a/src/renderers/DropDownButton.tsx +++ b/src/renderers/DropDownButton.tsx @@ -24,11 +24,11 @@ export interface DropDownButtonState { export default class DropDownButton extends React.Component { state: DropDownButtonState = { - isOpened: this.props.defaultIsOpened || false, + isOpened: this.props.defaultIsOpened || false }; static defaultProps = { - caretIcon: 'fa fa-angle-down', + caretIcon: 'fa fa-angle-down' }; target: any; @@ -49,38 +49,41 @@ export default class DropDownButton extends React.Component +
      {children ? children @@ -97,7 +100,7 @@ export default class DropDownButton extends React.Component ); @@ -146,7 +149,7 @@ export default class DropDownButton extends React.Component @@ -168,12 +171,12 @@ export default class DropDownButton extends React.Component - {icon ? () : null} + {icon ? : null} {typeof label === 'string' ? filter(label, data) : label} @@ -186,6 +189,6 @@ export default class DropDownButton extends React.Component { static propsList: Array = ['name', 'items', 'value']; static defaultProps: Partial = { - className: '', + className: '' }; render() { @@ -23,7 +23,7 @@ export default class Each extends React.Component { ? isObject(value) ? Object.keys(value).map(key => ({ key: key, - value: value[key], + value: value[key] })) : Array.isArray(value) ? value @@ -36,7 +36,7 @@ export default class Each extends React.Component { ? arr.map((item: any, index: number) => render(`item/${index}`, items, { data: createObject(data, isObject(item) ? item : {[name]: item, item: item}), - key: index, + key: index }) ) : null} @@ -47,6 +47,6 @@ export default class Each extends React.Component { @Renderer({ test: /(^|\/)(?:repeat|each)$/, - name: 'each', + name: 'each' }) export class EachRenderer extends Each {} diff --git a/src/renderers/Form/Array.tsx b/src/renderers/Form/Array.tsx index 52d002a2a..ff2ae380b 100644 --- a/src/renderers/Form/Array.tsx +++ b/src/renderers/Form/Array.tsx @@ -1,14 +1,10 @@ import React from 'react'; -import { - FormItem, - FormControlProps -} from './Item'; -import { Schema } from '../../types'; +import {FormItem, FormControlProps} from './Item'; +import {Schema} from '../../types'; import {ComboStore, IComboStore} from '../../store/combo'; -import { observer } from "mobx-react"; +import {observer} from 'mobx-react'; import Combo from './Combo'; - export interface ArrayProps extends FormControlProps { placeholder?: string; controls: Array; @@ -19,37 +15,32 @@ export interface ArrayProps extends FormControlProps { unique?: boolean; }; store: IComboStore; -}; +} export default class ArrayControl extends React.Component { - comboInstance:any; - constructor(props:ArrayProps) { + comboInstance: any; + constructor(props: ArrayProps) { super(props); this.comboRef = this.comboRef.bind(this); } - comboRef(ref:any) { + comboRef(ref: any) { this.comboInstance = ref; } - validate(args:Array) { + validate(args: Array) { return this.comboInstance ? this.comboInstance.validate(...args) : null; } render() { - const { - items, - ...rest - } = this.props; + const {items, ...rest} = this.props; - return (); + return ; } } - @FormItem({ type: 'array', storeType: ComboStore.name }) -export class ArrayControlRenderer extends ArrayControl {}; - +export class ArrayControlRenderer extends ArrayControl {} diff --git a/src/renderers/Form/Button.tsx b/src/renderers/Form/Button.tsx index e874f28a1..ba6f888a3 100644 --- a/src/renderers/Form/Button.tsx +++ b/src/renderers/Form/Button.tsx @@ -1,25 +1,14 @@ import React from 'react'; -import { - FormItem, - FormControlProps -} from './Item'; +import {FormItem, FormControlProps} from './Item'; import cx from 'classnames'; import {Button} from '../../types'; -export interface ButtonProps extends FormControlProps, Button { - -}; +export interface ButtonProps extends FormControlProps, Button {} export class ButtonControl extends React.Component { - static defaultProps:Partial = { - } + static defaultProps: Partial = {}; render() { - const { - render, - type, - children, - ...rest - } = this.props; + const {render, type, children, ...rest} = this.props; return render('action', { ...rest, @@ -34,7 +23,7 @@ export class ButtonControl extends React.Component { strictMode: false, sizeMutable: false }) -export class ButtonControlRenderer extends ButtonControl {}; +export class ButtonControlRenderer extends ButtonControl {} @FormItem({ type: 'submit', @@ -42,12 +31,12 @@ export class ButtonControlRenderer extends ButtonControl {}; sizeMutable: false, strictMode: false }) -export class SubmitControlRenderer extends ButtonControl {}; +export class SubmitControlRenderer extends ButtonControl {} @FormItem({ type: 'reset', renderLabel: false, strictMode: false, - sizeMutable: false, + sizeMutable: false }) -export class ResetControlRenderer extends ButtonControl {}; +export class ResetControlRenderer extends ButtonControl {} diff --git a/src/renderers/Form/ButtonGroup.tsx b/src/renderers/Form/ButtonGroup.tsx index 4dbeb2fcb..3719f50d5 100644 --- a/src/renderers/Form/ButtonGroup.tsx +++ b/src/renderers/Form/ButtonGroup.tsx @@ -1,15 +1,9 @@ import React from 'react'; import cx from 'classnames'; -import { - OptionsControl, - OptionsControlProps, - Option -} from './Options'; -import { - Button -} from '../../types'; -import { getLevelFromClassName, autobind, isEmpty} from '../../utils/helper'; -import { dataMapping } from '../../utils/tpl-builtin'; +import {OptionsControl, OptionsControlProps, Option} from './Options'; +import {Button} from '../../types'; +import {getLevelFromClassName, autobind, isEmpty} from '../../utils/helper'; +import {dataMapping} from '../../utils/tpl-builtin'; export interface ButtonGroupProps extends OptionsControlProps { buttons?: Array
    ); } @@ -214,5 +212,4 @@ export default class ChainedSelectControl extends React.Component { - static defaultProps:Partial = { + static defaultProps: Partial = { trueValue: true, falseValue: false - } + }; render() { const { className, @@ -39,7 +36,7 @@ export default class CheckboxControl extends React.Component falseValue={falseValue} classPrefix={ns} disabled={disabled} - onChange={(value:any) => onChange(value)} + onChange={(value: any) => onChange(value)} > {option ? render('option', option) : null} @@ -52,5 +49,4 @@ export default class CheckboxControl extends React.Component type: 'checkbox', sizeMutable: false }) -export class CheckboxControlRenderer extends CheckboxControl {}; - +export class CheckboxControlRenderer extends CheckboxControl {} diff --git a/src/renderers/Form/Checkboxes.tsx b/src/renderers/Form/Checkboxes.tsx index 2a367119e..1a3461909 100644 --- a/src/renderers/Form/Checkboxes.tsx +++ b/src/renderers/Form/Checkboxes.tsx @@ -1,9 +1,5 @@ import React from 'react'; -import { - OptionsControl, - OptionsControlProps, - Option -} from './Options'; +import {OptionsControl, OptionsControlProps, Option} from './Options'; import cx from 'classnames'; import Checkbox from '../../components/Checkbox'; import chunk = require('lodash/chunk'); @@ -13,20 +9,17 @@ export interface CheckboxesProps extends OptionsControlProps { disabled?: boolean; itemClassName?: string; columnsCount?: number; -}; +} export default class CheckboxesControl extends React.Component { - static defaultProps:Partial = { + static defaultProps: Partial = { columnsCount: 1, multiple: true, placeholder: '暂无选项' - } + }; componentDidMount() { - const { - defaultCheckAll, - onToggleAll - } = this.props; + const {defaultCheckAll, onToggleAll} = this.props; defaultCheckAll && onToggleAll(); } @@ -36,36 +29,26 @@ export default class CheckboxesControl extends React.Component - +
    + - { - option.children && option.children.length - ? option.children.map((option, index) => this.renderItem(option, index)) - : null - } + {option.children && option.children.length + ? option.children.map((option, index) => this.renderItem(option, index)) + : null}
    ); } - renderItem(option:Option, index:number) { + renderItem(option: Option, index: number) { if (option.children) { return this.renderGroup(option, index); } - const { - itemClassName, - onToggle, - selectedOptions, - disabled, - inline - } = this.props; + const {itemClassName, onToggle, selectedOptions, disabled, inline} = this.props; return ( = []; + let body: Array = []; if (options && options.length) { body = options.map((option, key) => this.renderItem(option, key)); @@ -120,12 +103,14 @@ export default class CheckboxesControl extends React.Component 1) { - let weight = 12/(columnsCount as number); + let weight = 12 / (columnsCount as number); let cellClassName = `Grid-col--sm${weight === Math.round(weight) ? weight : ''}`; body = chunk(body, columnsCount).map((group, groupIndex) => (
    {Array.from({length: columnsCount as number}).map((_, index) => ( -
    {group[index]}
    +
    + {group[index]} +
    ))}
    )); @@ -133,9 +118,7 @@ export default class CheckboxesControl extends React.Component - {body && body.length ? body : ( - {placeholder} - )} + {body && body.length ? body : {placeholder}}
    ); } @@ -145,5 +128,4 @@ export default class CheckboxesControl extends React.Component void; + value: any; + onChange: (value: any) => void; extractValue: boolean; joinValues?: boolean; delimiter: string; @@ -27,7 +19,7 @@ export interface CityPickerProps { allowCity: boolean; allowDistrict: boolean; // allowStreet: boolean; -}; +} export interface CityPickerState { code: number; @@ -38,7 +30,7 @@ export interface CityPickerState { district: string; districtCode: number; street: string; -}; +} export class CityPicker extends React.Component { static defaultProps = { @@ -46,7 +38,7 @@ export class CityPicker extends React.Component = {}) { - this.setState({ - ...otherStates as any, - district: option.label as string, - districtCode: option.value as number, - street: '', - code: option.value as number - }, this.syncOut); + handleDistrictChange(option: Option, otherStates: Partial = {}) { + this.setState( + { + ...(otherStates as any), + district: option.label as string, + districtCode: option.value as number, + street: '', + code: option.value as number + }, + this.syncOut + ); } @autobind - handleStreetChange(e:React.ChangeEvent) { + handleStreetChange(e: React.ChangeEvent) { this.setState({ street: e.currentTarget.value }); @@ -131,10 +131,7 @@ export class CityPicker extends React.Component @@ -294,28 +287,26 @@ export class CityPicker extends React.Component { - render() { const { - value, + value, onChange, allowCity, allowDistrict, extractValue, - joinValues, + joinValues // allowStreet } = this.props; return ( - { type: 'city', sizeMutable: false }) -export class CheckboxControlRenderer extends LocationControl {}; - +export class CheckboxControlRenderer extends LocationControl {} diff --git a/src/renderers/Form/CityDB.ts b/src/renderers/Form/CityDB.ts index 41e72b5b0..def8df86b 100644 --- a/src/renderers/Form/CityDB.ts +++ b/src/renderers/Form/CityDB.ts @@ -1,3552 +1,3554 @@ // 数据来源:https://lbs.amap.com/api/webservice/download -const db:{ - [propName:string]: any; +const db: { + [propName: string]: any; } = { - 110000: "北京市", - 110100: "北京市市辖区", - 110101: "东城区", - 110102: "西城区", - 110105: "朝阳区", - 110106: "丰台区", - 110107: "石景山区", - 110108: "海淀区", - 110109: "门头沟区", - 110111: "房山区", - 110112: "通州区", - 110113: "顺义区", - 110114: "昌平区", - 110115: "大兴区", - 110116: "怀柔区", - 110117: "平谷区", - 110118: "密云区", - 110119: "延庆区", - 120000: "天津市", - 120100: "天津市市辖区", - 120101: "和平区", - 120102: "河东区", - 120103: "河西区", - 120104: "南开区", - 120105: "河北区", - 120106: "红桥区", - 120110: "东丽区", - 120111: "西青区", - 120112: "津南区", - 120113: "北辰区", - 120114: "武清区", - 120115: "宝坻区", - 120116: "滨海新区", - 120117: "宁河区", - 120118: "静海区", - 120119: "蓟州区", - 130000: "河北省", - 130100: "石家庄市", - 130101: "石家庄市市辖区", - 130102: "长安区", - 130104: "桥西区", - 130105: "新华区", - 130107: "井陉矿区", - 130108: "裕华区", - 130109: "藁城区", - 130110: "鹿泉区", - 130111: "栾城区", - 130121: "井陉县", - 130123: "正定县", - 130125: "行唐县", - 130126: "灵寿县", - 130127: "高邑县", - 130128: "深泽县", - 130129: "赞皇县", - 130130: "无极县", - 130131: "平山县", - 130132: "元氏县", - 130133: "赵县", - 130181: "辛集市", - 130183: "晋州市", - 130184: "新乐市", - 130200: "唐山市", - 130201: "唐山市市辖区", - 130202: "路南区", - 130203: "路北区", - 130204: "古冶区", - 130205: "开平区", - 130207: "丰南区", - 130208: "丰润区", - 130209: "曹妃甸区", - 130224: "滦南县", - 130225: "乐亭县", - 130227: "迁西县", - 130229: "玉田县", - 130281: "遵化市", - 130283: "迁安市", - 130284: "滦州市", - 130300: "秦皇岛市", - 130301: "秦皇岛市市辖区", - 130302: "海港区", - 130303: "山海关区", - 130304: "北戴河区", - 130306: "抚宁区", - 130321: "青龙满族自治县", - 130322: "昌黎县", - 130324: "卢龙县", - 130400: "邯郸市", - 130401: "邯郸市市辖区", - 130402: "邯山区", - 130403: "丛台区", - 130404: "复兴区", - 130406: "峰峰矿区", - 130407: "肥乡区", - 130408: "永年区", - 130423: "临漳县", - 130424: "成安县", - 130425: "大名县", - 130426: "涉县", - 130427: "磁县", - 130430: "邱县", - 130431: "鸡泽县", - 130432: "广平县", - 130433: "馆陶县", - 130434: "魏县", - 130435: "曲周县", - 130481: "武安市", - 130500: "邢台市", - 130501: "邢台市市辖区", - 130502: "桥东区", - 130503: "桥西区", - 130521: "邢台县", - 130522: "临城县", - 130523: "内丘县", - 130524: "柏乡县", - 130525: "隆尧县", - 130526: "任县", - 130527: "南和县", - 130528: "宁晋县", - 130529: "巨鹿县", - 130530: "新河县", - 130531: "广宗县", - 130532: "平乡县", - 130533: "威县", - 130534: "清河县", - 130535: "临西县", - 130581: "南宫市", - 130582: "沙河市", - 130600: "保定市", - 130601: "保定市市辖区", - 130602: "竞秀区", - 130606: "莲池区", - 130607: "满城区", - 130608: "清苑区", - 130609: "徐水区", - 130623: "涞水县", - 130624: "阜平县", - 130626: "定兴县", - 130627: "唐县", - 130628: "高阳县", - 130629: "容城县", - 130630: "涞源县", - 130631: "望都县", - 130632: "安新县", - 130633: "易县", - 130634: "曲阳县", - 130635: "蠡县", - 130636: "顺平县", - 130637: "博野县", - 130638: "雄县", - 130681: "涿州市", - 130682: "定州市", - 130683: "安国市", - 130684: "高碑店市", - 130700: "张家口市", - 130701: "张家口市市辖区", - 130702: "桥东区", - 130703: "桥西区", - 130705: "宣化区", - 130706: "下花园区", - 130708: "万全区", - 130709: "崇礼区", - 130722: "张北县", - 130723: "康保县", - 130724: "沽源县", - 130725: "尚义县", - 130726: "蔚县", - 130727: "阳原县", - 130728: "怀安县", - 130730: "怀来县", - 130731: "涿鹿县", - 130732: "赤城县", - 130800: "承德市", - 130801: "承德市市辖区", - 130802: "双桥区", - 130803: "双滦区", - 130804: "鹰手营子矿区", - 130821: "承德县", - 130822: "兴隆县", - 130824: "滦平县", - 130825: "隆化县", - 130826: "丰宁满族自治县", - 130827: "宽城满族自治县", - 130828: "围场满族蒙古族自治县", - 130881: "平泉市", - 130900: "沧州市", - 130901: "沧州市市辖区", - 130902: "新华区", - 130903: "运河区", - 130921: "沧县", - 130922: "青县", - 130923: "东光县", - 130924: "海兴县", - 130925: "盐山县", - 130926: "肃宁县", - 130927: "南皮县", - 130928: "吴桥县", - 130929: "献县", - 130930: "孟村回族自治县", - 130981: "泊头市", - 130982: "任丘市", - 130983: "黄骅市", - 130984: "河间市", - 131000: "廊坊市", - 131001: "廊坊市市辖区", - 131002: "安次区", - 131003: "广阳区", - 131022: "固安县", - 131023: "永清县", - 131024: "香河县", - 131025: "大城县", - 131026: "文安县", - 131028: "大厂回族自治县", - 131081: "霸州市", - 131082: "三河市", - 131100: "衡水市", - 131101: "衡水市市辖区", - 131102: "桃城区", - 131103: "冀州区", - 131121: "枣强县", - 131122: "武邑县", - 131123: "武强县", - 131124: "饶阳县", - 131125: "安平县", - 131126: "故城县", - 131127: "景县", - 131128: "阜城县", - 131182: "深州市", - 140000: "山西省", - 140100: "太原市", - 140101: "太原市市辖区", - 140105: "小店区", - 140106: "迎泽区", - 140107: "杏花岭区", - 140108: "尖草坪区", - 140109: "万柏林区", - 140110: "晋源区", - 140121: "清徐县", - 140122: "阳曲县", - 140123: "娄烦县", - 140181: "古交市", - 140200: "大同市", - 140201: "大同市市辖区", - 140212: "新荣区", - 140213: "平城区", - 140214: "云冈区", - 140215: "云州区", - 140221: "阳高县", - 140222: "天镇县", - 140223: "广灵县", - 140224: "灵丘县", - 140225: "浑源县", - 140226: "左云县", - 140300: "阳泉市", - 140301: "阳泉市市辖区", - 140302: "城区", - 140303: "矿区", - 140311: "郊区", - 140321: "平定县", - 140322: "盂县", - 140400: "长治市", - 140401: "长治市市辖区", - 140403: "潞州区", - 140404: "上党区", - 140405: "屯留区", - 140406: "潞城区", - 140423: "襄垣县", - 140425: "平顺县", - 140426: "黎城县", - 140427: "壶关县", - 140428: "长子县", - 140429: "武乡县", - 140430: "沁县", - 140431: "沁源县", - 140500: "晋城市", - 140501: "晋城市市辖区", - 140502: "城区", - 140521: "沁水县", - 140522: "阳城县", - 140524: "陵川县", - 140525: "泽州县", - 140581: "高平市", - 140600: "朔州市", - 140601: "朔州市市辖区", - 140602: "朔城区", - 140603: "平鲁区", - 140621: "山阴县", - 140622: "应县", - 140623: "右玉县", - 140681: "怀仁市", - 140700: "晋中市", - 140701: "晋中市市辖区", - 140702: "榆次区", - 140721: "榆社县", - 140722: "左权县", - 140723: "和顺县", - 140724: "昔阳县", - 140725: "寿阳县", - 140726: "太谷县", - 140727: "祁县", - 140728: "平遥县", - 140729: "灵石县", - 140781: "介休市", - 140800: "运城市", - 140801: "运城市市辖区", - 140802: "盐湖区", - 140821: "临猗县", - 140822: "万荣县", - 140823: "闻喜县", - 140824: "稷山县", - 140825: "新绛县", - 140826: "绛县", - 140827: "垣曲县", - 140828: "夏县", - 140829: "平陆县", - 140830: "芮城县", - 140881: "永济市", - 140882: "河津市", - 140900: "忻州市", - 140901: "忻州市市辖区", - 140902: "忻府区", - 140921: "定襄县", - 140922: "五台县", - 140923: "代县", - 140924: "繁峙县", - 140925: "宁武县", - 140926: "静乐县", - 140927: "神池县", - 140928: "五寨县", - 140929: "岢岚县", - 140930: "河曲县", - 140931: "保德县", - 140932: "偏关县", - 140981: "原平市", - 141000: "临汾市", - 141001: "临汾市市辖区", - 141002: "尧都区", - 141021: "曲沃县", - 141022: "翼城县", - 141023: "襄汾县", - 141024: "洪洞县", - 141025: "古县", - 141026: "安泽县", - 141027: "浮山县", - 141028: "吉县", - 141029: "乡宁县", - 141030: "大宁县", - 141031: "隰县", - 141032: "永和县", - 141033: "蒲县", - 141034: "汾西县", - 141081: "侯马市", - 141082: "霍州市", - 141100: "吕梁市", - 141101: "吕梁市市辖区", - 141102: "离石区", - 141121: "文水县", - 141122: "交城县", - 141123: "兴县", - 141124: "临县", - 141125: "柳林县", - 141126: "石楼县", - 141127: "岚县", - 141128: "方山县", - 141129: "中阳县", - 141130: "交口县", - 141181: "孝义市", - 141182: "汾阳市", - 150000: "内蒙古自治区", - 150100: "呼和浩特市", - 150101: "呼和浩特市市辖区", - 150102: "新城区", - 150103: "回民区", - 150104: "玉泉区", - 150105: "赛罕区", - 150121: "土默特左旗", - 150122: "托克托县", - 150123: "和林格尔县", - 150124: "清水河县", - 150125: "武川县", - 150200: "包头市", - 150201: "包头市市辖区", - 150202: "东河区", - 150203: "昆都仑区", - 150204: "青山区", - 150205: "石拐区", - 150206: "白云鄂博矿区", - 150207: "九原区", - 150221: "土默特右旗", - 150222: "固阳县", - 150223: "达尔罕茂明安联合旗", - 150300: "乌海市", - 150301: "乌海市市辖区", - 150302: "海勃湾区", - 150303: "海南区", - 150304: "乌达区", - 150400: "赤峰市", - 150401: "赤峰市市辖区", - 150402: "红山区", - 150403: "元宝山区", - 150404: "松山区", - 150421: "阿鲁科尔沁旗", - 150422: "巴林左旗", - 150423: "巴林右旗", - 150424: "林西县", - 150425: "克什克腾旗", - 150426: "翁牛特旗", - 150428: "喀喇沁旗", - 150429: "宁城县", - 150430: "敖汉旗", - 150500: "通辽市", - 150501: "通辽市市辖区", - 150502: "科尔沁区", - 150521: "科尔沁左翼中旗", - 150522: "科尔沁左翼后旗", - 150523: "开鲁县", - 150524: "库伦旗", - 150525: "奈曼旗", - 150526: "扎鲁特旗", - 150581: "霍林郭勒市", - 150600: "鄂尔多斯市", - 150601: "鄂尔多斯市市辖区", - 150602: "东胜区", - 150603: "康巴什区", - 150621: "达拉特旗", - 150622: "准格尔旗", - 150623: "鄂托克前旗", - 150624: "鄂托克旗", - 150625: "杭锦旗", - 150626: "乌审旗", - 150627: "伊金霍洛旗", - 150700: "呼伦贝尔市", - 150701: "呼伦贝尔市市辖区", - 150702: "海拉尔区", - 150703: "扎赉诺尔区", - 150721: "阿荣旗", - 150722: "莫力达瓦达斡尔族自治旗", - 150723: "鄂伦春自治旗", - 150724: "鄂温克族自治旗", - 150725: "陈巴尔虎旗", - 150726: "新巴尔虎左旗", - 150727: "新巴尔虎右旗", - 150781: "满洲里市", - 150782: "牙克石市", - 150783: "扎兰屯市", - 150784: "额尔古纳市", - 150785: "根河市", - 150800: "巴彦淖尔市", - 150801: "巴彦淖尔市市辖区", - 150802: "临河区", - 150821: "五原县", - 150822: "磴口县", - 150823: "乌拉特前旗", - 150824: "乌拉特中旗", - 150825: "乌拉特后旗", - 150826: "杭锦后旗", - 150900: "乌兰察布市", - 150901: "乌兰察布市市辖区", - 150902: "集宁区", - 150921: "卓资县", - 150922: "化德县", - 150923: "商都县", - 150924: "兴和县", - 150925: "凉城县", - 150926: "察哈尔右翼前旗", - 150927: "察哈尔右翼中旗", - 150928: "察哈尔右翼后旗", - 150929: "四子王旗", - 150981: "丰镇市", - 152200: "兴安盟", - 152201: "乌兰浩特市", - 152202: "阿尔山市", - 152221: "科尔沁右翼前旗", - 152222: "科尔沁右翼中旗", - 152223: "扎赉特旗", - 152224: "突泉县", - 152500: "锡林郭勒盟", - 152501: "二连浩特市", - 152502: "锡林浩特市", - 152522: "阿巴嘎旗", - 152523: "苏尼特左旗", - 152524: "苏尼特右旗", - 152525: "东乌珠穆沁旗", - 152526: "西乌珠穆沁旗", - 152527: "太仆寺旗", - 152528: "镶黄旗", - 152529: "正镶白旗", - 152530: "正蓝旗", - 152531: "多伦县", - 152900: "阿拉善盟", - 152921: "阿拉善左旗", - 152922: "阿拉善右旗", - 152923: "额济纳旗", - 210000: "辽宁省", - 210100: "沈阳市", - 210101: "沈阳市市辖区", - 210102: "和平区", - 210103: "沈河区", - 210104: "大东区", - 210105: "皇姑区", - 210106: "铁西区", - 210111: "苏家屯区", - 210112: "浑南区", - 210113: "沈北新区", - 210114: "于洪区", - 210115: "辽中区", - 210123: "康平县", - 210124: "法库县", - 210181: "新民市", - 210200: "大连市", - 210201: "大连市市辖区", - 210202: "中山区", - 210203: "西岗区", - 210204: "沙河口区", - 210211: "甘井子区", - 210212: "旅顺口区", - 210213: "金州区", - 210214: "普兰店区", - 210224: "长海县", - 210281: "瓦房店市", - 210283: "庄河市", - 210300: "鞍山市", - 210301: "鞍山市市辖区", - 210302: "铁东区", - 210303: "铁西区", - 210304: "立山区", - 210311: "千山区", - 210321: "台安县", - 210323: "岫岩满族自治县", - 210381: "海城市", - 210400: "抚顺市", - 210401: "抚顺市市辖区", - 210402: "新抚区", - 210403: "东洲区", - 210404: "望花区", - 210411: "顺城区", - 210421: "抚顺县", - 210422: "新宾满族自治县", - 210423: "清原满族自治县", - 210500: "本溪市", - 210501: "本溪市市辖区", - 210502: "平山区", - 210503: "溪湖区", - 210504: "明山区", - 210505: "南芬区", - 210521: "本溪满族自治县", - 210522: "桓仁满族自治县", - 210600: "丹东市", - 210601: "丹东市市辖区", - 210602: "元宝区", - 210603: "振兴区", - 210604: "振安区", - 210624: "宽甸满族自治县", - 210681: "东港市", - 210682: "凤城市", - 210700: "锦州市", - 210701: "锦州市市辖区", - 210702: "古塔区", - 210703: "凌河区", - 210711: "太和区", - 210726: "黑山县", - 210727: "义县", - 210781: "凌海市", - 210782: "北镇市", - 210800: "营口市", - 210801: "营口市市辖区", - 210802: "站前区", - 210803: "西市区", - 210804: "鲅鱼圈区", - 210811: "老边区", - 210881: "盖州市", - 210882: "大石桥市", - 210900: "阜新市", - 210901: "阜新市市辖区", - 210902: "海州区", - 210903: "新邱区", - 210904: "太平区", - 210905: "清河门区", - 210911: "细河区", - 210921: "阜新蒙古族自治县", - 210922: "彰武县", - 211000: "辽阳市", - 211001: "辽阳市市辖区", - 211002: "白塔区", - 211003: "文圣区", - 211004: "宏伟区", - 211005: "弓长岭区", - 211011: "太子河区", - 211021: "辽阳县", - 211081: "灯塔市", - 211100: "盘锦市", - 211101: "盘锦市市辖区", - 211102: "双台子区", - 211103: "兴隆台区", - 211104: "大洼区", - 211122: "盘山县", - 211200: "铁岭市", - 211201: "铁岭市市辖区", - 211202: "银州区", - 211204: "清河区", - 211221: "铁岭县", - 211223: "西丰县", - 211224: "昌图县", - 211281: "调兵山市", - 211282: "开原市", - 211300: "朝阳市", - 211301: "朝阳市市辖区", - 211302: "双塔区", - 211303: "龙城区", - 211321: "朝阳县", - 211322: "建平县", - 211324: "喀喇沁左翼蒙古族自治县", - 211381: "北票市", - 211382: "凌源市", - 211400: "葫芦岛市", - 211401: "葫芦岛市市辖区", - 211402: "连山区", - 211403: "龙港区", - 211404: "南票区", - 211421: "绥中县", - 211422: "建昌县", - 211481: "兴城市", - 220000: "吉林省", - 220100: "长春市", - 220101: "长春市市辖区", - 220102: "南关区", - 220103: "宽城区", - 220104: "朝阳区", - 220105: "二道区", - 220106: "绿园区", - 220112: "双阳区", - 220113: "九台区", - 220122: "农安县", - 220182: "榆树市", - 220183: "德惠市", - 220200: "吉林市", - 220201: "吉林市市辖区", - 220202: "昌邑区", - 220203: "龙潭区", - 220204: "船营区", - 220211: "丰满区", - 220221: "永吉县", - 220281: "蛟河市", - 220282: "桦甸市", - 220283: "舒兰市", - 220284: "磐石市", - 220300: "四平市", - 220301: "四平市市辖区", - 220302: "铁西区", - 220303: "铁东区", - 220322: "梨树县", - 220323: "伊通满族自治县", - 220381: "公主岭市", - 220382: "双辽市", - 220400: "辽源市", - 220401: "辽源市市辖区", - 220402: "龙山区", - 220403: "西安区", - 220421: "东丰县", - 220422: "东辽县", - 220500: "通化市", - 220501: "通化市市辖区", - 220502: "东昌区", - 220503: "二道江区", - 220521: "通化县", - 220523: "辉南县", - 220524: "柳河县", - 220581: "梅河口市", - 220582: "集安市", - 220600: "白山市", - 220601: "白山市市辖区", - 220602: "浑江区", - 220605: "江源区", - 220621: "抚松县", - 220622: "靖宇县", - 220623: "长白朝鲜族自治县", - 220681: "临江市", - 220700: "松原市", - 220701: "松原市市辖区", - 220702: "宁江区", - 220721: "前郭尔罗斯蒙古族自治县", - 220722: "长岭县", - 220723: "乾安县", - 220781: "扶余市", - 220800: "白城市", - 220801: "白城市市辖区", - 220802: "洮北区", - 220821: "镇赉县", - 220822: "通榆县", - 220881: "洮南市", - 220882: "大安市", - 222400: "延边朝鲜族自治州", - 222401: "延吉市", - 222402: "图们市", - 222403: "敦化市", - 222404: "珲春市", - 222405: "龙井市", - 222406: "和龙市", - 222424: "汪清县", - 222426: "安图县", - 230000: "黑龙江省", - 230100: "哈尔滨市", - 230101: "哈尔滨市市辖区", - 230102: "道里区", - 230103: "南岗区", - 230104: "道外区", - 230108: "平房区", - 230109: "松北区", - 230110: "香坊区", - 230111: "呼兰区", - 230112: "阿城区", - 230113: "双城区", - 230123: "依兰县", - 230124: "方正县", - 230125: "宾县", - 230126: "巴彦县", - 230127: "木兰县", - 230128: "通河县", - 230129: "延寿县", - 230183: "尚志市", - 230184: "五常市", - 230200: "齐齐哈尔市", - 230201: "齐齐哈尔市市辖区", - 230202: "龙沙区", - 230203: "建华区", - 230204: "铁锋区", - 230205: "昂昂溪区", - 230206: "富拉尔基区", - 230207: "碾子山区", - 230208: "梅里斯达斡尔族区", - 230221: "龙江县", - 230223: "依安县", - 230224: "泰来县", - 230225: "甘南县", - 230227: "富裕县", - 230229: "克山县", - 230230: "克东县", - 230231: "拜泉县", - 230281: "讷河市", - 230300: "鸡西市", - 230301: "鸡西市市辖区", - 230302: "鸡冠区", - 230303: "恒山区", - 230304: "滴道区", - 230305: "梨树区", - 230306: "城子河区", - 230307: "麻山区", - 230321: "鸡东县", - 230381: "虎林市", - 230382: "密山市", - 230400: "鹤岗市", - 230401: "鹤岗市市辖区", - 230402: "向阳区", - 230403: "工农区", - 230404: "南山区", - 230405: "兴安区", - 230406: "东山区", - 230407: "兴山区", - 230421: "萝北县", - 230422: "绥滨县", - 230500: "双鸭山市", - 230501: "双鸭山市市辖区", - 230502: "尖山区", - 230503: "岭东区", - 230505: "四方台区", - 230506: "宝山区", - 230521: "集贤县", - 230522: "友谊县", - 230523: "宝清县", - 230524: "饶河县", - 230600: "大庆市", - 230601: "大庆市市辖区", - 230602: "萨尔图区", - 230603: "龙凤区", - 230604: "让胡路区", - 230605: "红岗区", - 230606: "大同区", - 230621: "肇州县", - 230622: "肇源县", - 230623: "林甸县", - 230624: "杜尔伯特蒙古族自治县", - 230700: "伊春市", - 230701: "伊春市市辖区", - 230702: "伊春区", - 230703: "南岔区", - 230704: "友好区", - 230705: "西林区", - 230706: "翠峦区", - 230707: "新青区", - 230708: "美溪区", - 230709: "金山屯区", - 230710: "五营区", - 230711: "乌马河区", - 230712: "汤旺河区", - 230713: "带岭区", - 230714: "乌伊岭区", - 230715: "红星区", - 230716: "上甘岭区", - 230722: "嘉荫县", - 230781: "铁力市", - 230800: "佳木斯市", - 230801: "佳木斯市市辖区", - 230803: "向阳区", - 230804: "前进区", - 230805: "东风区", - 230811: "郊区", - 230822: "桦南县", - 230826: "桦川县", - 230828: "汤原县", - 230881: "同江市", - 230882: "富锦市", - 230883: "抚远市", - 230900: "七台河市", - 230901: "七台河市市辖区", - 230902: "新兴区", - 230903: "桃山区", - 230904: "茄子河区", - 230921: "勃利县", - 231000: "牡丹江市", - 231001: "牡丹江市市辖区", - 231002: "东安区", - 231003: "阳明区", - 231004: "爱民区", - 231005: "西安区", - 231025: "林口县", - 231081: "绥芬河市", - 231083: "海林市", - 231084: "宁安市", - 231085: "穆棱市", - 231086: "东宁市", - 231100: "黑河市", - 231101: "黑河市市辖区", - 231102: "爱辉区", - 231121: "嫩江县", - 231123: "逊克县", - 231124: "孙吴县", - 231181: "北安市", - 231182: "五大连池市", - 231200: "绥化市", - 231201: "绥化市市辖区", - 231202: "北林区", - 231221: "望奎县", - 231222: "兰西县", - 231223: "青冈县", - 231224: "庆安县", - 231225: "明水县", - 231226: "绥棱县", - 231281: "安达市", - 231282: "肇东市", - 231283: "海伦市", - 232700: "大兴安岭地区", - 232701: "漠河市", - 232718: "加格达奇区", - 232721: "呼玛县", - 232722: "塔河县", - 310000: "上海市", - 310100: "上海市市辖区", - 310101: "黄浦区", - 310104: "徐汇区", - 310105: "长宁区", - 310106: "静安区", - 310107: "普陀区", - 310109: "虹口区", - 310110: "杨浦区", - 310112: "闵行区", - 310113: "宝山区", - 310114: "嘉定区", - 310115: "浦东新区", - 310116: "金山区", - 310117: "松江区", - 310118: "青浦区", - 310120: "奉贤区", - 310151: "崇明区", - 320000: "江苏省", - 320100: "南京市", - 320101: "南京市市辖区", - 320102: "玄武区", - 320104: "秦淮区", - 320105: "建邺区", - 320106: "鼓楼区", - 320111: "浦口区", - 320113: "栖霞区", - 320114: "雨花台区", - 320115: "江宁区", - 320116: "六合区", - 320117: "溧水区", - 320118: "高淳区", - 320200: "无锡市", - 320201: "无锡市市辖区", - 320205: "锡山区", - 320206: "惠山区", - 320211: "滨湖区", - 320213: "梁溪区", - 320214: "新吴区", - 320281: "江阴市", - 320282: "宜兴市", - 320300: "徐州市", - 320301: "徐州市市辖区", - 320302: "鼓楼区", - 320303: "云龙区", - 320305: "贾汪区", - 320311: "泉山区", - 320312: "铜山区", - 320321: "丰县", - 320322: "沛县", - 320324: "睢宁县", - 320381: "新沂市", - 320382: "邳州市", - 320400: "常州市", - 320401: "常州市市辖区", - 320402: "天宁区", - 320404: "钟楼区", - 320411: "新北区", - 320412: "武进区", - 320413: "金坛区", - 320481: "溧阳市", - 320500: "苏州市", - 320501: "苏州市市辖区", - 320505: "虎丘区", - 320506: "吴中区", - 320507: "相城区", - 320508: "姑苏区", - 320509: "吴江区", - 320571: "苏州工业园区", - 320581: "常熟市", - 320582: "张家港市", - 320583: "昆山市", - 320585: "太仓市", - 320600: "南通市", - 320601: "南通市市辖区", - 320602: "崇川区", - 320611: "港闸区", - 320612: "通州区", - 320623: "如东县", - 320681: "启东市", - 320682: "如皋市", - 320684: "海门市", - 320685: "海安市", - 320700: "连云港市", - 320701: "连云港市市辖区", - 320703: "连云区", - 320706: "海州区", - 320707: "赣榆区", - 320722: "东海县", - 320723: "灌云县", - 320724: "灌南县", - 320800: "淮安市", - 320801: "淮安市市辖区", - 320803: "淮安区", - 320804: "淮阴区", - 320812: "清江浦区", - 320813: "洪泽区", - 320826: "涟水县", - 320830: "盱眙县", - 320831: "金湖县", - 320900: "盐城市", - 320901: "盐城市市辖区", - 320902: "亭湖区", - 320903: "盐都区", - 320904: "大丰区", - 320921: "响水县", - 320922: "滨海县", - 320923: "阜宁县", - 320924: "射阳县", - 320925: "建湖县", - 320981: "东台市", - 321000: "扬州市", - 321001: "扬州市市辖区", - 321002: "广陵区", - 321003: "邗江区", - 321012: "江都区", - 321023: "宝应县", - 321081: "仪征市", - 321084: "高邮市", - 321100: "镇江市", - 321101: "镇江市市辖区", - 321102: "京口区", - 321111: "润州区", - 321112: "丹徒区", - 321181: "丹阳市", - 321182: "扬中市", - 321183: "句容市", - 321200: "泰州市", - 321201: "泰州市市辖区", - 321202: "海陵区", - 321203: "高港区", - 321204: "姜堰区", - 321281: "兴化市", - 321282: "靖江市", - 321283: "泰兴市", - 321300: "宿迁市", - 321301: "宿迁市市辖区", - 321302: "宿城区", - 321311: "宿豫区", - 321322: "沭阳县", - 321323: "泗阳县", - 321324: "泗洪县", - 330000: "浙江省", - 330100: "杭州市", - 330101: "杭州市市辖区", - 330102: "上城区", - 330103: "下城区", - 330104: "江干区", - 330105: "拱墅区", - 330106: "西湖区", - 330108: "滨江区", - 330109: "萧山区", - 330110: "余杭区", - 330111: "富阳区", - 330112: "临安区", - 330122: "桐庐县", - 330127: "淳安县", - 330182: "建德市", - 330200: "宁波市", - 330201: "宁波市市辖区", - 330203: "海曙区", - 330205: "江北区", - 330206: "北仑区", - 330211: "镇海区", - 330212: "鄞州区", - 330213: "奉化区", - 330225: "象山县", - 330226: "宁海县", - 330281: "余姚市", - 330282: "慈溪市", - 330300: "温州市", - 330301: "温州市市辖区", - 330302: "鹿城区", - 330303: "龙湾区", - 330304: "瓯海区", - 330305: "洞头区", - 330324: "永嘉县", - 330326: "平阳县", - 330327: "苍南县", - 330328: "文成县", - 330329: "泰顺县", - 330381: "瑞安市", - 330382: "乐清市", - 330400: "嘉兴市", - 330401: "嘉兴市市辖区", - 330402: "南湖区", - 330411: "秀洲区", - 330421: "嘉善县", - 330424: "海盐县", - 330481: "海宁市", - 330482: "平湖市", - 330483: "桐乡市", - 330500: "湖州市", - 330501: "湖州市市辖区", - 330502: "吴兴区", - 330503: "南浔区", - 330521: "德清县", - 330522: "长兴县", - 330523: "安吉县", - 330600: "绍兴市", - 330601: "绍兴市市辖区", - 330602: "越城区", - 330603: "柯桥区", - 330604: "上虞区", - 330624: "新昌县", - 330681: "诸暨市", - 330683: "嵊州市", - 330700: "金华市", - 330701: "金华市市辖区", - 330702: "婺城区", - 330703: "金东区", - 330723: "武义县", - 330726: "浦江县", - 330727: "磐安县", - 330781: "兰溪市", - 330782: "义乌市", - 330783: "东阳市", - 330784: "永康市", - 330800: "衢州市", - 330801: "衢州市市辖区", - 330802: "柯城区", - 330803: "衢江区", - 330822: "常山县", - 330824: "开化县", - 330825: "龙游县", - 330881: "江山市", - 330900: "舟山市", - 330901: "舟山市市辖区", - 330902: "定海区", - 330903: "普陀区", - 330921: "岱山县", - 330922: "嵊泗县", - 331000: "台州市", - 331001: "台州市市辖区", - 331002: "椒江区", - 331003: "黄岩区", - 331004: "路桥区", - 331022: "三门县", - 331023: "天台县", - 331024: "仙居县", - 331081: "温岭市", - 331082: "临海市", - 331083: "玉环市", - 331100: "丽水市", - 331101: "丽水市市辖区", - 331102: "莲都区", - 331121: "青田县", - 331122: "缙云县", - 331123: "遂昌县", - 331124: "松阳县", - 331125: "云和县", - 331126: "庆元县", - 331127: "景宁畲族自治县", - 331181: "龙泉市", - 340000: "安徽省", - 340100: "合肥市", - 340101: "合肥市市辖区", - 340102: "瑶海区", - 340103: "庐阳区", - 340104: "蜀山区", - 340111: "包河区", - 340121: "长丰县", - 340122: "肥东县", - 340123: "肥西县", - 340124: "庐江县", - 340181: "巢湖市", - 340200: "芜湖市", - 340201: "芜湖市市辖区", - 340202: "镜湖区", - 340203: "弋江区", - 340207: "鸠江区", - 340208: "三山区", - 340221: "芜湖县", - 340222: "繁昌县", - 340223: "南陵县", - 340225: "无为县", - 340300: "蚌埠市", - 340301: "蚌埠市市辖区", - 340302: "龙子湖区", - 340303: "蚌山区", - 340304: "禹会区", - 340311: "淮上区", - 340321: "怀远县", - 340322: "五河县", - 340323: "固镇县", - 340400: "淮南市", - 340401: "淮南市市辖区", - 340402: "大通区", - 340403: "田家庵区", - 340404: "谢家集区", - 340405: "八公山区", - 340406: "潘集区", - 340421: "凤台县", - 340422: "寿县", - 340500: "马鞍山市", - 340501: "马鞍山市市辖区", - 340503: "花山区", - 340504: "雨山区", - 340506: "博望区", - 340521: "当涂县", - 340522: "含山县", - 340523: "和县", - 340600: "淮北市", - 340601: "淮北市市辖区", - 340602: "杜集区", - 340603: "相山区", - 340604: "烈山区", - 340621: "濉溪县", - 340700: "铜陵市", - 340701: "铜陵市市辖区", - 340705: "铜官区", - 340706: "义安区", - 340711: "郊区", - 340722: "枞阳县", - 340800: "安庆市", - 340801: "安庆市市辖区", - 340802: "迎江区", - 340803: "大观区", - 340811: "宜秀区", - 340822: "怀宁县", - 340824: "潜山市", - 340825: "太湖县", - 340826: "宿松县", - 340827: "望江县", - 340828: "岳西县", - 340881: "桐城市", - 341000: "黄山市", - 341001: "黄山市市辖区", - 341002: "屯溪区", - 341003: "黄山区", - 341004: "徽州区", - 341021: "歙县", - 341022: "休宁县", - 341023: "黟县", - 341024: "祁门县", - 341100: "滁州市", - 341101: "滁州市市辖区", - 341102: "琅琊区", - 341103: "南谯区", - 341122: "来安县", - 341124: "全椒县", - 341125: "定远县", - 341126: "凤阳县", - 341181: "天长市", - 341182: "明光市", - 341200: "阜阳市", - 341201: "阜阳市市辖区", - 341202: "颍州区", - 341203: "颍东区", - 341204: "颍泉区", - 341221: "临泉县", - 341222: "太和县", - 341225: "阜南县", - 341226: "颍上县", - 341282: "界首市", - 341300: "宿州市", - 341301: "宿州市市辖区", - 341302: "埇桥区", - 341321: "砀山县", - 341322: "萧县", - 341323: "灵璧县", - 341324: "泗县", - 341500: "六安市", - 341501: "六安市市辖区", - 341502: "金安区", - 341503: "裕安区", - 341504: "叶集区", - 341522: "霍邱县", - 341523: "舒城县", - 341524: "金寨县", - 341525: "霍山县", - 341600: "亳州市", - 341601: "亳州市市辖区", - 341602: "谯城区", - 341621: "涡阳县", - 341622: "蒙城县", - 341623: "利辛县", - 341700: "池州市", - 341701: "池州市市辖区", - 341702: "贵池区", - 341721: "东至县", - 341722: "石台县", - 341723: "青阳县", - 341800: "宣城市", - 341801: "宣城市市辖区", - 341802: "宣州区", - 341821: "郎溪县", - 341822: "广德县", - 341823: "泾县", - 341824: "绩溪县", - 341825: "旌德县", - 341881: "宁国市", - 350000: "福建省", - 350100: "福州市", - 350101: "福州市市辖区", - 350102: "鼓楼区", - 350103: "台江区", - 350104: "仓山区", - 350105: "马尾区", - 350111: "晋安区", - 350112: "长乐区", - 350121: "闽侯县", - 350122: "连江县", - 350123: "罗源县", - 350124: "闽清县", - 350125: "永泰县", - 350128: "平潭县", - 350181: "福清市", - 350200: "厦门市", - 350201: "厦门市市辖区", - 350203: "思明区", - 350205: "海沧区", - 350206: "湖里区", - 350211: "集美区", - 350212: "同安区", - 350213: "翔安区", - 350300: "莆田市", - 350301: "莆田市市辖区", - 350302: "城厢区", - 350303: "涵江区", - 350304: "荔城区", - 350305: "秀屿区", - 350322: "仙游县", - 350400: "三明市", - 350401: "三明市市辖区", - 350402: "梅列区", - 350403: "三元区", - 350421: "明溪县", - 350423: "清流县", - 350424: "宁化县", - 350425: "大田县", - 350426: "尤溪县", - 350427: "沙县", - 350428: "将乐县", - 350429: "泰宁县", - 350430: "建宁县", - 350481: "永安市", - 350500: "泉州市", - 350501: "泉州市市辖区", - 350502: "鲤城区", - 350503: "丰泽区", - 350504: "洛江区", - 350505: "泉港区", - 350521: "惠安县", - 350524: "安溪县", - 350525: "永春县", - 350526: "德化县", - 350527: "金门县", - 350581: "石狮市", - 350582: "晋江市", - 350583: "南安市", - 350600: "漳州市", - 350601: "漳州市市辖区", - 350602: "芗城区", - 350603: "龙文区", - 350622: "云霄县", - 350623: "漳浦县", - 350624: "诏安县", - 350625: "长泰县", - 350626: "东山县", - 350627: "南靖县", - 350628: "平和县", - 350629: "华安县", - 350681: "龙海市", - 350700: "南平市", - 350701: "南平市市辖区", - 350702: "延平区", - 350703: "建阳区", - 350721: "顺昌县", - 350722: "浦城县", - 350723: "光泽县", - 350724: "松溪县", - 350725: "政和县", - 350781: "邵武市", - 350782: "武夷山市", - 350783: "建瓯市", - 350800: "龙岩市", - 350801: "龙岩市市辖区", - 350802: "新罗区", - 350803: "永定区", - 350821: "长汀县", - 350823: "上杭县", - 350824: "武平县", - 350825: "连城县", - 350881: "漳平市", - 350900: "宁德市", - 350901: "宁德市市辖区", - 350902: "蕉城区", - 350921: "霞浦县", - 350922: "古田县", - 350923: "屏南县", - 350924: "寿宁县", - 350925: "周宁县", - 350926: "柘荣县", - 350981: "福安市", - 350982: "福鼎市", - 360000: "江西省", - 360100: "南昌市", - 360101: "南昌市市辖区", - 360102: "东湖区", - 360103: "西湖区", - 360104: "青云谱区", - 360105: "湾里区", - 360111: "青山湖区", - 360112: "新建区", - 360121: "南昌县", - 360123: "安义县", - 360124: "进贤县", - 360200: "景德镇市", - 360201: "景德镇市市辖区", - 360202: "昌江区", - 360203: "珠山区", - 360222: "浮梁县", - 360281: "乐平市", - 360300: "萍乡市", - 360301: "萍乡市市辖区", - 360302: "安源区", - 360313: "湘东区", - 360321: "莲花县", - 360322: "上栗县", - 360323: "芦溪县", - 360400: "九江市", - 360401: "九江市市辖区", - 360402: "濂溪区", - 360403: "浔阳区", - 360404: "柴桑区", - 360423: "武宁县", - 360424: "修水县", - 360425: "永修县", - 360426: "德安县", - 360428: "都昌县", - 360429: "湖口县", - 360430: "彭泽县", - 360481: "瑞昌市", - 360482: "共青城市", - 360483: "庐山市", - 360500: "新余市", - 360501: "新余市市辖区", - 360502: "渝水区", - 360521: "分宜县", - 360600: "鹰潭市", - 360601: "鹰潭市市辖区", - 360602: "月湖区", - 360603: "余江区", - 360681: "贵溪市", - 360700: "赣州市", - 360701: "赣州市市辖区", - 360702: "章贡区", - 360703: "南康区", - 360704: "赣县区", - 360722: "信丰县", - 360723: "大余县", - 360724: "上犹县", - 360725: "崇义县", - 360726: "安远县", - 360727: "龙南县", - 360728: "定南县", - 360729: "全南县", - 360730: "宁都县", - 360731: "于都县", - 360732: "兴国县", - 360733: "会昌县", - 360734: "寻乌县", - 360735: "石城县", - 360781: "瑞金市", - 360800: "吉安市", - 360801: "吉安市市辖区", - 360802: "吉州区", - 360803: "青原区", - 360821: "吉安县", - 360822: "吉水县", - 360823: "峡江县", - 360824: "新干县", - 360825: "永丰县", - 360826: "泰和县", - 360827: "遂川县", - 360828: "万安县", - 360829: "安福县", - 360830: "永新县", - 360881: "井冈山市", - 360900: "宜春市", - 360901: "宜春市市辖区", - 360902: "袁州区", - 360921: "奉新县", - 360922: "万载县", - 360923: "上高县", - 360924: "宜丰县", - 360925: "靖安县", - 360926: "铜鼓县", - 360981: "丰城市", - 360982: "樟树市", - 360983: "高安市", - 361000: "抚州市", - 361001: "抚州市市辖区", - 361002: "临川区", - 361003: "东乡区", - 361021: "南城县", - 361022: "黎川县", - 361023: "南丰县", - 361024: "崇仁县", - 361025: "乐安县", - 361026: "宜黄县", - 361027: "金溪县", - 361028: "资溪县", - 361030: "广昌县", - 361100: "上饶市", - 361101: "上饶市市辖区", - 361102: "信州区", - 361103: "广丰区", - 361121: "上饶县", - 361123: "玉山县", - 361124: "铅山县", - 361125: "横峰县", - 361126: "弋阳县", - 361127: "余干县", - 361128: "鄱阳县", - 361129: "万年县", - 361130: "婺源县", - 361181: "德兴市", - 370000: "山东省", - 370100: "济南市", - 370101: "济南市市辖区", - 370102: "历下区", - 370103: "市中区", - 370104: "槐荫区", - 370105: "天桥区", - 370112: "历城区", - 370113: "长清区", - 370114: "章丘区", - 370115: "济阳区", - 370116: "莱芜区", - 370117: "钢城区", - 370124: "平阴县", - 370126: "商河县", - 370200: "青岛市", - 370201: "青岛市市辖区", - 370202: "市南区", - 370203: "市北区", - 370211: "黄岛区", - 370212: "崂山区", - 370213: "李沧区", - 370214: "城阳区", - 370215: "即墨区", - 370281: "胶州市", - 370283: "平度市", - 370285: "莱西市", - 370300: "淄博市", - 370301: "淄博市市辖区", - 370302: "淄川区", - 370303: "张店区", - 370304: "博山区", - 370305: "临淄区", - 370306: "周村区", - 370321: "桓台县", - 370322: "高青县", - 370323: "沂源县", - 370400: "枣庄市", - 370401: "枣庄市市辖区", - 370402: "市中区", - 370403: "薛城区", - 370404: "峄城区", - 370405: "台儿庄区", - 370406: "山亭区", - 370481: "滕州市", - 370500: "东营市", - 370501: "东营市市辖区", - 370502: "东营区", - 370503: "河口区", - 370505: "垦利区", - 370522: "利津县", - 370523: "广饶县", - 370600: "烟台市", - 370601: "烟台市市辖区", - 370602: "芝罘区", - 370611: "福山区", - 370612: "牟平区", - 370613: "莱山区", - 370634: "长岛县", - 370681: "龙口市", - 370682: "莱阳市", - 370683: "莱州市", - 370684: "蓬莱市", - 370685: "招远市", - 370686: "栖霞市", - 370687: "海阳市", - 370700: "潍坊市", - 370701: "潍坊市市辖区", - 370702: "潍城区", - 370703: "寒亭区", - 370704: "坊子区", - 370705: "奎文区", - 370724: "临朐县", - 370725: "昌乐县", - 370781: "青州市", - 370782: "诸城市", - 370783: "寿光市", - 370784: "安丘市", - 370785: "高密市", - 370786: "昌邑市", - 370800: "济宁市", - 370801: "济宁市市辖区", - 370811: "任城区", - 370812: "兖州区", - 370826: "微山县", - 370827: "鱼台县", - 370828: "金乡县", - 370829: "嘉祥县", - 370830: "汶上县", - 370831: "泗水县", - 370832: "梁山县", - 370881: "曲阜市", - 370883: "邹城市", - 370900: "泰安市", - 370901: "泰安市市辖区", - 370902: "泰山区", - 370911: "岱岳区", - 370921: "宁阳县", - 370923: "东平县", - 370982: "新泰市", - 370983: "肥城市", - 371000: "威海市", - 371001: "威海市市辖区", - 371002: "环翠区", - 371003: "文登区", - 371082: "荣成市", - 371083: "乳山市", - 371100: "日照市", - 371101: "日照市市辖区", - 371102: "东港区", - 371103: "岚山区", - 371121: "五莲县", - 371122: "莒县", - 371300: "临沂市", - 371301: "临沂市市辖区", - 371302: "兰山区", - 371311: "罗庄区", - 371312: "河东区", - 371321: "沂南县", - 371322: "郯城县", - 371323: "沂水县", - 371324: "兰陵县", - 371325: "费县", - 371326: "平邑县", - 371327: "莒南县", - 371328: "蒙阴县", - 371329: "临沭县", - 371400: "德州市", - 371401: "德州市市辖区", - 371402: "德城区", - 371403: "陵城区", - 371422: "宁津县", - 371423: "庆云县", - 371424: "临邑县", - 371425: "齐河县", - 371426: "平原县", - 371427: "夏津县", - 371428: "武城县", - 371481: "乐陵市", - 371482: "禹城市", - 371500: "聊城市", - 371501: "聊城市市辖区", - 371502: "东昌府区", - 371521: "阳谷县", - 371522: "莘县", - 371523: "茌平县", - 371524: "东阿县", - 371525: "冠县", - 371526: "高唐县", - 371581: "临清市", - 371600: "滨州市", - 371601: "滨州市市辖区", - 371602: "滨城区", - 371603: "沾化区", - 371621: "惠民县", - 371622: "阳信县", - 371623: "无棣县", - 371625: "博兴县", - 371681: "邹平市", - 371700: "菏泽市", - 371701: "菏泽市市辖区", - 371702: "牡丹区", - 371703: "定陶区", - 371721: "曹县", - 371722: "单县", - 371723: "成武县", - 371724: "巨野县", - 371725: "郓城县", - 371726: "鄄城县", - 371728: "东明县", - 410000: "河南省", - 410100: "郑州市", - 410101: "郑州市市辖区", - 410102: "中原区", - 410103: "二七区", - 410104: "管城回族区", - 410105: "金水区", - 410106: "上街区", - 410108: "惠济区", - 410122: "中牟县", - 410181: "巩义市", - 410182: "荥阳市", - 410183: "新密市", - 410184: "新郑市", - 410185: "登封市", - 410200: "开封市", - 410201: "开封市市辖区", - 410202: "龙亭区", - 410203: "顺河回族区", - 410204: "鼓楼区", - 410205: "禹王台区", - 410212: "祥符区", - 410221: "杞县", - 410222: "通许县", - 410223: "尉氏县", - 410225: "兰考县", - 410300: "洛阳市", - 410301: "洛阳市市辖区", - 410302: "老城区", - 410303: "西工区", - 410304: "瀍河回族区", - 410305: "涧西区", - 410306: "吉利区", - 410311: "洛龙区", - 410322: "孟津县", - 410323: "新安县", - 410324: "栾川县", - 410325: "嵩县", - 410326: "汝阳县", - 410327: "宜阳县", - 410328: "洛宁县", - 410329: "伊川县", - 410381: "偃师市", - 410400: "平顶山市", - 410401: "平顶山市市辖区", - 410402: "新华区", - 410403: "卫东区", - 410404: "石龙区", - 410411: "湛河区", - 410421: "宝丰县", - 410422: "叶县", - 410423: "鲁山县", - 410425: "郏县", - 410481: "舞钢市", - 410482: "汝州市", - 410500: "安阳市", - 410501: "安阳市市辖区", - 410502: "文峰区", - 410503: "北关区", - 410505: "殷都区", - 410506: "龙安区", - 410522: "安阳县", - 410523: "汤阴县", - 410526: "滑县", - 410527: "内黄县", - 410581: "林州市", - 410600: "鹤壁市", - 410601: "鹤壁市市辖区", - 410602: "鹤山区", - 410603: "山城区", - 410611: "淇滨区", - 410621: "浚县", - 410622: "淇县", - 410700: "新乡市", - 410701: "新乡市市辖区", - 410702: "红旗区", - 410703: "卫滨区", - 410704: "凤泉区", - 410711: "牧野区", - 410721: "新乡县", - 410724: "获嘉县", - 410725: "原阳县", - 410726: "延津县", - 410727: "封丘县", - 410728: "长垣县", - 410781: "卫辉市", - 410782: "辉县市", - 410800: "焦作市", - 410801: "焦作市市辖区", - 410802: "解放区", - 410803: "中站区", - 410804: "马村区", - 410811: "山阳区", - 410821: "修武县", - 410822: "博爱县", - 410823: "武陟县", - 410825: "温县", - 410882: "沁阳市", - 410883: "孟州市", - 410900: "濮阳市", - 410901: "濮阳市市辖区", - 410902: "华龙区", - 410922: "清丰县", - 410923: "南乐县", - 410926: "范县", - 410927: "台前县", - 410928: "濮阳县", - 411000: "许昌市", - 411001: "许昌市市辖区", - 411002: "魏都区", - 411003: "建安区", - 411024: "鄢陵县", - 411025: "襄城县", - 411081: "禹州市", - 411082: "长葛市", - 411100: "漯河市", - 411101: "漯河市市辖区", - 411102: "源汇区", - 411103: "郾城区", - 411104: "召陵区", - 411121: "舞阳县", - 411122: "临颍县", - 411200: "三门峡市", - 411201: "三门峡市市辖区", - 411202: "湖滨区", - 411203: "陕州区", - 411221: "渑池县", - 411224: "卢氏县", - 411281: "义马市", - 411282: "灵宝市", - 411300: "南阳市", - 411301: "南阳市市辖区", - 411302: "宛城区", - 411303: "卧龙区", - 411321: "南召县", - 411322: "方城县", - 411323: "西峡县", - 411324: "镇平县", - 411325: "内乡县", - 411326: "淅川县", - 411327: "社旗县", - 411328: "唐河县", - 411329: "新野县", - 411330: "桐柏县", - 411381: "邓州市", - 411400: "商丘市", - 411401: "商丘市市辖区", - 411402: "梁园区", - 411403: "睢阳区", - 411421: "民权县", - 411422: "睢县", - 411423: "宁陵县", - 411424: "柘城县", - 411425: "虞城县", - 411426: "夏邑县", - 411481: "永城市", - 411500: "信阳市", - 411501: "信阳市市辖区", - 411502: "浉河区", - 411503: "平桥区", - 411521: "罗山县", - 411522: "光山县", - 411523: "新县", - 411524: "商城县", - 411525: "固始县", - 411526: "潢川县", - 411527: "淮滨县", - 411528: "息县", - 411600: "周口市", - 411601: "周口市市辖区", - 411602: "川汇区", - 411621: "扶沟县", - 411622: "西华县", - 411623: "商水县", - 411624: "沈丘县", - 411625: "郸城县", - 411626: "淮阳县", - 411627: "太康县", - 411628: "鹿邑县", - 411681: "项城市", - 411700: "驻马店市", - 411701: "驻马店市市辖区", - 411702: "驿城区", - 411721: "西平县", - 411722: "上蔡县", - 411723: "平舆县", - 411724: "正阳县", - 411725: "确山县", - 411726: "泌阳县", - 411727: "汝南县", - 411728: "遂平县", - 411729: "新蔡县", - 419001: "济源市", - 420000: "湖北省", - 420100: "武汉市", - 420101: "武汉市市辖区", - 420102: "江岸区", - 420103: "江汉区", - 420104: "硚口区", - 420105: "汉阳区", - 420106: "武昌区", - 420107: "青山区", - 420111: "洪山区", - 420112: "东西湖区", - 420113: "汉南区", - 420114: "蔡甸区", - 420115: "江夏区", - 420116: "黄陂区", - 420117: "新洲区", - 420200: "黄石市", - 420201: "黄石市市辖区", - 420202: "黄石港区", - 420203: "西塞山区", - 420204: "下陆区", - 420205: "铁山区", - 420222: "阳新县", - 420281: "大冶市", - 420300: "十堰市", - 420301: "十堰市市辖区", - 420302: "茅箭区", - 420303: "张湾区", - 420304: "郧阳区", - 420322: "郧西县", - 420323: "竹山县", - 420324: "竹溪县", - 420325: "房县", - 420381: "丹江口市", - 420500: "宜昌市", - 420501: "宜昌市市辖区", - 420502: "西陵区", - 420503: "伍家岗区", - 420504: "点军区", - 420505: "猇亭区", - 420506: "夷陵区", - 420525: "远安县", - 420526: "兴山县", - 420527: "秭归县", - 420528: "长阳土家族自治县", - 420529: "五峰土家族自治县", - 420581: "宜都市", - 420582: "当阳市", - 420583: "枝江市", - 420600: "襄阳市", - 420601: "襄阳市市辖区", - 420602: "襄城区", - 420606: "樊城区", - 420607: "襄州区", - 420624: "南漳县", - 420625: "谷城县", - 420626: "保康县", - 420682: "老河口市", - 420683: "枣阳市", - 420684: "宜城市", - 420700: "鄂州市", - 420701: "鄂州市市辖区", - 420702: "梁子湖区", - 420703: "华容区", - 420704: "鄂城区", - 420800: "荆门市", - 420801: "荆门市市辖区", - 420802: "东宝区", - 420804: "掇刀区", - 420822: "沙洋县", - 420881: "钟祥市", - 420882: "京山市", - 420900: "孝感市", - 420901: "孝感市市辖区", - 420902: "孝南区", - 420921: "孝昌县", - 420922: "大悟县", - 420923: "云梦县", - 420981: "应城市", - 420982: "安陆市", - 420984: "汉川市", - 421000: "荆州市", - 421001: "荆州市市辖区", - 421002: "沙市区", - 421003: "荆州区", - 421022: "公安县", - 421023: "监利县", - 421024: "江陵县", - 421081: "石首市", - 421083: "洪湖市", - 421087: "松滋市", - 421100: "黄冈市", - 421101: "黄冈市市辖区", - 421102: "黄州区", - 421121: "团风县", - 421122: "红安县", - 421123: "罗田县", - 421124: "英山县", - 421125: "浠水县", - 421126: "蕲春县", - 421127: "黄梅县", - 421181: "麻城市", - 421182: "武穴市", - 421200: "咸宁市", - 421201: "咸宁市市辖区", - 421202: "咸安区", - 421221: "嘉鱼县", - 421222: "通城县", - 421223: "崇阳县", - 421224: "通山县", - 421281: "赤壁市", - 421300: "随州市", - 421301: "随州市市辖区", - 421303: "曾都区", - 421321: "随县", - 421381: "广水市", - 422800: "恩施土家族苗族自治州", - 422801: "恩施市", - 422802: "利川市", - 422822: "建始县", - 422823: "巴东县", - 422825: "宣恩县", - 422826: "咸丰县", - 422827: "来凤县", - 422828: "鹤峰县", - 429004: "仙桃市", - 429005: "潜江市", - 429006: "天门市", - 429021: "神农架林区", - 430000: "湖南省", - 430100: "长沙市", - 430101: "长沙市市辖区", - 430102: "芙蓉区", - 430103: "天心区", - 430104: "岳麓区", - 430105: "开福区", - 430111: "雨花区", - 430112: "望城区", - 430121: "长沙县", - 430181: "浏阳市", - 430182: "宁乡市", - 430200: "株洲市", - 430201: "株洲市市辖区", - 430202: "荷塘区", - 430203: "芦淞区", - 430204: "石峰区", - 430211: "天元区", - 430212: "渌口区", - 430223: "攸县", - 430224: "茶陵县", - 430225: "炎陵县", - 430281: "醴陵市", - 430300: "湘潭市", - 430301: "湘潭市市辖区", - 430302: "雨湖区", - 430304: "岳塘区", - 430321: "湘潭县", - 430381: "湘乡市", - 430382: "韶山市", - 430400: "衡阳市", - 430401: "衡阳市市辖区", - 430405: "珠晖区", - 430406: "雁峰区", - 430407: "石鼓区", - 430408: "蒸湘区", - 430412: "南岳区", - 430421: "衡阳县", - 430422: "衡南县", - 430423: "衡山县", - 430424: "衡东县", - 430426: "祁东县", - 430481: "耒阳市", - 430482: "常宁市", - 430500: "邵阳市", - 430501: "邵阳市市辖区", - 430502: "双清区", - 430503: "大祥区", - 430511: "北塔区", - 430521: "邵东县", - 430522: "新邵县", - 430523: "邵阳县", - 430524: "隆回县", - 430525: "洞口县", - 430527: "绥宁县", - 430528: "新宁县", - 430529: "城步苗族自治县", - 430581: "武冈市", - 430600: "岳阳市", - 430601: "岳阳市市辖区", - 430602: "岳阳楼区", - 430603: "云溪区", - 430611: "君山区", - 430621: "岳阳县", - 430623: "华容县", - 430624: "湘阴县", - 430626: "平江县", - 430681: "汨罗市", - 430682: "临湘市", - 430700: "常德市", - 430701: "常德市市辖区", - 430702: "武陵区", - 430703: "鼎城区", - 430721: "安乡县", - 430722: "汉寿县", - 430723: "澧县", - 430724: "临澧县", - 430725: "桃源县", - 430726: "石门县", - 430781: "津市市", - 430800: "张家界市", - 430801: "张家界市市辖区", - 430802: "永定区", - 430811: "武陵源区", - 430821: "慈利县", - 430822: "桑植县", - 430900: "益阳市", - 430901: "益阳市市辖区", - 430902: "资阳区", - 430903: "赫山区", - 430921: "南县", - 430922: "桃江县", - 430923: "安化县", - 430981: "沅江市", - 431000: "郴州市", - 431001: "郴州市市辖区", - 431002: "北湖区", - 431003: "苏仙区", - 431021: "桂阳县", - 431022: "宜章县", - 431023: "永兴县", - 431024: "嘉禾县", - 431025: "临武县", - 431026: "汝城县", - 431027: "桂东县", - 431028: "安仁县", - 431081: "资兴市", - 431100: "永州市", - 431101: "永州市市辖区", - 431102: "零陵区", - 431103: "冷水滩区", - 431121: "祁阳县", - 431122: "东安县", - 431123: "双牌县", - 431124: "道县", - 431125: "江永县", - 431126: "宁远县", - 431127: "蓝山县", - 431128: "新田县", - 431129: "江华瑶族自治县", - 431200: "怀化市", - 431201: "怀化市市辖区", - 431202: "鹤城区", - 431221: "中方县", - 431222: "沅陵县", - 431223: "辰溪县", - 431224: "溆浦县", - 431225: "会同县", - 431226: "麻阳苗族自治县", - 431227: "新晃侗族自治县", - 431228: "芷江侗族自治县", - 431229: "靖州苗族侗族自治县", - 431230: "通道侗族自治县", - 431281: "洪江市", - 431300: "娄底市", - 431301: "娄底市市辖区", - 431302: "娄星区", - 431321: "双峰县", - 431322: "新化县", - 431381: "冷水江市", - 431382: "涟源市", - 433100: "湘西土家族苗族自治州", - 433101: "吉首市", - 433122: "泸溪县", - 433123: "凤凰县", - 433124: "花垣县", - 433125: "保靖县", - 433126: "古丈县", - 433127: "永顺县", - 433130: "龙山县", - 440000: "广东省", - 440100: "广州市", - 440101: "广州市市辖区", - 440103: "荔湾区", - 440104: "越秀区", - 440105: "海珠区", - 440106: "天河区", - 440111: "白云区", - 440112: "黄埔区", - 440113: "番禺区", - 440114: "花都区", - 440115: "南沙区", - 440117: "从化区", - 440118: "增城区", - 440200: "韶关市", - 440201: "韶关市市辖区", - 440203: "武江区", - 440204: "浈江区", - 440205: "曲江区", - 440222: "始兴县", - 440224: "仁化县", - 440229: "翁源县", - 440232: "乳源瑶族自治县", - 440233: "新丰县", - 440281: "乐昌市", - 440282: "南雄市", - 440300: "深圳市", - 440301: "深圳市市辖区", - 440303: "罗湖区", - 440304: "福田区", - 440305: "南山区", - 440306: "宝安区", - 440307: "龙岗区", - 440308: "盐田区", - 440309: "龙华区", - 440310: "坪山区", - 440311: "光明区", - 440400: "珠海市", - 440401: "珠海市市辖区", - 440402: "香洲区", - 440403: "斗门区", - 440404: "金湾区", - 440500: "汕头市", - 440501: "汕头市市辖区", - 440507: "龙湖区", - 440511: "金平区", - 440512: "濠江区", - 440513: "潮阳区", - 440514: "潮南区", - 440515: "澄海区", - 440523: "南澳县", - 440600: "佛山市", - 440601: "佛山市市辖区", - 440604: "禅城区", - 440605: "南海区", - 440606: "顺德区", - 440607: "三水区", - 440608: "高明区", - 440700: "江门市", - 440701: "江门市市辖区", - 440703: "蓬江区", - 440704: "江海区", - 440705: "新会区", - 440781: "台山市", - 440783: "开平市", - 440784: "鹤山市", - 440785: "恩平市", - 440800: "湛江市", - 440801: "湛江市市辖区", - 440802: "赤坎区", - 440803: "霞山区", - 440804: "坡头区", - 440811: "麻章区", - 440823: "遂溪县", - 440825: "徐闻县", - 440881: "廉江市", - 440882: "雷州市", - 440883: "吴川市", - 440900: "茂名市", - 440901: "茂名市市辖区", - 440902: "茂南区", - 440904: "电白区", - 440981: "高州市", - 440982: "化州市", - 440983: "信宜市", - 441200: "肇庆市", - 441201: "肇庆市市辖区", - 441202: "端州区", - 441203: "鼎湖区", - 441204: "高要区", - 441223: "广宁县", - 441224: "怀集县", - 441225: "封开县", - 441226: "德庆县", - 441284: "四会市", - 441300: "惠州市", - 441301: "惠州市市辖区", - 441302: "惠城区", - 441303: "惠阳区", - 441322: "博罗县", - 441323: "惠东县", - 441324: "龙门县", - 441400: "梅州市", - 441401: "梅州市市辖区", - 441402: "梅江区", - 441403: "梅县区", - 441422: "大埔县", - 441423: "丰顺县", - 441424: "五华县", - 441426: "平远县", - 441427: "蕉岭县", - 441481: "兴宁市", - 441500: "汕尾市", - 441501: "汕尾市市辖区", - 441502: "城区", - 441521: "海丰县", - 441523: "陆河县", - 441581: "陆丰市", - 441600: "河源市", - 441601: "河源市市辖区", - 441602: "源城区", - 441621: "紫金县", - 441622: "龙川县", - 441623: "连平县", - 441624: "和平县", - 441625: "东源县", - 441700: "阳江市", - 441701: "阳江市市辖区", - 441702: "江城区", - 441704: "阳东区", - 441721: "阳西县", - 441781: "阳春市", - 441800: "清远市", - 441801: "清远市市辖区", - 441802: "清城区", - 441803: "清新区", - 441821: "佛冈县", - 441823: "阳山县", - 441825: "连山壮族瑶族自治县", - 441826: "连南瑶族自治县", - 441881: "英德市", - 441882: "连州市", - 441900: "东莞市", - 442000: "中山市", - 442101: "东沙群岛", - 445100: "潮州市", - 445101: "潮州市市辖区", - 445102: "湘桥区", - 445103: "潮安区", - 445122: "饶平县", - 445200: "揭阳市", - 445201: "揭阳市市辖区", - 445202: "榕城区", - 445203: "揭东区", - 445222: "揭西县", - 445224: "惠来县", - 445281: "普宁市", - 445300: "云浮市", - 445301: "云浮市市辖区", - 445302: "云城区", - 445303: "云安区", - 445321: "新兴县", - 445322: "郁南县", - 445381: "罗定市", - 450000: "广西壮族自治区", - 450100: "南宁市", - 450101: "南宁市市辖区", - 450102: "兴宁区", - 450103: "青秀区", - 450105: "江南区", - 450107: "西乡塘区", - 450108: "良庆区", - 450109: "邕宁区", - 450110: "武鸣区", - 450123: "隆安县", - 450124: "马山县", - 450125: "上林县", - 450126: "宾阳县", - 450127: "横县", - 450200: "柳州市", - 450201: "柳州市市辖区", - 450202: "城中区", - 450203: "鱼峰区", - 450204: "柳南区", - 450205: "柳北区", - 450206: "柳江区", - 450222: "柳城县", - 450223: "鹿寨县", - 450224: "融安县", - 450225: "融水苗族自治县", - 450226: "三江侗族自治县", - 450300: "桂林市", - 450301: "桂林市市辖区", - 450302: "秀峰区", - 450303: "叠彩区", - 450304: "象山区", - 450305: "七星区", - 450311: "雁山区", - 450312: "临桂区", - 450321: "阳朔县", - 450323: "灵川县", - 450324: "全州县", - 450325: "兴安县", - 450326: "永福县", - 450327: "灌阳县", - 450328: "龙胜各族自治县", - 450329: "资源县", - 450330: "平乐县", - 450332: "恭城瑶族自治县", - 450381: "荔浦市", - 450400: "梧州市", - 450401: "梧州市市辖区", - 450403: "万秀区", - 450405: "长洲区", - 450406: "龙圩区", - 450421: "苍梧县", - 450422: "藤县", - 450423: "蒙山县", - 450481: "岑溪市", - 450500: "北海市", - 450501: "北海市市辖区", - 450502: "海城区", - 450503: "银海区", - 450512: "铁山港区", - 450521: "合浦县", - 450600: "防城港市", - 450601: "防城港市市辖区", - 450602: "港口区", - 450603: "防城区", - 450621: "上思县", - 450681: "东兴市", - 450700: "钦州市", - 450701: "钦州市市辖区", - 450702: "钦南区", - 450703: "钦北区", - 450721: "灵山县", - 450722: "浦北县", - 450800: "贵港市", - 450801: "贵港市市辖区", - 450802: "港北区", - 450803: "港南区", - 450804: "覃塘区", - 450821: "平南县", - 450881: "桂平市", - 450900: "玉林市", - 450901: "玉林市市辖区", - 450902: "玉州区", - 450903: "福绵区", - 450921: "容县", - 450922: "陆川县", - 450923: "博白县", - 450924: "兴业县", - 450981: "北流市", - 451000: "百色市", - 451001: "百色市市辖区", - 451002: "右江区", - 451021: "田阳县", - 451022: "田东县", - 451023: "平果县", - 451024: "德保县", - 451026: "那坡县", - 451027: "凌云县", - 451028: "乐业县", - 451029: "田林县", - 451030: "西林县", - 451031: "隆林各族自治县", - 451081: "靖西市", - 451100: "贺州市", - 451101: "贺州市市辖区", - 451102: "八步区", - 451103: "平桂区", - 451121: "昭平县", - 451122: "钟山县", - 451123: "富川瑶族自治县", - 451200: "河池市", - 451201: "河池市市辖区", - 451202: "金城江区", - 451203: "宜州区", - 451221: "南丹县", - 451222: "天峨县", - 451223: "凤山县", - 451224: "东兰县", - 451225: "罗城仫佬族自治县", - 451226: "环江毛南族自治县", - 451227: "巴马瑶族自治县", - 451228: "都安瑶族自治县", - 451229: "大化瑶族自治县", - 451300: "来宾市", - 451301: "来宾市市辖区", - 451302: "兴宾区", - 451321: "忻城县", - 451322: "象州县", - 451323: "武宣县", - 451324: "金秀瑶族自治县", - 451381: "合山市", - 451400: "崇左市", - 451401: "崇左市市辖区", - 451402: "江州区", - 451421: "扶绥县", - 451422: "宁明县", - 451423: "龙州县", - 451424: "大新县", - 451425: "天等县", - 451481: "凭祥市", - 460000: "海南省", - 460100: "海口市", - 460101: "海口市市辖区", - 460105: "秀英区", - 460106: "龙华区", - 460107: "琼山区", - 460108: "美兰区", - 460200: "三亚市", - 460201: "三亚市市辖区", - 460202: "海棠区", - 460203: "吉阳区", - 460204: "天涯区", - 460205: "崖州区", - 460300: "三沙市", - 460301: "三沙市市辖区", - 460321: "西沙群岛", - 460322: "南沙群岛", - 460323: "中沙群岛的岛礁及其海域", - 460400: "儋州市", - 469001: "五指山市", - 469002: "琼海市", - 469005: "文昌市", - 469006: "万宁市", - 469007: "东方市", - 469021: "定安县", - 469022: "屯昌县", - 469023: "澄迈县", - 469024: "临高县", - 469025: "白沙黎族自治县", - 469026: "昌江黎族自治县", - 469027: "乐东黎族自治县", - 469028: "陵水黎族自治县", - 469029: "保亭黎族苗族自治县", - 469030: "琼中黎族苗族自治县", - 500000: "重庆市", - 500100: "重庆市市辖区", - 500101: "万州区", - 500102: "涪陵区", - 500103: "渝中区", - 500104: "大渡口区", - 500105: "江北区", - 500106: "沙坪坝区", - 500107: "九龙坡区", - 500108: "南岸区", - 500109: "北碚区", - 500110: "綦江区", - 500111: "大足区", - 500112: "渝北区", - 500113: "巴南区", - 500114: "黔江区", - 500115: "长寿区", - 500116: "江津区", - 500117: "合川区", - 500118: "永川区", - 500119: "南川区", - 500120: "璧山区", - 500151: "铜梁区", - 500152: "潼南区", - 500153: "荣昌区", - 500154: "开州区", - 500155: "梁平区", - 500156: "武隆区", - 500200: "重庆市郊县", - 500229: "城口县", - 500230: "丰都县", - 500231: "垫江县", - 500233: "忠县", - 500235: "云阳县", - 500236: "奉节县", - 500237: "巫山县", - 500238: "巫溪县", - 500240: "石柱土家族自治县", - 500241: "秀山土家族苗族自治县", - 500242: "酉阳土家族苗族自治县", - 500243: "彭水苗族土家族自治县", - 510000: "四川省", - 510100: "成都市", - 510101: "成都市市辖区", - 510104: "锦江区", - 510105: "青羊区", - 510106: "金牛区", - 510107: "武侯区", - 510108: "成华区", - 510112: "龙泉驿区", - 510113: "青白江区", - 510114: "新都区", - 510115: "温江区", - 510116: "双流区", - 510117: "郫都区", - 510121: "金堂县", - 510129: "大邑县", - 510131: "蒲江县", - 510132: "新津县", - 510181: "都江堰市", - 510182: "彭州市", - 510183: "邛崃市", - 510184: "崇州市", - 510185: "简阳市", - 510300: "自贡市", - 510301: "自贡市市辖区", - 510302: "自流井区", - 510303: "贡井区", - 510304: "大安区", - 510311: "沿滩区", - 510321: "荣县", - 510322: "富顺县", - 510400: "攀枝花市", - 510401: "攀枝花市市辖区", - 510402: "东区", - 510403: "西区", - 510411: "仁和区", - 510421: "米易县", - 510422: "盐边县", - 510500: "泸州市", - 510501: "泸州市市辖区", - 510502: "江阳区", - 510503: "纳溪区", - 510504: "龙马潭区", - 510521: "泸县", - 510522: "合江县", - 510524: "叙永县", - 510525: "古蔺县", - 510600: "德阳市", - 510601: "德阳市市辖区", - 510603: "旌阳区", - 510604: "罗江区", - 510623: "中江县", - 510681: "广汉市", - 510682: "什邡市", - 510683: "绵竹市", - 510700: "绵阳市", - 510701: "绵阳市市辖区", - 510703: "涪城区", - 510704: "游仙区", - 510705: "安州区", - 510722: "三台县", - 510723: "盐亭县", - 510725: "梓潼县", - 510726: "北川羌族自治县", - 510727: "平武县", - 510781: "江油市", - 510800: "广元市", - 510801: "广元市市辖区", - 510802: "利州区", - 510811: "昭化区", - 510812: "朝天区", - 510821: "旺苍县", - 510822: "青川县", - 510823: "剑阁县", - 510824: "苍溪县", - 510900: "遂宁市", - 510901: "遂宁市市辖区", - 510903: "船山区", - 510904: "安居区", - 510921: "蓬溪县", - 510922: "射洪县", - 510923: "大英县", - 511000: "内江市", - 511001: "内江市市辖区", - 511002: "市中区", - 511011: "东兴区", - 511024: "威远县", - 511025: "资中县", - 511083: "隆昌市", - 511100: "乐山市", - 511101: "乐山市市辖区", - 511102: "市中区", - 511111: "沙湾区", - 511112: "五通桥区", - 511113: "金口河区", - 511123: "犍为县", - 511124: "井研县", - 511126: "夹江县", - 511129: "沐川县", - 511132: "峨边彝族自治县", - 511133: "马边彝族自治县", - 511181: "峨眉山市", - 511300: "南充市", - 511301: "南充市市辖区", - 511302: "顺庆区", - 511303: "高坪区", - 511304: "嘉陵区", - 511321: "南部县", - 511322: "营山县", - 511323: "蓬安县", - 511324: "仪陇县", - 511325: "西充县", - 511381: "阆中市", - 511400: "眉山市", - 511401: "眉山市市辖区", - 511402: "东坡区", - 511403: "彭山区", - 511421: "仁寿县", - 511423: "洪雅县", - 511424: "丹棱县", - 511425: "青神县", - 511500: "宜宾市", - 511501: "宜宾市市辖区", - 511502: "翠屏区", - 511503: "南溪区", - 511504: "叙州区", - 511523: "江安县", - 511524: "长宁县", - 511525: "高县", - 511526: "珙县", - 511527: "筠连县", - 511528: "兴文县", - 511529: "屏山县", - 511600: "广安市", - 511601: "广安市市辖区", - 511602: "广安区", - 511603: "前锋区", - 511621: "岳池县", - 511622: "武胜县", - 511623: "邻水县", - 511681: "华蓥市", - 511700: "达州市", - 511701: "达州市市辖区", - 511702: "通川区", - 511703: "达川区", - 511722: "宣汉县", - 511723: "开江县", - 511724: "大竹县", - 511725: "渠县", - 511781: "万源市", - 511800: "雅安市", - 511801: "雅安市市辖区", - 511802: "雨城区", - 511803: "名山区", - 511822: "荥经县", - 511823: "汉源县", - 511824: "石棉县", - 511825: "天全县", - 511826: "芦山县", - 511827: "宝兴县", - 511900: "巴中市", - 511901: "巴中市市辖区", - 511902: "巴州区", - 511903: "恩阳区", - 511921: "通江县", - 511922: "南江县", - 511923: "平昌县", - 512000: "资阳市", - 512001: "资阳市市辖区", - 512002: "雁江区", - 512021: "安岳县", - 512022: "乐至县", - 513200: "阿坝藏族羌族自治州", - 513201: "马尔康市", - 513221: "汶川县", - 513222: "理县", - 513223: "茂县", - 513224: "松潘县", - 513225: "九寨沟县", - 513226: "金川县", - 513227: "小金县", - 513228: "黑水县", - 513230: "壤塘县", - 513231: "阿坝县", - 513232: "若尔盖县", - 513233: "红原县", - 513300: "甘孜藏族自治州", - 513301: "康定市", - 513322: "泸定县", - 513323: "丹巴县", - 513324: "九龙县", - 513325: "雅江县", - 513326: "道孚县", - 513327: "炉霍县", - 513328: "甘孜县", - 513329: "新龙县", - 513330: "德格县", - 513331: "白玉县", - 513332: "石渠县", - 513333: "色达县", - 513334: "理塘县", - 513335: "巴塘县", - 513336: "乡城县", - 513337: "稻城县", - 513338: "得荣县", - 513400: "凉山彝族自治州", - 513401: "西昌市", - 513422: "木里藏族自治县", - 513423: "盐源县", - 513424: "德昌县", - 513425: "会理县", - 513426: "会东县", - 513427: "宁南县", - 513428: "普格县", - 513429: "布拖县", - 513430: "金阳县", - 513431: "昭觉县", - 513432: "喜德县", - 513433: "冕宁县", - 513434: "越西县", - 513435: "甘洛县", - 513436: "美姑县", - 513437: "雷波县", - 520000: "贵州省", - 520100: "贵阳市", - 520101: "贵阳市市辖区", - 520102: "南明区", - 520103: "云岩区", - 520111: "花溪区", - 520112: "乌当区", - 520113: "白云区", - 520115: "观山湖区", - 520121: "开阳县", - 520122: "息烽县", - 520123: "修文县", - 520181: "清镇市", - 520200: "六盘水市", - 520201: "钟山区", - 520203: "六枝特区", - 520221: "水城县", - 520281: "盘州市", - 520300: "遵义市", - 520301: "遵义市市辖区", - 520302: "红花岗区", - 520303: "汇川区", - 520304: "播州区", - 520322: "桐梓县", - 520323: "绥阳县", - 520324: "正安县", - 520325: "道真仡佬族苗族自治县", - 520326: "务川仡佬族苗族自治县", - 520327: "凤冈县", - 520328: "湄潭县", - 520329: "余庆县", - 520330: "习水县", - 520381: "赤水市", - 520382: "仁怀市", - 520400: "安顺市", - 520401: "安顺市市辖区", - 520402: "西秀区", - 520403: "平坝区", - 520422: "普定县", - 520423: "镇宁布依族苗族自治县", - 520424: "关岭布依族苗族自治县", - 520425: "紫云苗族布依族自治县", - 520500: "毕节市", - 520502: "七星关区", - 520521: "大方县", - 520522: "黔西县", - 520523: "金沙县", - 520524: "织金县", - 520525: "纳雍县", - 520526: "威宁彝族回族苗族自治县", - 520527: "赫章县", - 520600: "铜仁市", - 520602: "碧江区", - 520603: "万山区", - 520621: "江口县", - 520622: "玉屏侗族自治县", - 520623: "石阡县", - 520624: "思南县", - 520625: "印江土家族苗族自治县", - 520626: "德江县", - 520627: "沿河土家族自治县", - 520628: "松桃苗族自治县", - 522300: "黔西南布依族苗族自治州", - 522301: "兴义市", - 522302: "兴仁市", - 522323: "普安县", - 522324: "晴隆县", - 522325: "贞丰县", - 522326: "望谟县", - 522327: "册亨县", - 522328: "安龙县", - 522600: "黔东南苗族侗族自治州", - 522601: "凯里市", - 522622: "黄平县", - 522623: "施秉县", - 522624: "三穗县", - 522625: "镇远县", - 522626: "岑巩县", - 522627: "天柱县", - 522628: "锦屏县", - 522629: "剑河县", - 522630: "台江县", - 522631: "黎平县", - 522632: "榕江县", - 522633: "从江县", - 522634: "雷山县", - 522635: "麻江县", - 522636: "丹寨县", - 522700: "黔南布依族苗族自治州", - 522701: "都匀市", - 522702: "福泉市", - 522722: "荔波县", - 522723: "贵定县", - 522725: "瓮安县", - 522726: "独山县", - 522727: "平塘县", - 522728: "罗甸县", - 522729: "长顺县", - 522730: "龙里县", - 522731: "惠水县", - 522732: "三都水族自治县", - 530000: "云南省", - 530100: "昆明市", - 530101: "昆明市市辖区", - 530102: "五华区", - 530103: "盘龙区", - 530111: "官渡区", - 530112: "西山区", - 530113: "东川区", - 530114: "呈贡区", - 530115: "晋宁区", - 530124: "富民县", - 530125: "宜良县", - 530126: "石林彝族自治县", - 530127: "嵩明县", - 530128: "禄劝彝族苗族自治县", - 530129: "寻甸回族彝族自治县", - 530181: "安宁市", - 530300: "曲靖市", - 530301: "曲靖市市辖区", - 530302: "麒麟区", - 530303: "沾益区", - 530304: "马龙区", - 530322: "陆良县", - 530323: "师宗县", - 530324: "罗平县", - 530325: "富源县", - 530326: "会泽县", - 530381: "宣威市", - 530400: "玉溪市", - 530401: "玉溪市市辖区", - 530402: "红塔区", - 530403: "江川区", - 530422: "澄江县", - 530423: "通海县", - 530424: "华宁县", - 530425: "易门县", - 530426: "峨山彝族自治县", - 530427: "新平彝族傣族自治县", - 530428: "元江哈尼族彝族傣族自治县", - 530500: "保山市", - 530501: "保山市市辖区", - 530502: "隆阳区", - 530521: "施甸县", - 530523: "龙陵县", - 530524: "昌宁县", - 530581: "腾冲市", - 530600: "昭通市", - 530601: "昭通市市辖区", - 530602: "昭阳区", - 530621: "鲁甸县", - 530622: "巧家县", - 530623: "盐津县", - 530624: "大关县", - 530625: "永善县", - 530626: "绥江县", - 530627: "镇雄县", - 530628: "彝良县", - 530629: "威信县", - 530681: "水富市", - 530700: "丽江市", - 530701: "丽江市市辖区", - 530702: "古城区", - 530721: "玉龙纳西族自治县", - 530722: "永胜县", - 530723: "华坪县", - 530724: "宁蒗彝族自治县", - 530800: "普洱市", - 530801: "普洱市市辖区", - 530802: "思茅区", - 530821: "宁洱哈尼族彝族自治县", - 530822: "墨江哈尼族自治县", - 530823: "景东彝族自治县", - 530824: "景谷傣族彝族自治县", - 530825: "镇沅彝族哈尼族拉祜族自治县", - 530826: "江城哈尼族彝族自治县", - 530827: "孟连傣族拉祜族佤族自治县", - 530828: "澜沧拉祜族自治县", - 530829: "西盟佤族自治县", - 530900: "临沧市", - 530901: "临沧市市辖区", - 530902: "临翔区", - 530921: "凤庆县", - 530922: "云县", - 530923: "永德县", - 530924: "镇康县", - 530925: "双江拉祜族佤族布朗族傣族自治县", - 530926: "耿马傣族佤族自治县", - 530927: "沧源佤族自治县", - 532300: "楚雄彝族自治州", - 532301: "楚雄市", - 532322: "双柏县", - 532323: "牟定县", - 532324: "南华县", - 532325: "姚安县", - 532326: "大姚县", - 532327: "永仁县", - 532328: "元谋县", - 532329: "武定县", - 532331: "禄丰县", - 532500: "红河哈尼族彝族自治州", - 532501: "个旧市", - 532502: "开远市", - 532503: "蒙自市", - 532504: "弥勒市", - 532523: "屏边苗族自治县", - 532524: "建水县", - 532525: "石屏县", - 532527: "泸西县", - 532528: "元阳县", - 532529: "红河县", - 532530: "金平苗族瑶族傣族自治县", - 532531: "绿春县", - 532532: "河口瑶族自治县", - 532600: "文山壮族苗族自治州", - 532601: "文山市", - 532622: "砚山县", - 532623: "西畴县", - 532624: "麻栗坡县", - 532625: "马关县", - 532626: "丘北县", - 532627: "广南县", - 532628: "富宁县", - 532800: "西双版纳傣族自治州", - 532801: "景洪市", - 532822: "勐海县", - 532823: "勐腊县", - 532900: "大理白族自治州", - 532901: "大理市", - 532922: "漾濞彝族自治县", - 532923: "祥云县", - 532924: "宾川县", - 532925: "弥渡县", - 532926: "南涧彝族自治县", - 532927: "巍山彝族回族自治县", - 532928: "永平县", - 532929: "云龙县", - 532930: "洱源县", - 532931: "剑川县", - 532932: "鹤庆县", - 533100: "德宏傣族景颇族自治州", - 533102: "瑞丽市", - 533103: "芒市", - 533122: "梁河县", - 533123: "盈江县", - 533124: "陇川县", - 533300: "怒江傈僳族自治州", - 533301: "泸水市", - 533323: "福贡县", - 533324: "贡山独龙族怒族自治县", - 533325: "兰坪白族普米族自治县", - 533400: "迪庆藏族自治州", - 533401: "香格里拉市", - 533422: "德钦县", - 533423: "维西傈僳族自治县", - 540000: "西藏自治区", - 540100: "拉萨市", - 540101: "拉萨市市辖区", - 540102: "城关区", - 540103: "堆龙德庆区", - 540104: "达孜区", - 540121: "林周县", - 540122: "当雄县", - 540123: "尼木县", - 540124: "曲水县", - 540127: "墨竹工卡县", - 540200: "日喀则市", - 540202: "桑珠孜区", - 540221: "南木林县", - 540222: "江孜县", - 540223: "定日县", - 540224: "萨迦县", - 540225: "拉孜县", - 540226: "昂仁县", - 540227: "谢通门县", - 540228: "白朗县", - 540229: "仁布县", - 540230: "康马县", - 540231: "定结县", - 540232: "仲巴县", - 540233: "亚东县", - 540234: "吉隆县", - 540235: "聂拉木县", - 540236: "萨嘎县", - 540237: "岗巴县", - 540300: "昌都市", - 540302: "卡若区", - 540321: "江达县", - 540322: "贡觉县", - 540323: "类乌齐县", - 540324: "丁青县", - 540325: "察雅县", - 540326: "八宿县", - 540327: "左贡县", - 540328: "芒康县", - 540329: "洛隆县", - 540330: "边坝县", - 540400: "林芝市", - 540402: "巴宜区", - 540421: "工布江达县", - 540422: "米林县", - 540423: "墨脱县", - 540424: "波密县", - 540425: "察隅县", - 540426: "朗县", - 540500: "山南市", - 540502: "乃东区", - 540521: "扎囊县", - 540522: "贡嘎县", - 540523: "桑日县", - 540524: "琼结县", - 540525: "曲松县", - 540526: "措美县", - 540527: "洛扎县", - 540528: "加查县", - 540529: "隆子县", - 540530: "错那县", - 540531: "浪卡子县", - 540600: "那曲市", - 540602: "色尼区", - 540621: "嘉黎县", - 540622: "比如县", - 540623: "聂荣县", - 540624: "安多县", - 540625: "申扎县", - 540626: "索县", - 540627: "班戈县", - 540628: "巴青县", - 540629: "尼玛县", - 540630: "双湖县", - 542500: "阿里地区", - 542521: "普兰县", - 542522: "札达县", - 542523: "噶尔县", - 542524: "日土县", - 542525: "革吉县", - 542526: "改则县", - 542527: "措勤县", - 610000: "陕西省", - 610100: "西安市", - 610101: "西安市市辖区", - 610102: "新城区", - 610103: "碑林区", - 610104: "莲湖区", - 610111: "灞桥区", - 610112: "未央区", - 610113: "雁塔区", - 610114: "阎良区", - 610115: "临潼区", - 610116: "长安区", - 610117: "高陵区", - 610118: "鄠邑区", - 610122: "蓝田县", - 610124: "周至县", - 610200: "铜川市", - 610201: "铜川市市辖区", - 610202: "王益区", - 610203: "印台区", - 610204: "耀州区", - 610222: "宜君县", - 610300: "宝鸡市", - 610301: "宝鸡市市辖区", - 610302: "渭滨区", - 610303: "金台区", - 610304: "陈仓区", - 610322: "凤翔县", - 610323: "岐山县", - 610324: "扶风县", - 610326: "眉县", - 610327: "陇县", - 610328: "千阳县", - 610329: "麟游县", - 610330: "凤县", - 610331: "太白县", - 610400: "咸阳市", - 610401: "咸阳市市辖区", - 610402: "秦都区", - 610403: "杨陵区", - 610404: "渭城区", - 610422: "三原县", - 610423: "泾阳县", - 610424: "乾县", - 610425: "礼泉县", - 610426: "永寿县", - 610428: "长武县", - 610429: "旬邑县", - 610430: "淳化县", - 610431: "武功县", - 610481: "兴平市", - 610482: "彬州市", - 610500: "渭南市", - 610501: "渭南市市辖区", - 610502: "临渭区", - 610503: "华州区", - 610522: "潼关县", - 610523: "大荔县", - 610524: "合阳县", - 610525: "澄城县", - 610526: "蒲城县", - 610527: "白水县", - 610528: "富平县", - 610581: "韩城市", - 610582: "华阴市", - 610600: "延安市", - 610601: "延安市市辖区", - 610602: "宝塔区", - 610603: "安塞区", - 610621: "延长县", - 610622: "延川县", - 610623: "子长县", - 610625: "志丹县", - 610626: "吴起县", - 610627: "甘泉县", - 610628: "富县", - 610629: "洛川县", - 610630: "宜川县", - 610631: "黄龙县", - 610632: "黄陵县", - 610700: "汉中市", - 610701: "汉中市市辖区", - 610702: "汉台区", - 610703: "南郑区", - 610722: "城固县", - 610723: "洋县", - 610724: "西乡县", - 610725: "勉县", - 610726: "宁强县", - 610727: "略阳县", - 610728: "镇巴县", - 610729: "留坝县", - 610730: "佛坪县", - 610800: "榆林市", - 610801: "榆林市市辖区", - 610802: "榆阳区", - 610803: "横山区", - 610822: "府谷县", - 610824: "靖边县", - 610825: "定边县", - 610826: "绥德县", - 610827: "米脂县", - 610828: "佳县", - 610829: "吴堡县", - 610830: "清涧县", - 610831: "子洲县", - 610881: "神木市", - 610900: "安康市", - 610901: "安康市市辖区", - 610902: "汉滨区", - 610921: "汉阴县", - 610922: "石泉县", - 610923: "宁陕县", - 610924: "紫阳县", - 610925: "岚皋县", - 610926: "平利县", - 610927: "镇坪县", - 610928: "旬阳县", - 610929: "白河县", - 611000: "商洛市", - 611001: "商洛市市辖区", - 611002: "商州区", - 611021: "洛南县", - 611022: "丹凤县", - 611023: "商南县", - 611024: "山阳县", - 611025: "镇安县", - 611026: "柞水县", - 620000: "甘肃省", - 620100: "兰州市", - 620101: "兰州市市辖区", - 620102: "城关区", - 620103: "七里河区", - 620104: "西固区", - 620105: "安宁区", - 620111: "红古区", - 620121: "永登县", - 620122: "皋兰县", - 620123: "榆中县", - 620200: "嘉峪关市", - 620201: "嘉峪关市市辖区", - 620300: "金昌市", - 620301: "金昌市市辖区", - 620302: "金川区", - 620321: "永昌县", - 620400: "白银市", - 620401: "白银市市辖区", - 620402: "白银区", - 620403: "平川区", - 620421: "靖远县", - 620422: "会宁县", - 620423: "景泰县", - 620500: "天水市", - 620501: "天水市市辖区", - 620502: "秦州区", - 620503: "麦积区", - 620521: "清水县", - 620522: "秦安县", - 620523: "甘谷县", - 620524: "武山县", - 620525: "张家川回族自治县", - 620600: "武威市", - 620601: "武威市市辖区", - 620602: "凉州区", - 620621: "民勤县", - 620622: "古浪县", - 620623: "天祝藏族自治县", - 620700: "张掖市", - 620701: "张掖市市辖区", - 620702: "甘州区", - 620721: "肃南裕固族自治县", - 620722: "民乐县", - 620723: "临泽县", - 620724: "高台县", - 620725: "山丹县", - 620800: "平凉市", - 620801: "平凉市市辖区", - 620802: "崆峒区", - 620821: "泾川县", - 620822: "灵台县", - 620823: "崇信县", - 620825: "庄浪县", - 620826: "静宁县", - 620881: "华亭市", - 620900: "酒泉市", - 620901: "酒泉市市辖区", - 620902: "肃州区", - 620921: "金塔县", - 620922: "瓜州县", - 620923: "肃北蒙古族自治县", - 620924: "阿克塞哈萨克族自治县", - 620981: "玉门市", - 620982: "敦煌市", - 621000: "庆阳市", - 621001: "庆阳市市辖区", - 621002: "西峰区", - 621021: "庆城县", - 621022: "环县", - 621023: "华池县", - 621024: "合水县", - 621025: "正宁县", - 621026: "宁县", - 621027: "镇原县", - 621100: "定西市", - 621101: "定西市市辖区", - 621102: "安定区", - 621121: "通渭县", - 621122: "陇西县", - 621123: "渭源县", - 621124: "临洮县", - 621125: "漳县", - 621126: "岷县", - 621200: "陇南市", - 621201: "陇南市市辖区", - 621202: "武都区", - 621221: "成县", - 621222: "文县", - 621223: "宕昌县", - 621224: "康县", - 621225: "西和县", - 621226: "礼县", - 621227: "徽县", - 621228: "两当县", - 622900: "临夏回族自治州", - 622901: "临夏市", - 622921: "临夏县", - 622922: "康乐县", - 622923: "永靖县", - 622924: "广河县", - 622925: "和政县", - 622926: "东乡族自治县", - 622927: "积石山保安族东乡族撒拉族自治县", - 623000: "甘南藏族自治州", - 623001: "合作市", - 623021: "临潭县", - 623022: "卓尼县", - 623023: "舟曲县", - 623024: "迭部县", - 623025: "玛曲县", - 623026: "碌曲县", - 623027: "夏河县", - 630000: "青海省", - 630100: "西宁市", - 630101: "西宁市市辖区", - 630102: "城东区", - 630103: "城中区", - 630104: "城西区", - 630105: "城北区", - 630121: "大通回族土族自治县", - 630122: "湟中县", - 630123: "湟源县", - 630200: "海东市", - 630202: "乐都区", - 630203: "平安区", - 630222: "民和回族土族自治县", - 630223: "互助土族自治县", - 630224: "化隆回族自治县", - 630225: "循化撒拉族自治县", - 632200: "海北藏族自治州", - 632221: "门源回族自治县", - 632222: "祁连县", - 632223: "海晏县", - 632224: "刚察县", - 632300: "黄南藏族自治州", - 632321: "同仁县", - 632322: "尖扎县", - 632323: "泽库县", - 632324: "河南蒙古族自治县", - 632500: "海南藏族自治州", - 632521: "共和县", - 632522: "同德县", - 632523: "贵德县", - 632524: "兴海县", - 632525: "贵南县", - 632600: "果洛藏族自治州", - 632621: "玛沁县", - 632622: "班玛县", - 632623: "甘德县", - 632624: "达日县", - 632625: "久治县", - 632626: "玛多县", - 632700: "玉树藏族自治州", - 632701: "玉树市", - 632722: "杂多县", - 632723: "称多县", - 632724: "治多县", - 632725: "囊谦县", - 632726: "曲麻莱县", - 632800: "海西蒙古族藏族自治州", - 632801: "格尔木市", - 632802: "德令哈市", - 632803: "茫崖市", - 632821: "乌兰县", - 632822: "都兰县", - 632823: "天峻县", - 632825: "海西蒙古族藏族自治州直辖", - 640000: "宁夏回族自治区", - 640100: "银川市", - 640101: "银川市市辖区", - 640104: "兴庆区", - 640105: "西夏区", - 640106: "金凤区", - 640121: "永宁县", - 640122: "贺兰县", - 640181: "灵武市", - 640200: "石嘴山市", - 640201: "石嘴山市市辖区", - 640202: "大武口区", - 640205: "惠农区", - 640221: "平罗县", - 640300: "吴忠市", - 640301: "吴忠市市辖区", - 640302: "利通区", - 640303: "红寺堡区", - 640323: "盐池县", - 640324: "同心县", - 640381: "青铜峡市", - 640400: "固原市", - 640401: "固原市市辖区", - 640402: "原州区", - 640422: "西吉县", - 640423: "隆德县", - 640424: "泾源县", - 640425: "彭阳县", - 640500: "中卫市", - 640501: "中卫市市辖区", - 640502: "沙坡头区", - 640521: "中宁县", - 640522: "海原县", - 650000: "新疆维吾尔自治区", - 650100: "乌鲁木齐市", - 650101: "乌鲁木齐市市辖区", - 650102: "天山区", - 650103: "沙依巴克区", - 650104: "新市区", - 650105: "水磨沟区", - 650106: "头屯河区", - 650107: "达坂城区", - 650109: "米东区", - 650121: "乌鲁木齐县", - 650200: "克拉玛依市", - 650201: "克拉玛依市市辖区", - 650202: "独山子区", - 650203: "克拉玛依区", - 650204: "白碱滩区", - 650205: "乌尔禾区", - 650400: "吐鲁番市", - 650402: "高昌区", - 650421: "鄯善县", - 650422: "托克逊县", - 650500: "哈密市", - 650502: "伊州区", - 650521: "巴里坤哈萨克自治县", - 650522: "伊吾县", - 652300: "昌吉回族自治州", - 652301: "昌吉市", - 652302: "阜康市", - 652323: "呼图壁县", - 652324: "玛纳斯县", - 652325: "奇台县", - 652327: "吉木萨尔县", - 652328: "木垒哈萨克自治县", - 652700: "博尔塔拉蒙古自治州", - 652701: "博乐市", - 652702: "阿拉山口市", - 652722: "精河县", - 652723: "温泉县", - 652800: "巴音郭楞蒙古自治州", - 652801: "库尔勒市", - 652822: "轮台县", - 652823: "尉犁县", - 652824: "若羌县", - 652825: "且末县", - 652826: "焉耆回族自治县", - 652827: "和静县", - 652828: "和硕县", - 652829: "博湖县", - 652900: "阿克苏地区", - 652901: "阿克苏市", - 652922: "温宿县", - 652923: "库车县", - 652924: "沙雅县", - 652925: "新和县", - 652926: "拜城县", - 652927: "乌什县", - 652928: "阿瓦提县", - 652929: "柯坪县", - 653000: "克孜勒苏柯尔克孜自治州", - 653001: "阿图什市", - 653022: "阿克陶县", - 653023: "阿合奇县", - 653024: "乌恰县", - 653100: "喀什地区", - 653101: "喀什市", - 653121: "疏附县", - 653122: "疏勒县", - 653123: "英吉沙县", - 653124: "泽普县", - 653125: "莎车县", - 653126: "叶城县", - 653127: "麦盖提县", - 653128: "岳普湖县", - 653129: "伽师县", - 653130: "巴楚县", - 653131: "塔什库尔干塔吉克自治县", - 653200: "和田地区", - 653201: "和田市", - 653221: "和田县", - 653222: "墨玉县", - 653223: "皮山县", - 653224: "洛浦县", - 653225: "策勒县", - 653226: "于田县", - 653227: "民丰县", - 654000: "伊犁哈萨克自治州", - 654002: "伊宁市", - 654003: "奎屯市", - 654004: "霍尔果斯市", - 654021: "伊宁县", - 654022: "察布查尔锡伯自治县", - 654023: "霍城县", - 654024: "巩留县", - 654025: "新源县", - 654026: "昭苏县", - 654027: "特克斯县", - 654028: "尼勒克县", - 654200: "塔城地区", - 654201: "塔城市", - 654202: "乌苏市", - 654221: "额敏县", - 654223: "沙湾县", - 654224: "托里县", - 654225: "裕民县", - 654226: "和布克赛尔蒙古自治县", - 654300: "阿勒泰地区", - 654301: "阿勒泰市", - 654321: "布尔津县", - 654322: "富蕴县", - 654323: "福海县", - 654324: "哈巴河县", - 654325: "青河县", - 654326: "吉木乃县", - 659001: "石河子市", - 659002: "阿拉尔市", - 659003: "图木舒克市", - 659004: "五家渠市", - 659005: "北屯市", - 659006: "铁门关市", - 659007: "双河市", - 659008: "可克达拉市", - 659009: "昆玉市", - 710000: "台湾省", - 810000: "香港特别行政区", - 810001: "中西区", - 810002: "湾仔区", - 810003: "东区", - 810004: "南区", - 810005: "油尖旺区", - 810006: "深水埗区", - 810007: "九龙城区", - 810008: "黄大仙区", - 810009: "观塘区", - 810010: "荃湾区", - 810011: "屯门区", - 810012: "元朗区", - 810013: "北区", - 810014: "大埔区", - 810015: "西贡区", - 810016: "沙田区", - 810017: "葵青区", - 810018: "离岛区", - 820000: "澳门特别行政区", - 820001: "花地玛堂区", - 820002: "花王堂区", - 820003: "望德堂区", - 820004: "大堂区", - 820005: "风顺堂区", - 820006: "嘉模堂区", - 820007: "路凼填海区", - 820008: "圣方济各堂区" + 110000: '北京市', + 110100: '北京市市辖区', + 110101: '东城区', + 110102: '西城区', + 110105: '朝阳区', + 110106: '丰台区', + 110107: '石景山区', + 110108: '海淀区', + 110109: '门头沟区', + 110111: '房山区', + 110112: '通州区', + 110113: '顺义区', + 110114: '昌平区', + 110115: '大兴区', + 110116: '怀柔区', + 110117: '平谷区', + 110118: '密云区', + 110119: '延庆区', + 120000: '天津市', + 120100: '天津市市辖区', + 120101: '和平区', + 120102: '河东区', + 120103: '河西区', + 120104: '南开区', + 120105: '河北区', + 120106: '红桥区', + 120110: '东丽区', + 120111: '西青区', + 120112: '津南区', + 120113: '北辰区', + 120114: '武清区', + 120115: '宝坻区', + 120116: '滨海新区', + 120117: '宁河区', + 120118: '静海区', + 120119: '蓟州区', + 130000: '河北省', + 130100: '石家庄市', + 130101: '石家庄市市辖区', + 130102: '长安区', + 130104: '桥西区', + 130105: '新华区', + 130107: '井陉矿区', + 130108: '裕华区', + 130109: '藁城区', + 130110: '鹿泉区', + 130111: '栾城区', + 130121: '井陉县', + 130123: '正定县', + 130125: '行唐县', + 130126: '灵寿县', + 130127: '高邑县', + 130128: '深泽县', + 130129: '赞皇县', + 130130: '无极县', + 130131: '平山县', + 130132: '元氏县', + 130133: '赵县', + 130181: '辛集市', + 130183: '晋州市', + 130184: '新乐市', + 130200: '唐山市', + 130201: '唐山市市辖区', + 130202: '路南区', + 130203: '路北区', + 130204: '古冶区', + 130205: '开平区', + 130207: '丰南区', + 130208: '丰润区', + 130209: '曹妃甸区', + 130224: '滦南县', + 130225: '乐亭县', + 130227: '迁西县', + 130229: '玉田县', + 130281: '遵化市', + 130283: '迁安市', + 130284: '滦州市', + 130300: '秦皇岛市', + 130301: '秦皇岛市市辖区', + 130302: '海港区', + 130303: '山海关区', + 130304: '北戴河区', + 130306: '抚宁区', + 130321: '青龙满族自治县', + 130322: '昌黎县', + 130324: '卢龙县', + 130400: '邯郸市', + 130401: '邯郸市市辖区', + 130402: '邯山区', + 130403: '丛台区', + 130404: '复兴区', + 130406: '峰峰矿区', + 130407: '肥乡区', + 130408: '永年区', + 130423: '临漳县', + 130424: '成安县', + 130425: '大名县', + 130426: '涉县', + 130427: '磁县', + 130430: '邱县', + 130431: '鸡泽县', + 130432: '广平县', + 130433: '馆陶县', + 130434: '魏县', + 130435: '曲周县', + 130481: '武安市', + 130500: '邢台市', + 130501: '邢台市市辖区', + 130502: '桥东区', + 130503: '桥西区', + 130521: '邢台县', + 130522: '临城县', + 130523: '内丘县', + 130524: '柏乡县', + 130525: '隆尧县', + 130526: '任县', + 130527: '南和县', + 130528: '宁晋县', + 130529: '巨鹿县', + 130530: '新河县', + 130531: '广宗县', + 130532: '平乡县', + 130533: '威县', + 130534: '清河县', + 130535: '临西县', + 130581: '南宫市', + 130582: '沙河市', + 130600: '保定市', + 130601: '保定市市辖区', + 130602: '竞秀区', + 130606: '莲池区', + 130607: '满城区', + 130608: '清苑区', + 130609: '徐水区', + 130623: '涞水县', + 130624: '阜平县', + 130626: '定兴县', + 130627: '唐县', + 130628: '高阳县', + 130629: '容城县', + 130630: '涞源县', + 130631: '望都县', + 130632: '安新县', + 130633: '易县', + 130634: '曲阳县', + 130635: '蠡县', + 130636: '顺平县', + 130637: '博野县', + 130638: '雄县', + 130681: '涿州市', + 130682: '定州市', + 130683: '安国市', + 130684: '高碑店市', + 130700: '张家口市', + 130701: '张家口市市辖区', + 130702: '桥东区', + 130703: '桥西区', + 130705: '宣化区', + 130706: '下花园区', + 130708: '万全区', + 130709: '崇礼区', + 130722: '张北县', + 130723: '康保县', + 130724: '沽源县', + 130725: '尚义县', + 130726: '蔚县', + 130727: '阳原县', + 130728: '怀安县', + 130730: '怀来县', + 130731: '涿鹿县', + 130732: '赤城县', + 130800: '承德市', + 130801: '承德市市辖区', + 130802: '双桥区', + 130803: '双滦区', + 130804: '鹰手营子矿区', + 130821: '承德县', + 130822: '兴隆县', + 130824: '滦平县', + 130825: '隆化县', + 130826: '丰宁满族自治县', + 130827: '宽城满族自治县', + 130828: '围场满族蒙古族自治县', + 130881: '平泉市', + 130900: '沧州市', + 130901: '沧州市市辖区', + 130902: '新华区', + 130903: '运河区', + 130921: '沧县', + 130922: '青县', + 130923: '东光县', + 130924: '海兴县', + 130925: '盐山县', + 130926: '肃宁县', + 130927: '南皮县', + 130928: '吴桥县', + 130929: '献县', + 130930: '孟村回族自治县', + 130981: '泊头市', + 130982: '任丘市', + 130983: '黄骅市', + 130984: '河间市', + 131000: '廊坊市', + 131001: '廊坊市市辖区', + 131002: '安次区', + 131003: '广阳区', + 131022: '固安县', + 131023: '永清县', + 131024: '香河县', + 131025: '大城县', + 131026: '文安县', + 131028: '大厂回族自治县', + 131081: '霸州市', + 131082: '三河市', + 131100: '衡水市', + 131101: '衡水市市辖区', + 131102: '桃城区', + 131103: '冀州区', + 131121: '枣强县', + 131122: '武邑县', + 131123: '武强县', + 131124: '饶阳县', + 131125: '安平县', + 131126: '故城县', + 131127: '景县', + 131128: '阜城县', + 131182: '深州市', + 140000: '山西省', + 140100: '太原市', + 140101: '太原市市辖区', + 140105: '小店区', + 140106: '迎泽区', + 140107: '杏花岭区', + 140108: '尖草坪区', + 140109: '万柏林区', + 140110: '晋源区', + 140121: '清徐县', + 140122: '阳曲县', + 140123: '娄烦县', + 140181: '古交市', + 140200: '大同市', + 140201: '大同市市辖区', + 140212: '新荣区', + 140213: '平城区', + 140214: '云冈区', + 140215: '云州区', + 140221: '阳高县', + 140222: '天镇县', + 140223: '广灵县', + 140224: '灵丘县', + 140225: '浑源县', + 140226: '左云县', + 140300: '阳泉市', + 140301: '阳泉市市辖区', + 140302: '城区', + 140303: '矿区', + 140311: '郊区', + 140321: '平定县', + 140322: '盂县', + 140400: '长治市', + 140401: '长治市市辖区', + 140403: '潞州区', + 140404: '上党区', + 140405: '屯留区', + 140406: '潞城区', + 140423: '襄垣县', + 140425: '平顺县', + 140426: '黎城县', + 140427: '壶关县', + 140428: '长子县', + 140429: '武乡县', + 140430: '沁县', + 140431: '沁源县', + 140500: '晋城市', + 140501: '晋城市市辖区', + 140502: '城区', + 140521: '沁水县', + 140522: '阳城县', + 140524: '陵川县', + 140525: '泽州县', + 140581: '高平市', + 140600: '朔州市', + 140601: '朔州市市辖区', + 140602: '朔城区', + 140603: '平鲁区', + 140621: '山阴县', + 140622: '应县', + 140623: '右玉县', + 140681: '怀仁市', + 140700: '晋中市', + 140701: '晋中市市辖区', + 140702: '榆次区', + 140721: '榆社县', + 140722: '左权县', + 140723: '和顺县', + 140724: '昔阳县', + 140725: '寿阳县', + 140726: '太谷县', + 140727: '祁县', + 140728: '平遥县', + 140729: '灵石县', + 140781: '介休市', + 140800: '运城市', + 140801: '运城市市辖区', + 140802: '盐湖区', + 140821: '临猗县', + 140822: '万荣县', + 140823: '闻喜县', + 140824: '稷山县', + 140825: '新绛县', + 140826: '绛县', + 140827: '垣曲县', + 140828: '夏县', + 140829: '平陆县', + 140830: '芮城县', + 140881: '永济市', + 140882: '河津市', + 140900: '忻州市', + 140901: '忻州市市辖区', + 140902: '忻府区', + 140921: '定襄县', + 140922: '五台县', + 140923: '代县', + 140924: '繁峙县', + 140925: '宁武县', + 140926: '静乐县', + 140927: '神池县', + 140928: '五寨县', + 140929: '岢岚县', + 140930: '河曲县', + 140931: '保德县', + 140932: '偏关县', + 140981: '原平市', + 141000: '临汾市', + 141001: '临汾市市辖区', + 141002: '尧都区', + 141021: '曲沃县', + 141022: '翼城县', + 141023: '襄汾县', + 141024: '洪洞县', + 141025: '古县', + 141026: '安泽县', + 141027: '浮山县', + 141028: '吉县', + 141029: '乡宁县', + 141030: '大宁县', + 141031: '隰县', + 141032: '永和县', + 141033: '蒲县', + 141034: '汾西县', + 141081: '侯马市', + 141082: '霍州市', + 141100: '吕梁市', + 141101: '吕梁市市辖区', + 141102: '离石区', + 141121: '文水县', + 141122: '交城县', + 141123: '兴县', + 141124: '临县', + 141125: '柳林县', + 141126: '石楼县', + 141127: '岚县', + 141128: '方山县', + 141129: '中阳县', + 141130: '交口县', + 141181: '孝义市', + 141182: '汾阳市', + 150000: '内蒙古自治区', + 150100: '呼和浩特市', + 150101: '呼和浩特市市辖区', + 150102: '新城区', + 150103: '回民区', + 150104: '玉泉区', + 150105: '赛罕区', + 150121: '土默特左旗', + 150122: '托克托县', + 150123: '和林格尔县', + 150124: '清水河县', + 150125: '武川县', + 150200: '包头市', + 150201: '包头市市辖区', + 150202: '东河区', + 150203: '昆都仑区', + 150204: '青山区', + 150205: '石拐区', + 150206: '白云鄂博矿区', + 150207: '九原区', + 150221: '土默特右旗', + 150222: '固阳县', + 150223: '达尔罕茂明安联合旗', + 150300: '乌海市', + 150301: '乌海市市辖区', + 150302: '海勃湾区', + 150303: '海南区', + 150304: '乌达区', + 150400: '赤峰市', + 150401: '赤峰市市辖区', + 150402: '红山区', + 150403: '元宝山区', + 150404: '松山区', + 150421: '阿鲁科尔沁旗', + 150422: '巴林左旗', + 150423: '巴林右旗', + 150424: '林西县', + 150425: '克什克腾旗', + 150426: '翁牛特旗', + 150428: '喀喇沁旗', + 150429: '宁城县', + 150430: '敖汉旗', + 150500: '通辽市', + 150501: '通辽市市辖区', + 150502: '科尔沁区', + 150521: '科尔沁左翼中旗', + 150522: '科尔沁左翼后旗', + 150523: '开鲁县', + 150524: '库伦旗', + 150525: '奈曼旗', + 150526: '扎鲁特旗', + 150581: '霍林郭勒市', + 150600: '鄂尔多斯市', + 150601: '鄂尔多斯市市辖区', + 150602: '东胜区', + 150603: '康巴什区', + 150621: '达拉特旗', + 150622: '准格尔旗', + 150623: '鄂托克前旗', + 150624: '鄂托克旗', + 150625: '杭锦旗', + 150626: '乌审旗', + 150627: '伊金霍洛旗', + 150700: '呼伦贝尔市', + 150701: '呼伦贝尔市市辖区', + 150702: '海拉尔区', + 150703: '扎赉诺尔区', + 150721: '阿荣旗', + 150722: '莫力达瓦达斡尔族自治旗', + 150723: '鄂伦春自治旗', + 150724: '鄂温克族自治旗', + 150725: '陈巴尔虎旗', + 150726: '新巴尔虎左旗', + 150727: '新巴尔虎右旗', + 150781: '满洲里市', + 150782: '牙克石市', + 150783: '扎兰屯市', + 150784: '额尔古纳市', + 150785: '根河市', + 150800: '巴彦淖尔市', + 150801: '巴彦淖尔市市辖区', + 150802: '临河区', + 150821: '五原县', + 150822: '磴口县', + 150823: '乌拉特前旗', + 150824: '乌拉特中旗', + 150825: '乌拉特后旗', + 150826: '杭锦后旗', + 150900: '乌兰察布市', + 150901: '乌兰察布市市辖区', + 150902: '集宁区', + 150921: '卓资县', + 150922: '化德县', + 150923: '商都县', + 150924: '兴和县', + 150925: '凉城县', + 150926: '察哈尔右翼前旗', + 150927: '察哈尔右翼中旗', + 150928: '察哈尔右翼后旗', + 150929: '四子王旗', + 150981: '丰镇市', + 152200: '兴安盟', + 152201: '乌兰浩特市', + 152202: '阿尔山市', + 152221: '科尔沁右翼前旗', + 152222: '科尔沁右翼中旗', + 152223: '扎赉特旗', + 152224: '突泉县', + 152500: '锡林郭勒盟', + 152501: '二连浩特市', + 152502: '锡林浩特市', + 152522: '阿巴嘎旗', + 152523: '苏尼特左旗', + 152524: '苏尼特右旗', + 152525: '东乌珠穆沁旗', + 152526: '西乌珠穆沁旗', + 152527: '太仆寺旗', + 152528: '镶黄旗', + 152529: '正镶白旗', + 152530: '正蓝旗', + 152531: '多伦县', + 152900: '阿拉善盟', + 152921: '阿拉善左旗', + 152922: '阿拉善右旗', + 152923: '额济纳旗', + 210000: '辽宁省', + 210100: '沈阳市', + 210101: '沈阳市市辖区', + 210102: '和平区', + 210103: '沈河区', + 210104: '大东区', + 210105: '皇姑区', + 210106: '铁西区', + 210111: '苏家屯区', + 210112: '浑南区', + 210113: '沈北新区', + 210114: '于洪区', + 210115: '辽中区', + 210123: '康平县', + 210124: '法库县', + 210181: '新民市', + 210200: '大连市', + 210201: '大连市市辖区', + 210202: '中山区', + 210203: '西岗区', + 210204: '沙河口区', + 210211: '甘井子区', + 210212: '旅顺口区', + 210213: '金州区', + 210214: '普兰店区', + 210224: '长海县', + 210281: '瓦房店市', + 210283: '庄河市', + 210300: '鞍山市', + 210301: '鞍山市市辖区', + 210302: '铁东区', + 210303: '铁西区', + 210304: '立山区', + 210311: '千山区', + 210321: '台安县', + 210323: '岫岩满族自治县', + 210381: '海城市', + 210400: '抚顺市', + 210401: '抚顺市市辖区', + 210402: '新抚区', + 210403: '东洲区', + 210404: '望花区', + 210411: '顺城区', + 210421: '抚顺县', + 210422: '新宾满族自治县', + 210423: '清原满族自治县', + 210500: '本溪市', + 210501: '本溪市市辖区', + 210502: '平山区', + 210503: '溪湖区', + 210504: '明山区', + 210505: '南芬区', + 210521: '本溪满族自治县', + 210522: '桓仁满族自治县', + 210600: '丹东市', + 210601: '丹东市市辖区', + 210602: '元宝区', + 210603: '振兴区', + 210604: '振安区', + 210624: '宽甸满族自治县', + 210681: '东港市', + 210682: '凤城市', + 210700: '锦州市', + 210701: '锦州市市辖区', + 210702: '古塔区', + 210703: '凌河区', + 210711: '太和区', + 210726: '黑山县', + 210727: '义县', + 210781: '凌海市', + 210782: '北镇市', + 210800: '营口市', + 210801: '营口市市辖区', + 210802: '站前区', + 210803: '西市区', + 210804: '鲅鱼圈区', + 210811: '老边区', + 210881: '盖州市', + 210882: '大石桥市', + 210900: '阜新市', + 210901: '阜新市市辖区', + 210902: '海州区', + 210903: '新邱区', + 210904: '太平区', + 210905: '清河门区', + 210911: '细河区', + 210921: '阜新蒙古族自治县', + 210922: '彰武县', + 211000: '辽阳市', + 211001: '辽阳市市辖区', + 211002: '白塔区', + 211003: '文圣区', + 211004: '宏伟区', + 211005: '弓长岭区', + 211011: '太子河区', + 211021: '辽阳县', + 211081: '灯塔市', + 211100: '盘锦市', + 211101: '盘锦市市辖区', + 211102: '双台子区', + 211103: '兴隆台区', + 211104: '大洼区', + 211122: '盘山县', + 211200: '铁岭市', + 211201: '铁岭市市辖区', + 211202: '银州区', + 211204: '清河区', + 211221: '铁岭县', + 211223: '西丰县', + 211224: '昌图县', + 211281: '调兵山市', + 211282: '开原市', + 211300: '朝阳市', + 211301: '朝阳市市辖区', + 211302: '双塔区', + 211303: '龙城区', + 211321: '朝阳县', + 211322: '建平县', + 211324: '喀喇沁左翼蒙古族自治县', + 211381: '北票市', + 211382: '凌源市', + 211400: '葫芦岛市', + 211401: '葫芦岛市市辖区', + 211402: '连山区', + 211403: '龙港区', + 211404: '南票区', + 211421: '绥中县', + 211422: '建昌县', + 211481: '兴城市', + 220000: '吉林省', + 220100: '长春市', + 220101: '长春市市辖区', + 220102: '南关区', + 220103: '宽城区', + 220104: '朝阳区', + 220105: '二道区', + 220106: '绿园区', + 220112: '双阳区', + 220113: '九台区', + 220122: '农安县', + 220182: '榆树市', + 220183: '德惠市', + 220200: '吉林市', + 220201: '吉林市市辖区', + 220202: '昌邑区', + 220203: '龙潭区', + 220204: '船营区', + 220211: '丰满区', + 220221: '永吉县', + 220281: '蛟河市', + 220282: '桦甸市', + 220283: '舒兰市', + 220284: '磐石市', + 220300: '四平市', + 220301: '四平市市辖区', + 220302: '铁西区', + 220303: '铁东区', + 220322: '梨树县', + 220323: '伊通满族自治县', + 220381: '公主岭市', + 220382: '双辽市', + 220400: '辽源市', + 220401: '辽源市市辖区', + 220402: '龙山区', + 220403: '西安区', + 220421: '东丰县', + 220422: '东辽县', + 220500: '通化市', + 220501: '通化市市辖区', + 220502: '东昌区', + 220503: '二道江区', + 220521: '通化县', + 220523: '辉南县', + 220524: '柳河县', + 220581: '梅河口市', + 220582: '集安市', + 220600: '白山市', + 220601: '白山市市辖区', + 220602: '浑江区', + 220605: '江源区', + 220621: '抚松县', + 220622: '靖宇县', + 220623: '长白朝鲜族自治县', + 220681: '临江市', + 220700: '松原市', + 220701: '松原市市辖区', + 220702: '宁江区', + 220721: '前郭尔罗斯蒙古族自治县', + 220722: '长岭县', + 220723: '乾安县', + 220781: '扶余市', + 220800: '白城市', + 220801: '白城市市辖区', + 220802: '洮北区', + 220821: '镇赉县', + 220822: '通榆县', + 220881: '洮南市', + 220882: '大安市', + 222400: '延边朝鲜族自治州', + 222401: '延吉市', + 222402: '图们市', + 222403: '敦化市', + 222404: '珲春市', + 222405: '龙井市', + 222406: '和龙市', + 222424: '汪清县', + 222426: '安图县', + 230000: '黑龙江省', + 230100: '哈尔滨市', + 230101: '哈尔滨市市辖区', + 230102: '道里区', + 230103: '南岗区', + 230104: '道外区', + 230108: '平房区', + 230109: '松北区', + 230110: '香坊区', + 230111: '呼兰区', + 230112: '阿城区', + 230113: '双城区', + 230123: '依兰县', + 230124: '方正县', + 230125: '宾县', + 230126: '巴彦县', + 230127: '木兰县', + 230128: '通河县', + 230129: '延寿县', + 230183: '尚志市', + 230184: '五常市', + 230200: '齐齐哈尔市', + 230201: '齐齐哈尔市市辖区', + 230202: '龙沙区', + 230203: '建华区', + 230204: '铁锋区', + 230205: '昂昂溪区', + 230206: '富拉尔基区', + 230207: '碾子山区', + 230208: '梅里斯达斡尔族区', + 230221: '龙江县', + 230223: '依安县', + 230224: '泰来县', + 230225: '甘南县', + 230227: '富裕县', + 230229: '克山县', + 230230: '克东县', + 230231: '拜泉县', + 230281: '讷河市', + 230300: '鸡西市', + 230301: '鸡西市市辖区', + 230302: '鸡冠区', + 230303: '恒山区', + 230304: '滴道区', + 230305: '梨树区', + 230306: '城子河区', + 230307: '麻山区', + 230321: '鸡东县', + 230381: '虎林市', + 230382: '密山市', + 230400: '鹤岗市', + 230401: '鹤岗市市辖区', + 230402: '向阳区', + 230403: '工农区', + 230404: '南山区', + 230405: '兴安区', + 230406: '东山区', + 230407: '兴山区', + 230421: '萝北县', + 230422: '绥滨县', + 230500: '双鸭山市', + 230501: '双鸭山市市辖区', + 230502: '尖山区', + 230503: '岭东区', + 230505: '四方台区', + 230506: '宝山区', + 230521: '集贤县', + 230522: '友谊县', + 230523: '宝清县', + 230524: '饶河县', + 230600: '大庆市', + 230601: '大庆市市辖区', + 230602: '萨尔图区', + 230603: '龙凤区', + 230604: '让胡路区', + 230605: '红岗区', + 230606: '大同区', + 230621: '肇州县', + 230622: '肇源县', + 230623: '林甸县', + 230624: '杜尔伯特蒙古族自治县', + 230700: '伊春市', + 230701: '伊春市市辖区', + 230702: '伊春区', + 230703: '南岔区', + 230704: '友好区', + 230705: '西林区', + 230706: '翠峦区', + 230707: '新青区', + 230708: '美溪区', + 230709: '金山屯区', + 230710: '五营区', + 230711: '乌马河区', + 230712: '汤旺河区', + 230713: '带岭区', + 230714: '乌伊岭区', + 230715: '红星区', + 230716: '上甘岭区', + 230722: '嘉荫县', + 230781: '铁力市', + 230800: '佳木斯市', + 230801: '佳木斯市市辖区', + 230803: '向阳区', + 230804: '前进区', + 230805: '东风区', + 230811: '郊区', + 230822: '桦南县', + 230826: '桦川县', + 230828: '汤原县', + 230881: '同江市', + 230882: '富锦市', + 230883: '抚远市', + 230900: '七台河市', + 230901: '七台河市市辖区', + 230902: '新兴区', + 230903: '桃山区', + 230904: '茄子河区', + 230921: '勃利县', + 231000: '牡丹江市', + 231001: '牡丹江市市辖区', + 231002: '东安区', + 231003: '阳明区', + 231004: '爱民区', + 231005: '西安区', + 231025: '林口县', + 231081: '绥芬河市', + 231083: '海林市', + 231084: '宁安市', + 231085: '穆棱市', + 231086: '东宁市', + 231100: '黑河市', + 231101: '黑河市市辖区', + 231102: '爱辉区', + 231121: '嫩江县', + 231123: '逊克县', + 231124: '孙吴县', + 231181: '北安市', + 231182: '五大连池市', + 231200: '绥化市', + 231201: '绥化市市辖区', + 231202: '北林区', + 231221: '望奎县', + 231222: '兰西县', + 231223: '青冈县', + 231224: '庆安县', + 231225: '明水县', + 231226: '绥棱县', + 231281: '安达市', + 231282: '肇东市', + 231283: '海伦市', + 232700: '大兴安岭地区', + 232701: '漠河市', + 232718: '加格达奇区', + 232721: '呼玛县', + 232722: '塔河县', + 310000: '上海市', + 310100: '上海市市辖区', + 310101: '黄浦区', + 310104: '徐汇区', + 310105: '长宁区', + 310106: '静安区', + 310107: '普陀区', + 310109: '虹口区', + 310110: '杨浦区', + 310112: '闵行区', + 310113: '宝山区', + 310114: '嘉定区', + 310115: '浦东新区', + 310116: '金山区', + 310117: '松江区', + 310118: '青浦区', + 310120: '奉贤区', + 310151: '崇明区', + 320000: '江苏省', + 320100: '南京市', + 320101: '南京市市辖区', + 320102: '玄武区', + 320104: '秦淮区', + 320105: '建邺区', + 320106: '鼓楼区', + 320111: '浦口区', + 320113: '栖霞区', + 320114: '雨花台区', + 320115: '江宁区', + 320116: '六合区', + 320117: '溧水区', + 320118: '高淳区', + 320200: '无锡市', + 320201: '无锡市市辖区', + 320205: '锡山区', + 320206: '惠山区', + 320211: '滨湖区', + 320213: '梁溪区', + 320214: '新吴区', + 320281: '江阴市', + 320282: '宜兴市', + 320300: '徐州市', + 320301: '徐州市市辖区', + 320302: '鼓楼区', + 320303: '云龙区', + 320305: '贾汪区', + 320311: '泉山区', + 320312: '铜山区', + 320321: '丰县', + 320322: '沛县', + 320324: '睢宁县', + 320381: '新沂市', + 320382: '邳州市', + 320400: '常州市', + 320401: '常州市市辖区', + 320402: '天宁区', + 320404: '钟楼区', + 320411: '新北区', + 320412: '武进区', + 320413: '金坛区', + 320481: '溧阳市', + 320500: '苏州市', + 320501: '苏州市市辖区', + 320505: '虎丘区', + 320506: '吴中区', + 320507: '相城区', + 320508: '姑苏区', + 320509: '吴江区', + 320571: '苏州工业园区', + 320581: '常熟市', + 320582: '张家港市', + 320583: '昆山市', + 320585: '太仓市', + 320600: '南通市', + 320601: '南通市市辖区', + 320602: '崇川区', + 320611: '港闸区', + 320612: '通州区', + 320623: '如东县', + 320681: '启东市', + 320682: '如皋市', + 320684: '海门市', + 320685: '海安市', + 320700: '连云港市', + 320701: '连云港市市辖区', + 320703: '连云区', + 320706: '海州区', + 320707: '赣榆区', + 320722: '东海县', + 320723: '灌云县', + 320724: '灌南县', + 320800: '淮安市', + 320801: '淮安市市辖区', + 320803: '淮安区', + 320804: '淮阴区', + 320812: '清江浦区', + 320813: '洪泽区', + 320826: '涟水县', + 320830: '盱眙县', + 320831: '金湖县', + 320900: '盐城市', + 320901: '盐城市市辖区', + 320902: '亭湖区', + 320903: '盐都区', + 320904: '大丰区', + 320921: '响水县', + 320922: '滨海县', + 320923: '阜宁县', + 320924: '射阳县', + 320925: '建湖县', + 320981: '东台市', + 321000: '扬州市', + 321001: '扬州市市辖区', + 321002: '广陵区', + 321003: '邗江区', + 321012: '江都区', + 321023: '宝应县', + 321081: '仪征市', + 321084: '高邮市', + 321100: '镇江市', + 321101: '镇江市市辖区', + 321102: '京口区', + 321111: '润州区', + 321112: '丹徒区', + 321181: '丹阳市', + 321182: '扬中市', + 321183: '句容市', + 321200: '泰州市', + 321201: '泰州市市辖区', + 321202: '海陵区', + 321203: '高港区', + 321204: '姜堰区', + 321281: '兴化市', + 321282: '靖江市', + 321283: '泰兴市', + 321300: '宿迁市', + 321301: '宿迁市市辖区', + 321302: '宿城区', + 321311: '宿豫区', + 321322: '沭阳县', + 321323: '泗阳县', + 321324: '泗洪县', + 330000: '浙江省', + 330100: '杭州市', + 330101: '杭州市市辖区', + 330102: '上城区', + 330103: '下城区', + 330104: '江干区', + 330105: '拱墅区', + 330106: '西湖区', + 330108: '滨江区', + 330109: '萧山区', + 330110: '余杭区', + 330111: '富阳区', + 330112: '临安区', + 330122: '桐庐县', + 330127: '淳安县', + 330182: '建德市', + 330200: '宁波市', + 330201: '宁波市市辖区', + 330203: '海曙区', + 330205: '江北区', + 330206: '北仑区', + 330211: '镇海区', + 330212: '鄞州区', + 330213: '奉化区', + 330225: '象山县', + 330226: '宁海县', + 330281: '余姚市', + 330282: '慈溪市', + 330300: '温州市', + 330301: '温州市市辖区', + 330302: '鹿城区', + 330303: '龙湾区', + 330304: '瓯海区', + 330305: '洞头区', + 330324: '永嘉县', + 330326: '平阳县', + 330327: '苍南县', + 330328: '文成县', + 330329: '泰顺县', + 330381: '瑞安市', + 330382: '乐清市', + 330400: '嘉兴市', + 330401: '嘉兴市市辖区', + 330402: '南湖区', + 330411: '秀洲区', + 330421: '嘉善县', + 330424: '海盐县', + 330481: '海宁市', + 330482: '平湖市', + 330483: '桐乡市', + 330500: '湖州市', + 330501: '湖州市市辖区', + 330502: '吴兴区', + 330503: '南浔区', + 330521: '德清县', + 330522: '长兴县', + 330523: '安吉县', + 330600: '绍兴市', + 330601: '绍兴市市辖区', + 330602: '越城区', + 330603: '柯桥区', + 330604: '上虞区', + 330624: '新昌县', + 330681: '诸暨市', + 330683: '嵊州市', + 330700: '金华市', + 330701: '金华市市辖区', + 330702: '婺城区', + 330703: '金东区', + 330723: '武义县', + 330726: '浦江县', + 330727: '磐安县', + 330781: '兰溪市', + 330782: '义乌市', + 330783: '东阳市', + 330784: '永康市', + 330800: '衢州市', + 330801: '衢州市市辖区', + 330802: '柯城区', + 330803: '衢江区', + 330822: '常山县', + 330824: '开化县', + 330825: '龙游县', + 330881: '江山市', + 330900: '舟山市', + 330901: '舟山市市辖区', + 330902: '定海区', + 330903: '普陀区', + 330921: '岱山县', + 330922: '嵊泗县', + 331000: '台州市', + 331001: '台州市市辖区', + 331002: '椒江区', + 331003: '黄岩区', + 331004: '路桥区', + 331022: '三门县', + 331023: '天台县', + 331024: '仙居县', + 331081: '温岭市', + 331082: '临海市', + 331083: '玉环市', + 331100: '丽水市', + 331101: '丽水市市辖区', + 331102: '莲都区', + 331121: '青田县', + 331122: '缙云县', + 331123: '遂昌县', + 331124: '松阳县', + 331125: '云和县', + 331126: '庆元县', + 331127: '景宁畲族自治县', + 331181: '龙泉市', + 340000: '安徽省', + 340100: '合肥市', + 340101: '合肥市市辖区', + 340102: '瑶海区', + 340103: '庐阳区', + 340104: '蜀山区', + 340111: '包河区', + 340121: '长丰县', + 340122: '肥东县', + 340123: '肥西县', + 340124: '庐江县', + 340181: '巢湖市', + 340200: '芜湖市', + 340201: '芜湖市市辖区', + 340202: '镜湖区', + 340203: '弋江区', + 340207: '鸠江区', + 340208: '三山区', + 340221: '芜湖县', + 340222: '繁昌县', + 340223: '南陵县', + 340225: '无为县', + 340300: '蚌埠市', + 340301: '蚌埠市市辖区', + 340302: '龙子湖区', + 340303: '蚌山区', + 340304: '禹会区', + 340311: '淮上区', + 340321: '怀远县', + 340322: '五河县', + 340323: '固镇县', + 340400: '淮南市', + 340401: '淮南市市辖区', + 340402: '大通区', + 340403: '田家庵区', + 340404: '谢家集区', + 340405: '八公山区', + 340406: '潘集区', + 340421: '凤台县', + 340422: '寿县', + 340500: '马鞍山市', + 340501: '马鞍山市市辖区', + 340503: '花山区', + 340504: '雨山区', + 340506: '博望区', + 340521: '当涂县', + 340522: '含山县', + 340523: '和县', + 340600: '淮北市', + 340601: '淮北市市辖区', + 340602: '杜集区', + 340603: '相山区', + 340604: '烈山区', + 340621: '濉溪县', + 340700: '铜陵市', + 340701: '铜陵市市辖区', + 340705: '铜官区', + 340706: '义安区', + 340711: '郊区', + 340722: '枞阳县', + 340800: '安庆市', + 340801: '安庆市市辖区', + 340802: '迎江区', + 340803: '大观区', + 340811: '宜秀区', + 340822: '怀宁县', + 340824: '潜山市', + 340825: '太湖县', + 340826: '宿松县', + 340827: '望江县', + 340828: '岳西县', + 340881: '桐城市', + 341000: '黄山市', + 341001: '黄山市市辖区', + 341002: '屯溪区', + 341003: '黄山区', + 341004: '徽州区', + 341021: '歙县', + 341022: '休宁县', + 341023: '黟县', + 341024: '祁门县', + 341100: '滁州市', + 341101: '滁州市市辖区', + 341102: '琅琊区', + 341103: '南谯区', + 341122: '来安县', + 341124: '全椒县', + 341125: '定远县', + 341126: '凤阳县', + 341181: '天长市', + 341182: '明光市', + 341200: '阜阳市', + 341201: '阜阳市市辖区', + 341202: '颍州区', + 341203: '颍东区', + 341204: '颍泉区', + 341221: '临泉县', + 341222: '太和县', + 341225: '阜南县', + 341226: '颍上县', + 341282: '界首市', + 341300: '宿州市', + 341301: '宿州市市辖区', + 341302: '埇桥区', + 341321: '砀山县', + 341322: '萧县', + 341323: '灵璧县', + 341324: '泗县', + 341500: '六安市', + 341501: '六安市市辖区', + 341502: '金安区', + 341503: '裕安区', + 341504: '叶集区', + 341522: '霍邱县', + 341523: '舒城县', + 341524: '金寨县', + 341525: '霍山县', + 341600: '亳州市', + 341601: '亳州市市辖区', + 341602: '谯城区', + 341621: '涡阳县', + 341622: '蒙城县', + 341623: '利辛县', + 341700: '池州市', + 341701: '池州市市辖区', + 341702: '贵池区', + 341721: '东至县', + 341722: '石台县', + 341723: '青阳县', + 341800: '宣城市', + 341801: '宣城市市辖区', + 341802: '宣州区', + 341821: '郎溪县', + 341822: '广德县', + 341823: '泾县', + 341824: '绩溪县', + 341825: '旌德县', + 341881: '宁国市', + 350000: '福建省', + 350100: '福州市', + 350101: '福州市市辖区', + 350102: '鼓楼区', + 350103: '台江区', + 350104: '仓山区', + 350105: '马尾区', + 350111: '晋安区', + 350112: '长乐区', + 350121: '闽侯县', + 350122: '连江县', + 350123: '罗源县', + 350124: '闽清县', + 350125: '永泰县', + 350128: '平潭县', + 350181: '福清市', + 350200: '厦门市', + 350201: '厦门市市辖区', + 350203: '思明区', + 350205: '海沧区', + 350206: '湖里区', + 350211: '集美区', + 350212: '同安区', + 350213: '翔安区', + 350300: '莆田市', + 350301: '莆田市市辖区', + 350302: '城厢区', + 350303: '涵江区', + 350304: '荔城区', + 350305: '秀屿区', + 350322: '仙游县', + 350400: '三明市', + 350401: '三明市市辖区', + 350402: '梅列区', + 350403: '三元区', + 350421: '明溪县', + 350423: '清流县', + 350424: '宁化县', + 350425: '大田县', + 350426: '尤溪县', + 350427: '沙县', + 350428: '将乐县', + 350429: '泰宁县', + 350430: '建宁县', + 350481: '永安市', + 350500: '泉州市', + 350501: '泉州市市辖区', + 350502: '鲤城区', + 350503: '丰泽区', + 350504: '洛江区', + 350505: '泉港区', + 350521: '惠安县', + 350524: '安溪县', + 350525: '永春县', + 350526: '德化县', + 350527: '金门县', + 350581: '石狮市', + 350582: '晋江市', + 350583: '南安市', + 350600: '漳州市', + 350601: '漳州市市辖区', + 350602: '芗城区', + 350603: '龙文区', + 350622: '云霄县', + 350623: '漳浦县', + 350624: '诏安县', + 350625: '长泰县', + 350626: '东山县', + 350627: '南靖县', + 350628: '平和县', + 350629: '华安县', + 350681: '龙海市', + 350700: '南平市', + 350701: '南平市市辖区', + 350702: '延平区', + 350703: '建阳区', + 350721: '顺昌县', + 350722: '浦城县', + 350723: '光泽县', + 350724: '松溪县', + 350725: '政和县', + 350781: '邵武市', + 350782: '武夷山市', + 350783: '建瓯市', + 350800: '龙岩市', + 350801: '龙岩市市辖区', + 350802: '新罗区', + 350803: '永定区', + 350821: '长汀县', + 350823: '上杭县', + 350824: '武平县', + 350825: '连城县', + 350881: '漳平市', + 350900: '宁德市', + 350901: '宁德市市辖区', + 350902: '蕉城区', + 350921: '霞浦县', + 350922: '古田县', + 350923: '屏南县', + 350924: '寿宁县', + 350925: '周宁县', + 350926: '柘荣县', + 350981: '福安市', + 350982: '福鼎市', + 360000: '江西省', + 360100: '南昌市', + 360101: '南昌市市辖区', + 360102: '东湖区', + 360103: '西湖区', + 360104: '青云谱区', + 360105: '湾里区', + 360111: '青山湖区', + 360112: '新建区', + 360121: '南昌县', + 360123: '安义县', + 360124: '进贤县', + 360200: '景德镇市', + 360201: '景德镇市市辖区', + 360202: '昌江区', + 360203: '珠山区', + 360222: '浮梁县', + 360281: '乐平市', + 360300: '萍乡市', + 360301: '萍乡市市辖区', + 360302: '安源区', + 360313: '湘东区', + 360321: '莲花县', + 360322: '上栗县', + 360323: '芦溪县', + 360400: '九江市', + 360401: '九江市市辖区', + 360402: '濂溪区', + 360403: '浔阳区', + 360404: '柴桑区', + 360423: '武宁县', + 360424: '修水县', + 360425: '永修县', + 360426: '德安县', + 360428: '都昌县', + 360429: '湖口县', + 360430: '彭泽县', + 360481: '瑞昌市', + 360482: '共青城市', + 360483: '庐山市', + 360500: '新余市', + 360501: '新余市市辖区', + 360502: '渝水区', + 360521: '分宜县', + 360600: '鹰潭市', + 360601: '鹰潭市市辖区', + 360602: '月湖区', + 360603: '余江区', + 360681: '贵溪市', + 360700: '赣州市', + 360701: '赣州市市辖区', + 360702: '章贡区', + 360703: '南康区', + 360704: '赣县区', + 360722: '信丰县', + 360723: '大余县', + 360724: '上犹县', + 360725: '崇义县', + 360726: '安远县', + 360727: '龙南县', + 360728: '定南县', + 360729: '全南县', + 360730: '宁都县', + 360731: '于都县', + 360732: '兴国县', + 360733: '会昌县', + 360734: '寻乌县', + 360735: '石城县', + 360781: '瑞金市', + 360800: '吉安市', + 360801: '吉安市市辖区', + 360802: '吉州区', + 360803: '青原区', + 360821: '吉安县', + 360822: '吉水县', + 360823: '峡江县', + 360824: '新干县', + 360825: '永丰县', + 360826: '泰和县', + 360827: '遂川县', + 360828: '万安县', + 360829: '安福县', + 360830: '永新县', + 360881: '井冈山市', + 360900: '宜春市', + 360901: '宜春市市辖区', + 360902: '袁州区', + 360921: '奉新县', + 360922: '万载县', + 360923: '上高县', + 360924: '宜丰县', + 360925: '靖安县', + 360926: '铜鼓县', + 360981: '丰城市', + 360982: '樟树市', + 360983: '高安市', + 361000: '抚州市', + 361001: '抚州市市辖区', + 361002: '临川区', + 361003: '东乡区', + 361021: '南城县', + 361022: '黎川县', + 361023: '南丰县', + 361024: '崇仁县', + 361025: '乐安县', + 361026: '宜黄县', + 361027: '金溪县', + 361028: '资溪县', + 361030: '广昌县', + 361100: '上饶市', + 361101: '上饶市市辖区', + 361102: '信州区', + 361103: '广丰区', + 361121: '上饶县', + 361123: '玉山县', + 361124: '铅山县', + 361125: '横峰县', + 361126: '弋阳县', + 361127: '余干县', + 361128: '鄱阳县', + 361129: '万年县', + 361130: '婺源县', + 361181: '德兴市', + 370000: '山东省', + 370100: '济南市', + 370101: '济南市市辖区', + 370102: '历下区', + 370103: '市中区', + 370104: '槐荫区', + 370105: '天桥区', + 370112: '历城区', + 370113: '长清区', + 370114: '章丘区', + 370115: '济阳区', + 370116: '莱芜区', + 370117: '钢城区', + 370124: '平阴县', + 370126: '商河县', + 370200: '青岛市', + 370201: '青岛市市辖区', + 370202: '市南区', + 370203: '市北区', + 370211: '黄岛区', + 370212: '崂山区', + 370213: '李沧区', + 370214: '城阳区', + 370215: '即墨区', + 370281: '胶州市', + 370283: '平度市', + 370285: '莱西市', + 370300: '淄博市', + 370301: '淄博市市辖区', + 370302: '淄川区', + 370303: '张店区', + 370304: '博山区', + 370305: '临淄区', + 370306: '周村区', + 370321: '桓台县', + 370322: '高青县', + 370323: '沂源县', + 370400: '枣庄市', + 370401: '枣庄市市辖区', + 370402: '市中区', + 370403: '薛城区', + 370404: '峄城区', + 370405: '台儿庄区', + 370406: '山亭区', + 370481: '滕州市', + 370500: '东营市', + 370501: '东营市市辖区', + 370502: '东营区', + 370503: '河口区', + 370505: '垦利区', + 370522: '利津县', + 370523: '广饶县', + 370600: '烟台市', + 370601: '烟台市市辖区', + 370602: '芝罘区', + 370611: '福山区', + 370612: '牟平区', + 370613: '莱山区', + 370634: '长岛县', + 370681: '龙口市', + 370682: '莱阳市', + 370683: '莱州市', + 370684: '蓬莱市', + 370685: '招远市', + 370686: '栖霞市', + 370687: '海阳市', + 370700: '潍坊市', + 370701: '潍坊市市辖区', + 370702: '潍城区', + 370703: '寒亭区', + 370704: '坊子区', + 370705: '奎文区', + 370724: '临朐县', + 370725: '昌乐县', + 370781: '青州市', + 370782: '诸城市', + 370783: '寿光市', + 370784: '安丘市', + 370785: '高密市', + 370786: '昌邑市', + 370800: '济宁市', + 370801: '济宁市市辖区', + 370811: '任城区', + 370812: '兖州区', + 370826: '微山县', + 370827: '鱼台县', + 370828: '金乡县', + 370829: '嘉祥县', + 370830: '汶上县', + 370831: '泗水县', + 370832: '梁山县', + 370881: '曲阜市', + 370883: '邹城市', + 370900: '泰安市', + 370901: '泰安市市辖区', + 370902: '泰山区', + 370911: '岱岳区', + 370921: '宁阳县', + 370923: '东平县', + 370982: '新泰市', + 370983: '肥城市', + 371000: '威海市', + 371001: '威海市市辖区', + 371002: '环翠区', + 371003: '文登区', + 371082: '荣成市', + 371083: '乳山市', + 371100: '日照市', + 371101: '日照市市辖区', + 371102: '东港区', + 371103: '岚山区', + 371121: '五莲县', + 371122: '莒县', + 371300: '临沂市', + 371301: '临沂市市辖区', + 371302: '兰山区', + 371311: '罗庄区', + 371312: '河东区', + 371321: '沂南县', + 371322: '郯城县', + 371323: '沂水县', + 371324: '兰陵县', + 371325: '费县', + 371326: '平邑县', + 371327: '莒南县', + 371328: '蒙阴县', + 371329: '临沭县', + 371400: '德州市', + 371401: '德州市市辖区', + 371402: '德城区', + 371403: '陵城区', + 371422: '宁津县', + 371423: '庆云县', + 371424: '临邑县', + 371425: '齐河县', + 371426: '平原县', + 371427: '夏津县', + 371428: '武城县', + 371481: '乐陵市', + 371482: '禹城市', + 371500: '聊城市', + 371501: '聊城市市辖区', + 371502: '东昌府区', + 371521: '阳谷县', + 371522: '莘县', + 371523: '茌平县', + 371524: '东阿县', + 371525: '冠县', + 371526: '高唐县', + 371581: '临清市', + 371600: '滨州市', + 371601: '滨州市市辖区', + 371602: '滨城区', + 371603: '沾化区', + 371621: '惠民县', + 371622: '阳信县', + 371623: '无棣县', + 371625: '博兴县', + 371681: '邹平市', + 371700: '菏泽市', + 371701: '菏泽市市辖区', + 371702: '牡丹区', + 371703: '定陶区', + 371721: '曹县', + 371722: '单县', + 371723: '成武县', + 371724: '巨野县', + 371725: '郓城县', + 371726: '鄄城县', + 371728: '东明县', + 410000: '河南省', + 410100: '郑州市', + 410101: '郑州市市辖区', + 410102: '中原区', + 410103: '二七区', + 410104: '管城回族区', + 410105: '金水区', + 410106: '上街区', + 410108: '惠济区', + 410122: '中牟县', + 410181: '巩义市', + 410182: '荥阳市', + 410183: '新密市', + 410184: '新郑市', + 410185: '登封市', + 410200: '开封市', + 410201: '开封市市辖区', + 410202: '龙亭区', + 410203: '顺河回族区', + 410204: '鼓楼区', + 410205: '禹王台区', + 410212: '祥符区', + 410221: '杞县', + 410222: '通许县', + 410223: '尉氏县', + 410225: '兰考县', + 410300: '洛阳市', + 410301: '洛阳市市辖区', + 410302: '老城区', + 410303: '西工区', + 410304: '瀍河回族区', + 410305: '涧西区', + 410306: '吉利区', + 410311: '洛龙区', + 410322: '孟津县', + 410323: '新安县', + 410324: '栾川县', + 410325: '嵩县', + 410326: '汝阳县', + 410327: '宜阳县', + 410328: '洛宁县', + 410329: '伊川县', + 410381: '偃师市', + 410400: '平顶山市', + 410401: '平顶山市市辖区', + 410402: '新华区', + 410403: '卫东区', + 410404: '石龙区', + 410411: '湛河区', + 410421: '宝丰县', + 410422: '叶县', + 410423: '鲁山县', + 410425: '郏县', + 410481: '舞钢市', + 410482: '汝州市', + 410500: '安阳市', + 410501: '安阳市市辖区', + 410502: '文峰区', + 410503: '北关区', + 410505: '殷都区', + 410506: '龙安区', + 410522: '安阳县', + 410523: '汤阴县', + 410526: '滑县', + 410527: '内黄县', + 410581: '林州市', + 410600: '鹤壁市', + 410601: '鹤壁市市辖区', + 410602: '鹤山区', + 410603: '山城区', + 410611: '淇滨区', + 410621: '浚县', + 410622: '淇县', + 410700: '新乡市', + 410701: '新乡市市辖区', + 410702: '红旗区', + 410703: '卫滨区', + 410704: '凤泉区', + 410711: '牧野区', + 410721: '新乡县', + 410724: '获嘉县', + 410725: '原阳县', + 410726: '延津县', + 410727: '封丘县', + 410728: '长垣县', + 410781: '卫辉市', + 410782: '辉县市', + 410800: '焦作市', + 410801: '焦作市市辖区', + 410802: '解放区', + 410803: '中站区', + 410804: '马村区', + 410811: '山阳区', + 410821: '修武县', + 410822: '博爱县', + 410823: '武陟县', + 410825: '温县', + 410882: '沁阳市', + 410883: '孟州市', + 410900: '濮阳市', + 410901: '濮阳市市辖区', + 410902: '华龙区', + 410922: '清丰县', + 410923: '南乐县', + 410926: '范县', + 410927: '台前县', + 410928: '濮阳县', + 411000: '许昌市', + 411001: '许昌市市辖区', + 411002: '魏都区', + 411003: '建安区', + 411024: '鄢陵县', + 411025: '襄城县', + 411081: '禹州市', + 411082: '长葛市', + 411100: '漯河市', + 411101: '漯河市市辖区', + 411102: '源汇区', + 411103: '郾城区', + 411104: '召陵区', + 411121: '舞阳县', + 411122: '临颍县', + 411200: '三门峡市', + 411201: '三门峡市市辖区', + 411202: '湖滨区', + 411203: '陕州区', + 411221: '渑池县', + 411224: '卢氏县', + 411281: '义马市', + 411282: '灵宝市', + 411300: '南阳市', + 411301: '南阳市市辖区', + 411302: '宛城区', + 411303: '卧龙区', + 411321: '南召县', + 411322: '方城县', + 411323: '西峡县', + 411324: '镇平县', + 411325: '内乡县', + 411326: '淅川县', + 411327: '社旗县', + 411328: '唐河县', + 411329: '新野县', + 411330: '桐柏县', + 411381: '邓州市', + 411400: '商丘市', + 411401: '商丘市市辖区', + 411402: '梁园区', + 411403: '睢阳区', + 411421: '民权县', + 411422: '睢县', + 411423: '宁陵县', + 411424: '柘城县', + 411425: '虞城县', + 411426: '夏邑县', + 411481: '永城市', + 411500: '信阳市', + 411501: '信阳市市辖区', + 411502: '浉河区', + 411503: '平桥区', + 411521: '罗山县', + 411522: '光山县', + 411523: '新县', + 411524: '商城县', + 411525: '固始县', + 411526: '潢川县', + 411527: '淮滨县', + 411528: '息县', + 411600: '周口市', + 411601: '周口市市辖区', + 411602: '川汇区', + 411621: '扶沟县', + 411622: '西华县', + 411623: '商水县', + 411624: '沈丘县', + 411625: '郸城县', + 411626: '淮阳县', + 411627: '太康县', + 411628: '鹿邑县', + 411681: '项城市', + 411700: '驻马店市', + 411701: '驻马店市市辖区', + 411702: '驿城区', + 411721: '西平县', + 411722: '上蔡县', + 411723: '平舆县', + 411724: '正阳县', + 411725: '确山县', + 411726: '泌阳县', + 411727: '汝南县', + 411728: '遂平县', + 411729: '新蔡县', + 419001: '济源市', + 420000: '湖北省', + 420100: '武汉市', + 420101: '武汉市市辖区', + 420102: '江岸区', + 420103: '江汉区', + 420104: '硚口区', + 420105: '汉阳区', + 420106: '武昌区', + 420107: '青山区', + 420111: '洪山区', + 420112: '东西湖区', + 420113: '汉南区', + 420114: '蔡甸区', + 420115: '江夏区', + 420116: '黄陂区', + 420117: '新洲区', + 420200: '黄石市', + 420201: '黄石市市辖区', + 420202: '黄石港区', + 420203: '西塞山区', + 420204: '下陆区', + 420205: '铁山区', + 420222: '阳新县', + 420281: '大冶市', + 420300: '十堰市', + 420301: '十堰市市辖区', + 420302: '茅箭区', + 420303: '张湾区', + 420304: '郧阳区', + 420322: '郧西县', + 420323: '竹山县', + 420324: '竹溪县', + 420325: '房县', + 420381: '丹江口市', + 420500: '宜昌市', + 420501: '宜昌市市辖区', + 420502: '西陵区', + 420503: '伍家岗区', + 420504: '点军区', + 420505: '猇亭区', + 420506: '夷陵区', + 420525: '远安县', + 420526: '兴山县', + 420527: '秭归县', + 420528: '长阳土家族自治县', + 420529: '五峰土家族自治县', + 420581: '宜都市', + 420582: '当阳市', + 420583: '枝江市', + 420600: '襄阳市', + 420601: '襄阳市市辖区', + 420602: '襄城区', + 420606: '樊城区', + 420607: '襄州区', + 420624: '南漳县', + 420625: '谷城县', + 420626: '保康县', + 420682: '老河口市', + 420683: '枣阳市', + 420684: '宜城市', + 420700: '鄂州市', + 420701: '鄂州市市辖区', + 420702: '梁子湖区', + 420703: '华容区', + 420704: '鄂城区', + 420800: '荆门市', + 420801: '荆门市市辖区', + 420802: '东宝区', + 420804: '掇刀区', + 420822: '沙洋县', + 420881: '钟祥市', + 420882: '京山市', + 420900: '孝感市', + 420901: '孝感市市辖区', + 420902: '孝南区', + 420921: '孝昌县', + 420922: '大悟县', + 420923: '云梦县', + 420981: '应城市', + 420982: '安陆市', + 420984: '汉川市', + 421000: '荆州市', + 421001: '荆州市市辖区', + 421002: '沙市区', + 421003: '荆州区', + 421022: '公安县', + 421023: '监利县', + 421024: '江陵县', + 421081: '石首市', + 421083: '洪湖市', + 421087: '松滋市', + 421100: '黄冈市', + 421101: '黄冈市市辖区', + 421102: '黄州区', + 421121: '团风县', + 421122: '红安县', + 421123: '罗田县', + 421124: '英山县', + 421125: '浠水县', + 421126: '蕲春县', + 421127: '黄梅县', + 421181: '麻城市', + 421182: '武穴市', + 421200: '咸宁市', + 421201: '咸宁市市辖区', + 421202: '咸安区', + 421221: '嘉鱼县', + 421222: '通城县', + 421223: '崇阳县', + 421224: '通山县', + 421281: '赤壁市', + 421300: '随州市', + 421301: '随州市市辖区', + 421303: '曾都区', + 421321: '随县', + 421381: '广水市', + 422800: '恩施土家族苗族自治州', + 422801: '恩施市', + 422802: '利川市', + 422822: '建始县', + 422823: '巴东县', + 422825: '宣恩县', + 422826: '咸丰县', + 422827: '来凤县', + 422828: '鹤峰县', + 429004: '仙桃市', + 429005: '潜江市', + 429006: '天门市', + 429021: '神农架林区', + 430000: '湖南省', + 430100: '长沙市', + 430101: '长沙市市辖区', + 430102: '芙蓉区', + 430103: '天心区', + 430104: '岳麓区', + 430105: '开福区', + 430111: '雨花区', + 430112: '望城区', + 430121: '长沙县', + 430181: '浏阳市', + 430182: '宁乡市', + 430200: '株洲市', + 430201: '株洲市市辖区', + 430202: '荷塘区', + 430203: '芦淞区', + 430204: '石峰区', + 430211: '天元区', + 430212: '渌口区', + 430223: '攸县', + 430224: '茶陵县', + 430225: '炎陵县', + 430281: '醴陵市', + 430300: '湘潭市', + 430301: '湘潭市市辖区', + 430302: '雨湖区', + 430304: '岳塘区', + 430321: '湘潭县', + 430381: '湘乡市', + 430382: '韶山市', + 430400: '衡阳市', + 430401: '衡阳市市辖区', + 430405: '珠晖区', + 430406: '雁峰区', + 430407: '石鼓区', + 430408: '蒸湘区', + 430412: '南岳区', + 430421: '衡阳县', + 430422: '衡南县', + 430423: '衡山县', + 430424: '衡东县', + 430426: '祁东县', + 430481: '耒阳市', + 430482: '常宁市', + 430500: '邵阳市', + 430501: '邵阳市市辖区', + 430502: '双清区', + 430503: '大祥区', + 430511: '北塔区', + 430521: '邵东县', + 430522: '新邵县', + 430523: '邵阳县', + 430524: '隆回县', + 430525: '洞口县', + 430527: '绥宁县', + 430528: '新宁县', + 430529: '城步苗族自治县', + 430581: '武冈市', + 430600: '岳阳市', + 430601: '岳阳市市辖区', + 430602: '岳阳楼区', + 430603: '云溪区', + 430611: '君山区', + 430621: '岳阳县', + 430623: '华容县', + 430624: '湘阴县', + 430626: '平江县', + 430681: '汨罗市', + 430682: '临湘市', + 430700: '常德市', + 430701: '常德市市辖区', + 430702: '武陵区', + 430703: '鼎城区', + 430721: '安乡县', + 430722: '汉寿县', + 430723: '澧县', + 430724: '临澧县', + 430725: '桃源县', + 430726: '石门县', + 430781: '津市市', + 430800: '张家界市', + 430801: '张家界市市辖区', + 430802: '永定区', + 430811: '武陵源区', + 430821: '慈利县', + 430822: '桑植县', + 430900: '益阳市', + 430901: '益阳市市辖区', + 430902: '资阳区', + 430903: '赫山区', + 430921: '南县', + 430922: '桃江县', + 430923: '安化县', + 430981: '沅江市', + 431000: '郴州市', + 431001: '郴州市市辖区', + 431002: '北湖区', + 431003: '苏仙区', + 431021: '桂阳县', + 431022: '宜章县', + 431023: '永兴县', + 431024: '嘉禾县', + 431025: '临武县', + 431026: '汝城县', + 431027: '桂东县', + 431028: '安仁县', + 431081: '资兴市', + 431100: '永州市', + 431101: '永州市市辖区', + 431102: '零陵区', + 431103: '冷水滩区', + 431121: '祁阳县', + 431122: '东安县', + 431123: '双牌县', + 431124: '道县', + 431125: '江永县', + 431126: '宁远县', + 431127: '蓝山县', + 431128: '新田县', + 431129: '江华瑶族自治县', + 431200: '怀化市', + 431201: '怀化市市辖区', + 431202: '鹤城区', + 431221: '中方县', + 431222: '沅陵县', + 431223: '辰溪县', + 431224: '溆浦县', + 431225: '会同县', + 431226: '麻阳苗族自治县', + 431227: '新晃侗族自治县', + 431228: '芷江侗族自治县', + 431229: '靖州苗族侗族自治县', + 431230: '通道侗族自治县', + 431281: '洪江市', + 431300: '娄底市', + 431301: '娄底市市辖区', + 431302: '娄星区', + 431321: '双峰县', + 431322: '新化县', + 431381: '冷水江市', + 431382: '涟源市', + 433100: '湘西土家族苗族自治州', + 433101: '吉首市', + 433122: '泸溪县', + 433123: '凤凰县', + 433124: '花垣县', + 433125: '保靖县', + 433126: '古丈县', + 433127: '永顺县', + 433130: '龙山县', + 440000: '广东省', + 440100: '广州市', + 440101: '广州市市辖区', + 440103: '荔湾区', + 440104: '越秀区', + 440105: '海珠区', + 440106: '天河区', + 440111: '白云区', + 440112: '黄埔区', + 440113: '番禺区', + 440114: '花都区', + 440115: '南沙区', + 440117: '从化区', + 440118: '增城区', + 440200: '韶关市', + 440201: '韶关市市辖区', + 440203: '武江区', + 440204: '浈江区', + 440205: '曲江区', + 440222: '始兴县', + 440224: '仁化县', + 440229: '翁源县', + 440232: '乳源瑶族自治县', + 440233: '新丰县', + 440281: '乐昌市', + 440282: '南雄市', + 440300: '深圳市', + 440301: '深圳市市辖区', + 440303: '罗湖区', + 440304: '福田区', + 440305: '南山区', + 440306: '宝安区', + 440307: '龙岗区', + 440308: '盐田区', + 440309: '龙华区', + 440310: '坪山区', + 440311: '光明区', + 440400: '珠海市', + 440401: '珠海市市辖区', + 440402: '香洲区', + 440403: '斗门区', + 440404: '金湾区', + 440500: '汕头市', + 440501: '汕头市市辖区', + 440507: '龙湖区', + 440511: '金平区', + 440512: '濠江区', + 440513: '潮阳区', + 440514: '潮南区', + 440515: '澄海区', + 440523: '南澳县', + 440600: '佛山市', + 440601: '佛山市市辖区', + 440604: '禅城区', + 440605: '南海区', + 440606: '顺德区', + 440607: '三水区', + 440608: '高明区', + 440700: '江门市', + 440701: '江门市市辖区', + 440703: '蓬江区', + 440704: '江海区', + 440705: '新会区', + 440781: '台山市', + 440783: '开平市', + 440784: '鹤山市', + 440785: '恩平市', + 440800: '湛江市', + 440801: '湛江市市辖区', + 440802: '赤坎区', + 440803: '霞山区', + 440804: '坡头区', + 440811: '麻章区', + 440823: '遂溪县', + 440825: '徐闻县', + 440881: '廉江市', + 440882: '雷州市', + 440883: '吴川市', + 440900: '茂名市', + 440901: '茂名市市辖区', + 440902: '茂南区', + 440904: '电白区', + 440981: '高州市', + 440982: '化州市', + 440983: '信宜市', + 441200: '肇庆市', + 441201: '肇庆市市辖区', + 441202: '端州区', + 441203: '鼎湖区', + 441204: '高要区', + 441223: '广宁县', + 441224: '怀集县', + 441225: '封开县', + 441226: '德庆县', + 441284: '四会市', + 441300: '惠州市', + 441301: '惠州市市辖区', + 441302: '惠城区', + 441303: '惠阳区', + 441322: '博罗县', + 441323: '惠东县', + 441324: '龙门县', + 441400: '梅州市', + 441401: '梅州市市辖区', + 441402: '梅江区', + 441403: '梅县区', + 441422: '大埔县', + 441423: '丰顺县', + 441424: '五华县', + 441426: '平远县', + 441427: '蕉岭县', + 441481: '兴宁市', + 441500: '汕尾市', + 441501: '汕尾市市辖区', + 441502: '城区', + 441521: '海丰县', + 441523: '陆河县', + 441581: '陆丰市', + 441600: '河源市', + 441601: '河源市市辖区', + 441602: '源城区', + 441621: '紫金县', + 441622: '龙川县', + 441623: '连平县', + 441624: '和平县', + 441625: '东源县', + 441700: '阳江市', + 441701: '阳江市市辖区', + 441702: '江城区', + 441704: '阳东区', + 441721: '阳西县', + 441781: '阳春市', + 441800: '清远市', + 441801: '清远市市辖区', + 441802: '清城区', + 441803: '清新区', + 441821: '佛冈县', + 441823: '阳山县', + 441825: '连山壮族瑶族自治县', + 441826: '连南瑶族自治县', + 441881: '英德市', + 441882: '连州市', + 441900: '东莞市', + 442000: '中山市', + 442101: '东沙群岛', + 445100: '潮州市', + 445101: '潮州市市辖区', + 445102: '湘桥区', + 445103: '潮安区', + 445122: '饶平县', + 445200: '揭阳市', + 445201: '揭阳市市辖区', + 445202: '榕城区', + 445203: '揭东区', + 445222: '揭西县', + 445224: '惠来县', + 445281: '普宁市', + 445300: '云浮市', + 445301: '云浮市市辖区', + 445302: '云城区', + 445303: '云安区', + 445321: '新兴县', + 445322: '郁南县', + 445381: '罗定市', + 450000: '广西壮族自治区', + 450100: '南宁市', + 450101: '南宁市市辖区', + 450102: '兴宁区', + 450103: '青秀区', + 450105: '江南区', + 450107: '西乡塘区', + 450108: '良庆区', + 450109: '邕宁区', + 450110: '武鸣区', + 450123: '隆安县', + 450124: '马山县', + 450125: '上林县', + 450126: '宾阳县', + 450127: '横县', + 450200: '柳州市', + 450201: '柳州市市辖区', + 450202: '城中区', + 450203: '鱼峰区', + 450204: '柳南区', + 450205: '柳北区', + 450206: '柳江区', + 450222: '柳城县', + 450223: '鹿寨县', + 450224: '融安县', + 450225: '融水苗族自治县', + 450226: '三江侗族自治县', + 450300: '桂林市', + 450301: '桂林市市辖区', + 450302: '秀峰区', + 450303: '叠彩区', + 450304: '象山区', + 450305: '七星区', + 450311: '雁山区', + 450312: '临桂区', + 450321: '阳朔县', + 450323: '灵川县', + 450324: '全州县', + 450325: '兴安县', + 450326: '永福县', + 450327: '灌阳县', + 450328: '龙胜各族自治县', + 450329: '资源县', + 450330: '平乐县', + 450332: '恭城瑶族自治县', + 450381: '荔浦市', + 450400: '梧州市', + 450401: '梧州市市辖区', + 450403: '万秀区', + 450405: '长洲区', + 450406: '龙圩区', + 450421: '苍梧县', + 450422: '藤县', + 450423: '蒙山县', + 450481: '岑溪市', + 450500: '北海市', + 450501: '北海市市辖区', + 450502: '海城区', + 450503: '银海区', + 450512: '铁山港区', + 450521: '合浦县', + 450600: '防城港市', + 450601: '防城港市市辖区', + 450602: '港口区', + 450603: '防城区', + 450621: '上思县', + 450681: '东兴市', + 450700: '钦州市', + 450701: '钦州市市辖区', + 450702: '钦南区', + 450703: '钦北区', + 450721: '灵山县', + 450722: '浦北县', + 450800: '贵港市', + 450801: '贵港市市辖区', + 450802: '港北区', + 450803: '港南区', + 450804: '覃塘区', + 450821: '平南县', + 450881: '桂平市', + 450900: '玉林市', + 450901: '玉林市市辖区', + 450902: '玉州区', + 450903: '福绵区', + 450921: '容县', + 450922: '陆川县', + 450923: '博白县', + 450924: '兴业县', + 450981: '北流市', + 451000: '百色市', + 451001: '百色市市辖区', + 451002: '右江区', + 451021: '田阳县', + 451022: '田东县', + 451023: '平果县', + 451024: '德保县', + 451026: '那坡县', + 451027: '凌云县', + 451028: '乐业县', + 451029: '田林县', + 451030: '西林县', + 451031: '隆林各族自治县', + 451081: '靖西市', + 451100: '贺州市', + 451101: '贺州市市辖区', + 451102: '八步区', + 451103: '平桂区', + 451121: '昭平县', + 451122: '钟山县', + 451123: '富川瑶族自治县', + 451200: '河池市', + 451201: '河池市市辖区', + 451202: '金城江区', + 451203: '宜州区', + 451221: '南丹县', + 451222: '天峨县', + 451223: '凤山县', + 451224: '东兰县', + 451225: '罗城仫佬族自治县', + 451226: '环江毛南族自治县', + 451227: '巴马瑶族自治县', + 451228: '都安瑶族自治县', + 451229: '大化瑶族自治县', + 451300: '来宾市', + 451301: '来宾市市辖区', + 451302: '兴宾区', + 451321: '忻城县', + 451322: '象州县', + 451323: '武宣县', + 451324: '金秀瑶族自治县', + 451381: '合山市', + 451400: '崇左市', + 451401: '崇左市市辖区', + 451402: '江州区', + 451421: '扶绥县', + 451422: '宁明县', + 451423: '龙州县', + 451424: '大新县', + 451425: '天等县', + 451481: '凭祥市', + 460000: '海南省', + 460100: '海口市', + 460101: '海口市市辖区', + 460105: '秀英区', + 460106: '龙华区', + 460107: '琼山区', + 460108: '美兰区', + 460200: '三亚市', + 460201: '三亚市市辖区', + 460202: '海棠区', + 460203: '吉阳区', + 460204: '天涯区', + 460205: '崖州区', + 460300: '三沙市', + 460301: '三沙市市辖区', + 460321: '西沙群岛', + 460322: '南沙群岛', + 460323: '中沙群岛的岛礁及其海域', + 460400: '儋州市', + 469001: '五指山市', + 469002: '琼海市', + 469005: '文昌市', + 469006: '万宁市', + 469007: '东方市', + 469021: '定安县', + 469022: '屯昌县', + 469023: '澄迈县', + 469024: '临高县', + 469025: '白沙黎族自治县', + 469026: '昌江黎族自治县', + 469027: '乐东黎族自治县', + 469028: '陵水黎族自治县', + 469029: '保亭黎族苗族自治县', + 469030: '琼中黎族苗族自治县', + 500000: '重庆市', + 500100: '重庆市市辖区', + 500101: '万州区', + 500102: '涪陵区', + 500103: '渝中区', + 500104: '大渡口区', + 500105: '江北区', + 500106: '沙坪坝区', + 500107: '九龙坡区', + 500108: '南岸区', + 500109: '北碚区', + 500110: '綦江区', + 500111: '大足区', + 500112: '渝北区', + 500113: '巴南区', + 500114: '黔江区', + 500115: '长寿区', + 500116: '江津区', + 500117: '合川区', + 500118: '永川区', + 500119: '南川区', + 500120: '璧山区', + 500151: '铜梁区', + 500152: '潼南区', + 500153: '荣昌区', + 500154: '开州区', + 500155: '梁平区', + 500156: '武隆区', + 500200: '重庆市郊县', + 500229: '城口县', + 500230: '丰都县', + 500231: '垫江县', + 500233: '忠县', + 500235: '云阳县', + 500236: '奉节县', + 500237: '巫山县', + 500238: '巫溪县', + 500240: '石柱土家族自治县', + 500241: '秀山土家族苗族自治县', + 500242: '酉阳土家族苗族自治县', + 500243: '彭水苗族土家族自治县', + 510000: '四川省', + 510100: '成都市', + 510101: '成都市市辖区', + 510104: '锦江区', + 510105: '青羊区', + 510106: '金牛区', + 510107: '武侯区', + 510108: '成华区', + 510112: '龙泉驿区', + 510113: '青白江区', + 510114: '新都区', + 510115: '温江区', + 510116: '双流区', + 510117: '郫都区', + 510121: '金堂县', + 510129: '大邑县', + 510131: '蒲江县', + 510132: '新津县', + 510181: '都江堰市', + 510182: '彭州市', + 510183: '邛崃市', + 510184: '崇州市', + 510185: '简阳市', + 510300: '自贡市', + 510301: '自贡市市辖区', + 510302: '自流井区', + 510303: '贡井区', + 510304: '大安区', + 510311: '沿滩区', + 510321: '荣县', + 510322: '富顺县', + 510400: '攀枝花市', + 510401: '攀枝花市市辖区', + 510402: '东区', + 510403: '西区', + 510411: '仁和区', + 510421: '米易县', + 510422: '盐边县', + 510500: '泸州市', + 510501: '泸州市市辖区', + 510502: '江阳区', + 510503: '纳溪区', + 510504: '龙马潭区', + 510521: '泸县', + 510522: '合江县', + 510524: '叙永县', + 510525: '古蔺县', + 510600: '德阳市', + 510601: '德阳市市辖区', + 510603: '旌阳区', + 510604: '罗江区', + 510623: '中江县', + 510681: '广汉市', + 510682: '什邡市', + 510683: '绵竹市', + 510700: '绵阳市', + 510701: '绵阳市市辖区', + 510703: '涪城区', + 510704: '游仙区', + 510705: '安州区', + 510722: '三台县', + 510723: '盐亭县', + 510725: '梓潼县', + 510726: '北川羌族自治县', + 510727: '平武县', + 510781: '江油市', + 510800: '广元市', + 510801: '广元市市辖区', + 510802: '利州区', + 510811: '昭化区', + 510812: '朝天区', + 510821: '旺苍县', + 510822: '青川县', + 510823: '剑阁县', + 510824: '苍溪县', + 510900: '遂宁市', + 510901: '遂宁市市辖区', + 510903: '船山区', + 510904: '安居区', + 510921: '蓬溪县', + 510922: '射洪县', + 510923: '大英县', + 511000: '内江市', + 511001: '内江市市辖区', + 511002: '市中区', + 511011: '东兴区', + 511024: '威远县', + 511025: '资中县', + 511083: '隆昌市', + 511100: '乐山市', + 511101: '乐山市市辖区', + 511102: '市中区', + 511111: '沙湾区', + 511112: '五通桥区', + 511113: '金口河区', + 511123: '犍为县', + 511124: '井研县', + 511126: '夹江县', + 511129: '沐川县', + 511132: '峨边彝族自治县', + 511133: '马边彝族自治县', + 511181: '峨眉山市', + 511300: '南充市', + 511301: '南充市市辖区', + 511302: '顺庆区', + 511303: '高坪区', + 511304: '嘉陵区', + 511321: '南部县', + 511322: '营山县', + 511323: '蓬安县', + 511324: '仪陇县', + 511325: '西充县', + 511381: '阆中市', + 511400: '眉山市', + 511401: '眉山市市辖区', + 511402: '东坡区', + 511403: '彭山区', + 511421: '仁寿县', + 511423: '洪雅县', + 511424: '丹棱县', + 511425: '青神县', + 511500: '宜宾市', + 511501: '宜宾市市辖区', + 511502: '翠屏区', + 511503: '南溪区', + 511504: '叙州区', + 511523: '江安县', + 511524: '长宁县', + 511525: '高县', + 511526: '珙县', + 511527: '筠连县', + 511528: '兴文县', + 511529: '屏山县', + 511600: '广安市', + 511601: '广安市市辖区', + 511602: '广安区', + 511603: '前锋区', + 511621: '岳池县', + 511622: '武胜县', + 511623: '邻水县', + 511681: '华蓥市', + 511700: '达州市', + 511701: '达州市市辖区', + 511702: '通川区', + 511703: '达川区', + 511722: '宣汉县', + 511723: '开江县', + 511724: '大竹县', + 511725: '渠县', + 511781: '万源市', + 511800: '雅安市', + 511801: '雅安市市辖区', + 511802: '雨城区', + 511803: '名山区', + 511822: '荥经县', + 511823: '汉源县', + 511824: '石棉县', + 511825: '天全县', + 511826: '芦山县', + 511827: '宝兴县', + 511900: '巴中市', + 511901: '巴中市市辖区', + 511902: '巴州区', + 511903: '恩阳区', + 511921: '通江县', + 511922: '南江县', + 511923: '平昌县', + 512000: '资阳市', + 512001: '资阳市市辖区', + 512002: '雁江区', + 512021: '安岳县', + 512022: '乐至县', + 513200: '阿坝藏族羌族自治州', + 513201: '马尔康市', + 513221: '汶川县', + 513222: '理县', + 513223: '茂县', + 513224: '松潘县', + 513225: '九寨沟县', + 513226: '金川县', + 513227: '小金县', + 513228: '黑水县', + 513230: '壤塘县', + 513231: '阿坝县', + 513232: '若尔盖县', + 513233: '红原县', + 513300: '甘孜藏族自治州', + 513301: '康定市', + 513322: '泸定县', + 513323: '丹巴县', + 513324: '九龙县', + 513325: '雅江县', + 513326: '道孚县', + 513327: '炉霍县', + 513328: '甘孜县', + 513329: '新龙县', + 513330: '德格县', + 513331: '白玉县', + 513332: '石渠县', + 513333: '色达县', + 513334: '理塘县', + 513335: '巴塘县', + 513336: '乡城县', + 513337: '稻城县', + 513338: '得荣县', + 513400: '凉山彝族自治州', + 513401: '西昌市', + 513422: '木里藏族自治县', + 513423: '盐源县', + 513424: '德昌县', + 513425: '会理县', + 513426: '会东县', + 513427: '宁南县', + 513428: '普格县', + 513429: '布拖县', + 513430: '金阳县', + 513431: '昭觉县', + 513432: '喜德县', + 513433: '冕宁县', + 513434: '越西县', + 513435: '甘洛县', + 513436: '美姑县', + 513437: '雷波县', + 520000: '贵州省', + 520100: '贵阳市', + 520101: '贵阳市市辖区', + 520102: '南明区', + 520103: '云岩区', + 520111: '花溪区', + 520112: '乌当区', + 520113: '白云区', + 520115: '观山湖区', + 520121: '开阳县', + 520122: '息烽县', + 520123: '修文县', + 520181: '清镇市', + 520200: '六盘水市', + 520201: '钟山区', + 520203: '六枝特区', + 520221: '水城县', + 520281: '盘州市', + 520300: '遵义市', + 520301: '遵义市市辖区', + 520302: '红花岗区', + 520303: '汇川区', + 520304: '播州区', + 520322: '桐梓县', + 520323: '绥阳县', + 520324: '正安县', + 520325: '道真仡佬族苗族自治县', + 520326: '务川仡佬族苗族自治县', + 520327: '凤冈县', + 520328: '湄潭县', + 520329: '余庆县', + 520330: '习水县', + 520381: '赤水市', + 520382: '仁怀市', + 520400: '安顺市', + 520401: '安顺市市辖区', + 520402: '西秀区', + 520403: '平坝区', + 520422: '普定县', + 520423: '镇宁布依族苗族自治县', + 520424: '关岭布依族苗族自治县', + 520425: '紫云苗族布依族自治县', + 520500: '毕节市', + 520502: '七星关区', + 520521: '大方县', + 520522: '黔西县', + 520523: '金沙县', + 520524: '织金县', + 520525: '纳雍县', + 520526: '威宁彝族回族苗族自治县', + 520527: '赫章县', + 520600: '铜仁市', + 520602: '碧江区', + 520603: '万山区', + 520621: '江口县', + 520622: '玉屏侗族自治县', + 520623: '石阡县', + 520624: '思南县', + 520625: '印江土家族苗族自治县', + 520626: '德江县', + 520627: '沿河土家族自治县', + 520628: '松桃苗族自治县', + 522300: '黔西南布依族苗族自治州', + 522301: '兴义市', + 522302: '兴仁市', + 522323: '普安县', + 522324: '晴隆县', + 522325: '贞丰县', + 522326: '望谟县', + 522327: '册亨县', + 522328: '安龙县', + 522600: '黔东南苗族侗族自治州', + 522601: '凯里市', + 522622: '黄平县', + 522623: '施秉县', + 522624: '三穗县', + 522625: '镇远县', + 522626: '岑巩县', + 522627: '天柱县', + 522628: '锦屏县', + 522629: '剑河县', + 522630: '台江县', + 522631: '黎平县', + 522632: '榕江县', + 522633: '从江县', + 522634: '雷山县', + 522635: '麻江县', + 522636: '丹寨县', + 522700: '黔南布依族苗族自治州', + 522701: '都匀市', + 522702: '福泉市', + 522722: '荔波县', + 522723: '贵定县', + 522725: '瓮安县', + 522726: '独山县', + 522727: '平塘县', + 522728: '罗甸县', + 522729: '长顺县', + 522730: '龙里县', + 522731: '惠水县', + 522732: '三都水族自治县', + 530000: '云南省', + 530100: '昆明市', + 530101: '昆明市市辖区', + 530102: '五华区', + 530103: '盘龙区', + 530111: '官渡区', + 530112: '西山区', + 530113: '东川区', + 530114: '呈贡区', + 530115: '晋宁区', + 530124: '富民县', + 530125: '宜良县', + 530126: '石林彝族自治县', + 530127: '嵩明县', + 530128: '禄劝彝族苗族自治县', + 530129: '寻甸回族彝族自治县', + 530181: '安宁市', + 530300: '曲靖市', + 530301: '曲靖市市辖区', + 530302: '麒麟区', + 530303: '沾益区', + 530304: '马龙区', + 530322: '陆良县', + 530323: '师宗县', + 530324: '罗平县', + 530325: '富源县', + 530326: '会泽县', + 530381: '宣威市', + 530400: '玉溪市', + 530401: '玉溪市市辖区', + 530402: '红塔区', + 530403: '江川区', + 530422: '澄江县', + 530423: '通海县', + 530424: '华宁县', + 530425: '易门县', + 530426: '峨山彝族自治县', + 530427: '新平彝族傣族自治县', + 530428: '元江哈尼族彝族傣族自治县', + 530500: '保山市', + 530501: '保山市市辖区', + 530502: '隆阳区', + 530521: '施甸县', + 530523: '龙陵县', + 530524: '昌宁县', + 530581: '腾冲市', + 530600: '昭通市', + 530601: '昭通市市辖区', + 530602: '昭阳区', + 530621: '鲁甸县', + 530622: '巧家县', + 530623: '盐津县', + 530624: '大关县', + 530625: '永善县', + 530626: '绥江县', + 530627: '镇雄县', + 530628: '彝良县', + 530629: '威信县', + 530681: '水富市', + 530700: '丽江市', + 530701: '丽江市市辖区', + 530702: '古城区', + 530721: '玉龙纳西族自治县', + 530722: '永胜县', + 530723: '华坪县', + 530724: '宁蒗彝族自治县', + 530800: '普洱市', + 530801: '普洱市市辖区', + 530802: '思茅区', + 530821: '宁洱哈尼族彝族自治县', + 530822: '墨江哈尼族自治县', + 530823: '景东彝族自治县', + 530824: '景谷傣族彝族自治县', + 530825: '镇沅彝族哈尼族拉祜族自治县', + 530826: '江城哈尼族彝族自治县', + 530827: '孟连傣族拉祜族佤族自治县', + 530828: '澜沧拉祜族自治县', + 530829: '西盟佤族自治县', + 530900: '临沧市', + 530901: '临沧市市辖区', + 530902: '临翔区', + 530921: '凤庆县', + 530922: '云县', + 530923: '永德县', + 530924: '镇康县', + 530925: '双江拉祜族佤族布朗族傣族自治县', + 530926: '耿马傣族佤族自治县', + 530927: '沧源佤族自治县', + 532300: '楚雄彝族自治州', + 532301: '楚雄市', + 532322: '双柏县', + 532323: '牟定县', + 532324: '南华县', + 532325: '姚安县', + 532326: '大姚县', + 532327: '永仁县', + 532328: '元谋县', + 532329: '武定县', + 532331: '禄丰县', + 532500: '红河哈尼族彝族自治州', + 532501: '个旧市', + 532502: '开远市', + 532503: '蒙自市', + 532504: '弥勒市', + 532523: '屏边苗族自治县', + 532524: '建水县', + 532525: '石屏县', + 532527: '泸西县', + 532528: '元阳县', + 532529: '红河县', + 532530: '金平苗族瑶族傣族自治县', + 532531: '绿春县', + 532532: '河口瑶族自治县', + 532600: '文山壮族苗族自治州', + 532601: '文山市', + 532622: '砚山县', + 532623: '西畴县', + 532624: '麻栗坡县', + 532625: '马关县', + 532626: '丘北县', + 532627: '广南县', + 532628: '富宁县', + 532800: '西双版纳傣族自治州', + 532801: '景洪市', + 532822: '勐海县', + 532823: '勐腊县', + 532900: '大理白族自治州', + 532901: '大理市', + 532922: '漾濞彝族自治县', + 532923: '祥云县', + 532924: '宾川县', + 532925: '弥渡县', + 532926: '南涧彝族自治县', + 532927: '巍山彝族回族自治县', + 532928: '永平县', + 532929: '云龙县', + 532930: '洱源县', + 532931: '剑川县', + 532932: '鹤庆县', + 533100: '德宏傣族景颇族自治州', + 533102: '瑞丽市', + 533103: '芒市', + 533122: '梁河县', + 533123: '盈江县', + 533124: '陇川县', + 533300: '怒江傈僳族自治州', + 533301: '泸水市', + 533323: '福贡县', + 533324: '贡山独龙族怒族自治县', + 533325: '兰坪白族普米族自治县', + 533400: '迪庆藏族自治州', + 533401: '香格里拉市', + 533422: '德钦县', + 533423: '维西傈僳族自治县', + 540000: '西藏自治区', + 540100: '拉萨市', + 540101: '拉萨市市辖区', + 540102: '城关区', + 540103: '堆龙德庆区', + 540104: '达孜区', + 540121: '林周县', + 540122: '当雄县', + 540123: '尼木县', + 540124: '曲水县', + 540127: '墨竹工卡县', + 540200: '日喀则市', + 540202: '桑珠孜区', + 540221: '南木林县', + 540222: '江孜县', + 540223: '定日县', + 540224: '萨迦县', + 540225: '拉孜县', + 540226: '昂仁县', + 540227: '谢通门县', + 540228: '白朗县', + 540229: '仁布县', + 540230: '康马县', + 540231: '定结县', + 540232: '仲巴县', + 540233: '亚东县', + 540234: '吉隆县', + 540235: '聂拉木县', + 540236: '萨嘎县', + 540237: '岗巴县', + 540300: '昌都市', + 540302: '卡若区', + 540321: '江达县', + 540322: '贡觉县', + 540323: '类乌齐县', + 540324: '丁青县', + 540325: '察雅县', + 540326: '八宿县', + 540327: '左贡县', + 540328: '芒康县', + 540329: '洛隆县', + 540330: '边坝县', + 540400: '林芝市', + 540402: '巴宜区', + 540421: '工布江达县', + 540422: '米林县', + 540423: '墨脱县', + 540424: '波密县', + 540425: '察隅县', + 540426: '朗县', + 540500: '山南市', + 540502: '乃东区', + 540521: '扎囊县', + 540522: '贡嘎县', + 540523: '桑日县', + 540524: '琼结县', + 540525: '曲松县', + 540526: '措美县', + 540527: '洛扎县', + 540528: '加查县', + 540529: '隆子县', + 540530: '错那县', + 540531: '浪卡子县', + 540600: '那曲市', + 540602: '色尼区', + 540621: '嘉黎县', + 540622: '比如县', + 540623: '聂荣县', + 540624: '安多县', + 540625: '申扎县', + 540626: '索县', + 540627: '班戈县', + 540628: '巴青县', + 540629: '尼玛县', + 540630: '双湖县', + 542500: '阿里地区', + 542521: '普兰县', + 542522: '札达县', + 542523: '噶尔县', + 542524: '日土县', + 542525: '革吉县', + 542526: '改则县', + 542527: '措勤县', + 610000: '陕西省', + 610100: '西安市', + 610101: '西安市市辖区', + 610102: '新城区', + 610103: '碑林区', + 610104: '莲湖区', + 610111: '灞桥区', + 610112: '未央区', + 610113: '雁塔区', + 610114: '阎良区', + 610115: '临潼区', + 610116: '长安区', + 610117: '高陵区', + 610118: '鄠邑区', + 610122: '蓝田县', + 610124: '周至县', + 610200: '铜川市', + 610201: '铜川市市辖区', + 610202: '王益区', + 610203: '印台区', + 610204: '耀州区', + 610222: '宜君县', + 610300: '宝鸡市', + 610301: '宝鸡市市辖区', + 610302: '渭滨区', + 610303: '金台区', + 610304: '陈仓区', + 610322: '凤翔县', + 610323: '岐山县', + 610324: '扶风县', + 610326: '眉县', + 610327: '陇县', + 610328: '千阳县', + 610329: '麟游县', + 610330: '凤县', + 610331: '太白县', + 610400: '咸阳市', + 610401: '咸阳市市辖区', + 610402: '秦都区', + 610403: '杨陵区', + 610404: '渭城区', + 610422: '三原县', + 610423: '泾阳县', + 610424: '乾县', + 610425: '礼泉县', + 610426: '永寿县', + 610428: '长武县', + 610429: '旬邑县', + 610430: '淳化县', + 610431: '武功县', + 610481: '兴平市', + 610482: '彬州市', + 610500: '渭南市', + 610501: '渭南市市辖区', + 610502: '临渭区', + 610503: '华州区', + 610522: '潼关县', + 610523: '大荔县', + 610524: '合阳县', + 610525: '澄城县', + 610526: '蒲城县', + 610527: '白水县', + 610528: '富平县', + 610581: '韩城市', + 610582: '华阴市', + 610600: '延安市', + 610601: '延安市市辖区', + 610602: '宝塔区', + 610603: '安塞区', + 610621: '延长县', + 610622: '延川县', + 610623: '子长县', + 610625: '志丹县', + 610626: '吴起县', + 610627: '甘泉县', + 610628: '富县', + 610629: '洛川县', + 610630: '宜川县', + 610631: '黄龙县', + 610632: '黄陵县', + 610700: '汉中市', + 610701: '汉中市市辖区', + 610702: '汉台区', + 610703: '南郑区', + 610722: '城固县', + 610723: '洋县', + 610724: '西乡县', + 610725: '勉县', + 610726: '宁强县', + 610727: '略阳县', + 610728: '镇巴县', + 610729: '留坝县', + 610730: '佛坪县', + 610800: '榆林市', + 610801: '榆林市市辖区', + 610802: '榆阳区', + 610803: '横山区', + 610822: '府谷县', + 610824: '靖边县', + 610825: '定边县', + 610826: '绥德县', + 610827: '米脂县', + 610828: '佳县', + 610829: '吴堡县', + 610830: '清涧县', + 610831: '子洲县', + 610881: '神木市', + 610900: '安康市', + 610901: '安康市市辖区', + 610902: '汉滨区', + 610921: '汉阴县', + 610922: '石泉县', + 610923: '宁陕县', + 610924: '紫阳县', + 610925: '岚皋县', + 610926: '平利县', + 610927: '镇坪县', + 610928: '旬阳县', + 610929: '白河县', + 611000: '商洛市', + 611001: '商洛市市辖区', + 611002: '商州区', + 611021: '洛南县', + 611022: '丹凤县', + 611023: '商南县', + 611024: '山阳县', + 611025: '镇安县', + 611026: '柞水县', + 620000: '甘肃省', + 620100: '兰州市', + 620101: '兰州市市辖区', + 620102: '城关区', + 620103: '七里河区', + 620104: '西固区', + 620105: '安宁区', + 620111: '红古区', + 620121: '永登县', + 620122: '皋兰县', + 620123: '榆中县', + 620200: '嘉峪关市', + 620201: '嘉峪关市市辖区', + 620300: '金昌市', + 620301: '金昌市市辖区', + 620302: '金川区', + 620321: '永昌县', + 620400: '白银市', + 620401: '白银市市辖区', + 620402: '白银区', + 620403: '平川区', + 620421: '靖远县', + 620422: '会宁县', + 620423: '景泰县', + 620500: '天水市', + 620501: '天水市市辖区', + 620502: '秦州区', + 620503: '麦积区', + 620521: '清水县', + 620522: '秦安县', + 620523: '甘谷县', + 620524: '武山县', + 620525: '张家川回族自治县', + 620600: '武威市', + 620601: '武威市市辖区', + 620602: '凉州区', + 620621: '民勤县', + 620622: '古浪县', + 620623: '天祝藏族自治县', + 620700: '张掖市', + 620701: '张掖市市辖区', + 620702: '甘州区', + 620721: '肃南裕固族自治县', + 620722: '民乐县', + 620723: '临泽县', + 620724: '高台县', + 620725: '山丹县', + 620800: '平凉市', + 620801: '平凉市市辖区', + 620802: '崆峒区', + 620821: '泾川县', + 620822: '灵台县', + 620823: '崇信县', + 620825: '庄浪县', + 620826: '静宁县', + 620881: '华亭市', + 620900: '酒泉市', + 620901: '酒泉市市辖区', + 620902: '肃州区', + 620921: '金塔县', + 620922: '瓜州县', + 620923: '肃北蒙古族自治县', + 620924: '阿克塞哈萨克族自治县', + 620981: '玉门市', + 620982: '敦煌市', + 621000: '庆阳市', + 621001: '庆阳市市辖区', + 621002: '西峰区', + 621021: '庆城县', + 621022: '环县', + 621023: '华池县', + 621024: '合水县', + 621025: '正宁县', + 621026: '宁县', + 621027: '镇原县', + 621100: '定西市', + 621101: '定西市市辖区', + 621102: '安定区', + 621121: '通渭县', + 621122: '陇西县', + 621123: '渭源县', + 621124: '临洮县', + 621125: '漳县', + 621126: '岷县', + 621200: '陇南市', + 621201: '陇南市市辖区', + 621202: '武都区', + 621221: '成县', + 621222: '文县', + 621223: '宕昌县', + 621224: '康县', + 621225: '西和县', + 621226: '礼县', + 621227: '徽县', + 621228: '两当县', + 622900: '临夏回族自治州', + 622901: '临夏市', + 622921: '临夏县', + 622922: '康乐县', + 622923: '永靖县', + 622924: '广河县', + 622925: '和政县', + 622926: '东乡族自治县', + 622927: '积石山保安族东乡族撒拉族自治县', + 623000: '甘南藏族自治州', + 623001: '合作市', + 623021: '临潭县', + 623022: '卓尼县', + 623023: '舟曲县', + 623024: '迭部县', + 623025: '玛曲县', + 623026: '碌曲县', + 623027: '夏河县', + 630000: '青海省', + 630100: '西宁市', + 630101: '西宁市市辖区', + 630102: '城东区', + 630103: '城中区', + 630104: '城西区', + 630105: '城北区', + 630121: '大通回族土族自治县', + 630122: '湟中县', + 630123: '湟源县', + 630200: '海东市', + 630202: '乐都区', + 630203: '平安区', + 630222: '民和回族土族自治县', + 630223: '互助土族自治县', + 630224: '化隆回族自治县', + 630225: '循化撒拉族自治县', + 632200: '海北藏族自治州', + 632221: '门源回族自治县', + 632222: '祁连县', + 632223: '海晏县', + 632224: '刚察县', + 632300: '黄南藏族自治州', + 632321: '同仁县', + 632322: '尖扎县', + 632323: '泽库县', + 632324: '河南蒙古族自治县', + 632500: '海南藏族自治州', + 632521: '共和县', + 632522: '同德县', + 632523: '贵德县', + 632524: '兴海县', + 632525: '贵南县', + 632600: '果洛藏族自治州', + 632621: '玛沁县', + 632622: '班玛县', + 632623: '甘德县', + 632624: '达日县', + 632625: '久治县', + 632626: '玛多县', + 632700: '玉树藏族自治州', + 632701: '玉树市', + 632722: '杂多县', + 632723: '称多县', + 632724: '治多县', + 632725: '囊谦县', + 632726: '曲麻莱县', + 632800: '海西蒙古族藏族自治州', + 632801: '格尔木市', + 632802: '德令哈市', + 632803: '茫崖市', + 632821: '乌兰县', + 632822: '都兰县', + 632823: '天峻县', + 632825: '海西蒙古族藏族自治州直辖', + 640000: '宁夏回族自治区', + 640100: '银川市', + 640101: '银川市市辖区', + 640104: '兴庆区', + 640105: '西夏区', + 640106: '金凤区', + 640121: '永宁县', + 640122: '贺兰县', + 640181: '灵武市', + 640200: '石嘴山市', + 640201: '石嘴山市市辖区', + 640202: '大武口区', + 640205: '惠农区', + 640221: '平罗县', + 640300: '吴忠市', + 640301: '吴忠市市辖区', + 640302: '利通区', + 640303: '红寺堡区', + 640323: '盐池县', + 640324: '同心县', + 640381: '青铜峡市', + 640400: '固原市', + 640401: '固原市市辖区', + 640402: '原州区', + 640422: '西吉县', + 640423: '隆德县', + 640424: '泾源县', + 640425: '彭阳县', + 640500: '中卫市', + 640501: '中卫市市辖区', + 640502: '沙坡头区', + 640521: '中宁县', + 640522: '海原县', + 650000: '新疆维吾尔自治区', + 650100: '乌鲁木齐市', + 650101: '乌鲁木齐市市辖区', + 650102: '天山区', + 650103: '沙依巴克区', + 650104: '新市区', + 650105: '水磨沟区', + 650106: '头屯河区', + 650107: '达坂城区', + 650109: '米东区', + 650121: '乌鲁木齐县', + 650200: '克拉玛依市', + 650201: '克拉玛依市市辖区', + 650202: '独山子区', + 650203: '克拉玛依区', + 650204: '白碱滩区', + 650205: '乌尔禾区', + 650400: '吐鲁番市', + 650402: '高昌区', + 650421: '鄯善县', + 650422: '托克逊县', + 650500: '哈密市', + 650502: '伊州区', + 650521: '巴里坤哈萨克自治县', + 650522: '伊吾县', + 652300: '昌吉回族自治州', + 652301: '昌吉市', + 652302: '阜康市', + 652323: '呼图壁县', + 652324: '玛纳斯县', + 652325: '奇台县', + 652327: '吉木萨尔县', + 652328: '木垒哈萨克自治县', + 652700: '博尔塔拉蒙古自治州', + 652701: '博乐市', + 652702: '阿拉山口市', + 652722: '精河县', + 652723: '温泉县', + 652800: '巴音郭楞蒙古自治州', + 652801: '库尔勒市', + 652822: '轮台县', + 652823: '尉犁县', + 652824: '若羌县', + 652825: '且末县', + 652826: '焉耆回族自治县', + 652827: '和静县', + 652828: '和硕县', + 652829: '博湖县', + 652900: '阿克苏地区', + 652901: '阿克苏市', + 652922: '温宿县', + 652923: '库车县', + 652924: '沙雅县', + 652925: '新和县', + 652926: '拜城县', + 652927: '乌什县', + 652928: '阿瓦提县', + 652929: '柯坪县', + 653000: '克孜勒苏柯尔克孜自治州', + 653001: '阿图什市', + 653022: '阿克陶县', + 653023: '阿合奇县', + 653024: '乌恰县', + 653100: '喀什地区', + 653101: '喀什市', + 653121: '疏附县', + 653122: '疏勒县', + 653123: '英吉沙县', + 653124: '泽普县', + 653125: '莎车县', + 653126: '叶城县', + 653127: '麦盖提县', + 653128: '岳普湖县', + 653129: '伽师县', + 653130: '巴楚县', + 653131: '塔什库尔干塔吉克自治县', + 653200: '和田地区', + 653201: '和田市', + 653221: '和田县', + 653222: '墨玉县', + 653223: '皮山县', + 653224: '洛浦县', + 653225: '策勒县', + 653226: '于田县', + 653227: '民丰县', + 654000: '伊犁哈萨克自治州', + 654002: '伊宁市', + 654003: '奎屯市', + 654004: '霍尔果斯市', + 654021: '伊宁县', + 654022: '察布查尔锡伯自治县', + 654023: '霍城县', + 654024: '巩留县', + 654025: '新源县', + 654026: '昭苏县', + 654027: '特克斯县', + 654028: '尼勒克县', + 654200: '塔城地区', + 654201: '塔城市', + 654202: '乌苏市', + 654221: '额敏县', + 654223: '沙湾县', + 654224: '托里县', + 654225: '裕民县', + 654226: '和布克赛尔蒙古自治县', + 654300: '阿勒泰地区', + 654301: '阿勒泰市', + 654321: '布尔津县', + 654322: '富蕴县', + 654323: '福海县', + 654324: '哈巴河县', + 654325: '青河县', + 654326: '吉木乃县', + 659001: '石河子市', + 659002: '阿拉尔市', + 659003: '图木舒克市', + 659004: '五家渠市', + 659005: '北屯市', + 659006: '铁门关市', + 659007: '双河市', + 659008: '可克达拉市', + 659009: '昆玉市', + 710000: '台湾省', + 810000: '香港特别行政区', + 810001: '中西区', + 810002: '湾仔区', + 810003: '东区', + 810004: '南区', + 810005: '油尖旺区', + 810006: '深水埗区', + 810007: '九龙城区', + 810008: '黄大仙区', + 810009: '观塘区', + 810010: '荃湾区', + 810011: '屯门区', + 810012: '元朗区', + 810013: '北区', + 810014: '大埔区', + 810015: '西贡区', + 810016: '沙田区', + 810017: '葵青区', + 810018: '离岛区', + 820000: '澳门特别行政区', + 820001: '花地玛堂区', + 820002: '花王堂区', + 820003: '望德堂区', + 820004: '大堂区', + 820005: '风顺堂区', + 820006: '嘉模堂区', + 820007: '路凼填海区', + 820008: '圣方济各堂区' }; -export const province:Array = []; -export const city:{ - [propName:number]: Array +export const province: Array = []; +export const city: { + [propName: number]: Array; } = {}; -export const district:{ - [propName:number]: { - [propName:number]: Array - } | Array; +export const district: { + [propName: number]: + | { + [propName: number]: Array; + } + | Array; } = {}; Object.keys(db).forEach(key => { @@ -3557,7 +3559,7 @@ Object.keys(db).forEach(key => { } else if (!(code % 100)) { const provinceCode = code - (code % 10000); city[provinceCode].push(code); - district[provinceCode] = (district[provinceCode] || {}) + district[provinceCode] = district[provinceCode] || {}; district[provinceCode][code] = []; } else { const provinceCode = code - (code % 10000); @@ -3566,7 +3568,7 @@ Object.keys(db).forEach(key => { if (district[provinceCode] && Array.isArray(district[provinceCode][cityCode])) { (district[provinceCode][cityCode] as Array).push(code); } else if (!district[provinceCode] || Array.isArray(district[provinceCode])) { - district[provinceCode] = (district[provinceCode] || []); + district[provinceCode] = district[provinceCode] || []; (district[provinceCode] as Array).push(code); } else { city[provinceCode].push(code); @@ -3574,4 +3576,4 @@ Object.keys(db).forEach(key => { } }); -export default db; \ No newline at end of file +export default db; diff --git a/src/renderers/Form/Color.tsx b/src/renderers/Form/Color.tsx index f16d9398d..4974f6a1b 100644 --- a/src/renderers/Form/Color.tsx +++ b/src/renderers/Form/Color.tsx @@ -1,8 +1,5 @@ import React from 'react'; -import { - FormItem, - FormControlProps -} from './Item'; +import {FormItem, FormControlProps} from './Item'; import cx from 'classnames'; import ColorPicker from '../../components/ColorPicker'; @@ -10,43 +7,35 @@ export interface ColorProps extends FormControlProps { placeholder?: string; format?: string; timeConstrainst?: object; - closeOnSelect?:boolean; + closeOnSelect?: boolean; presetColors?: string[]; -}; +} export interface ColorControlState { open: boolean; -}; +} export default class ColorControl extends React.PureComponent { - static defaultProps:Partial = { + static defaultProps: Partial = { format: 'hex', clearable: true }; - state:ColorControlState = { + state: ColorControlState = { open: false }; - + render() { - const { - className, - classPrefix: ns, - ...rest - } = this.props; + const {className, classPrefix: ns, ...rest} = this.props; return (
    - +
    ); } } @FormItem({ - type: 'color', + type: 'color' }) -export class ColorControlRenderer extends ColorControl {}; - +export class ColorControlRenderer extends ColorControl {} diff --git a/src/renderers/Form/Combo.tsx b/src/renderers/Form/Combo.tsx index 7e8e16a6e..7cbb9e0a3 100644 --- a/src/renderers/Form/Combo.tsx +++ b/src/renderers/Form/Combo.tsx @@ -1,28 +1,17 @@ import React from 'react'; -import { - findDOMNode -} from 'react-dom'; -import { - FormItem, - FormControlProps -} from './Item'; -import { Schema, Action, Api } from '../../types'; +import {findDOMNode} from 'react-dom'; +import {FormItem, FormControlProps} from './Item'; +import {Schema, Action, Api} from '../../types'; import {ComboStore, IComboStore} from '../../store/combo'; -import { default as CTabs, Tab } from '../../components/Tabs'; +import {default as CTabs, Tab} from '../../components/Tabs'; -import { - guid, - anyChanged, - isObject, - createObject, - extendObject, - autobind} from '../../utils/helper'; +import {guid, anyChanged, isObject, createObject, extendObject, autobind} from '../../utils/helper'; import Sortable = require('sortablejs'); -import { evalExpression, filter } from '../../utils/tpl'; +import {evalExpression, filter} from '../../utils/tpl'; import find = require('lodash/find'); import Select from '../../components/Select'; -import { dataMapping } from '../../utils/tpl-builtin'; -import { isEffectiveApi } from '../../utils/api'; +import {dataMapping} from '../../utils/tpl-builtin'; +import {isEffectiveApi} from '../../utils/api'; export interface Condition { test: string; @@ -49,14 +38,14 @@ export interface ComboProps extends FormControlProps { addable?: boolean; typeSwitchable?: boolean; removable?: boolean; - deleteApi?: Api, + deleteApi?: Api; deleteConfirmText?: string; canAccessSuperData?: boolean; subFormMode?: 'normal' | 'inline' | 'horizontal'; noBorder?: boolean; joinValues?: boolean; delimiter?: string; - dragIcon: string, + dragIcon: string; deleteIcon: string; store: IComboStore; tabsMode: boolean; @@ -66,8 +55,8 @@ export interface ComboProps extends FormControlProps { validateFailed?: string; minLengthValidateFailed?: string; maxLengthValidateFailed?: string; - } -}; + }; +} export default class ComboControl extends React.Component { static defaultProps = { @@ -88,32 +77,32 @@ export default class ComboControl extends React.Component { tabsStyle: '' }; static propsList: Array = [ - "minLength", - "maxLength", - "multiple", - "multiLine", - "addButtonClassName", - "subFormMode", - "draggableTip", - "addButtonText", - "draggable", - "scaffold", - "canAccessSuperData", - "addIcon", - "dragIcon", - "deleteIcon", - "noBorder", - "conditions", - "tabsMode", - "tabsStyle" + 'minLength', + 'maxLength', + 'multiple', + 'multiLine', + 'addButtonClassName', + 'subFormMode', + 'draggableTip', + 'addButtonText', + 'draggable', + 'scaffold', + 'canAccessSuperData', + 'addIcon', + 'dragIcon', + 'deleteIcon', + 'noBorder', + 'conditions', + 'tabsMode', + 'tabsStyle' ]; - subForms:Array = []; + subForms: Array = []; keys: Array = []; dragTip?: HTMLElement; sortable?: Sortable; defaultValue?: any; - constructor(props:ComboProps) { + constructor(props: ComboProps) { super(props); this.handleChange = this.handleChange.bind(this); @@ -130,34 +119,24 @@ export default class ComboControl extends React.Component { } componentWillMount() { - const { - store, - value, - minLength, - maxLength, - formItem - } = this.props; + const {store, value, minLength, maxLength, formItem} = this.props; store.config({ minLength, maxLength, - length: this.getValueAsArray().length, + length: this.getValueAsArray().length }); formItem && formItem.setSubStore(store); } - componentWillReceiveProps(nextProps:ComboProps) { + componentWillReceiveProps(nextProps: ComboProps) { const props = this.props; if (anyChanged(['minLength', 'maxLength', 'value'], props, nextProps)) { - const { - store, - minLength, - maxLength - } = nextProps; + const {store, minLength, maxLength} = nextProps; const values = this.getValueAsArray(nextProps); - + store.config({ minLength, maxLength, @@ -171,19 +150,13 @@ export default class ComboControl extends React.Component { } componentWillUnmount() { - const { - formItem - } = this.props; + const {formItem} = this.props; formItem && formItem.setSubStore(null); } getValueAsArray(props = this.props) { - const { - flat, - joinValues, - delimiter, - } = props; + const {flat, joinValues, delimiter} = props; let value = props.value; if (joinValues && flat && typeof value === 'string') { @@ -196,14 +169,8 @@ export default class ComboControl extends React.Component { return value; } - addItemWith(condition:Condition) { - const { - flat, - joinValues, - delimiter, - scaffold, - disabled - } = this.props; + addItemWith(condition: Condition) { + const {flat, joinValues, delimiter, scaffold, disabled} = this.props; if (disabled) { return; @@ -211,9 +178,13 @@ export default class ComboControl extends React.Component { let value = this.getValueAsArray(); - value.push(flat ? condition.scaffold || scaffold || '' : { - ...condition.scaffold || scaffold - }); + value.push( + flat + ? condition.scaffold || scaffold || '' + : { + ...(condition.scaffold || scaffold) + } + ); this.keys.push(guid()); if (flat && joinValues) { @@ -224,13 +195,7 @@ export default class ComboControl extends React.Component { } addItem() { - const { - flat, - joinValues, - delimiter, - scaffold, - disabled - } = this.props; + const {flat, joinValues, delimiter, scaffold, disabled} = this.props; if (disabled) { return; @@ -238,9 +203,13 @@ export default class ComboControl extends React.Component { let value = this.getValueAsArray(); - value.push(flat ? scaffold || '' : { - ...scaffold - }); + value.push( + flat + ? scaffold || '' + : { + ...scaffold + } + ); this.keys.push(guid()); if (flat && joinValues) { @@ -250,17 +219,8 @@ export default class ComboControl extends React.Component { this.props.onChange(value); } - async removeItem(key:number) { - const { - flat, - joinValues, - delimiter, - disabled, - deleteApi, - deleteConfirmText, - data, - env - } = this.props; + async removeItem(key: number) { + const {flat, joinValues, delimiter, disabled, deleteApi, deleteConfirmText, data, env} = this.props; if (disabled) { return; @@ -268,11 +228,11 @@ export default class ComboControl extends React.Component { let value = this.getValueAsArray(); const ctx = createObject(data, value[key]); - + if (isEffectiveApi(deleteApi, ctx)) { - - const confirmed = await env.confirm(deleteConfirmText ? filter(deleteConfirmText, ctx): '确认要删除?') - if (!confirmed) { // 如果不确认,则跳过! + const confirmed = await env.confirm(deleteConfirmText ? filter(deleteConfirmText, ctx) : '确认要删除?'); + if (!confirmed) { + // 如果不确认,则跳过! return; } @@ -294,16 +254,8 @@ export default class ComboControl extends React.Component { this.props.onChange(value); } - handleChange(index:number, values: any) { - const { - formItem, - flat, - store, - joinValues, - delimiter, - disabled, - validateOnChange - } = this.props; + handleChange(index: number, values: any) { + const {formItem, flat, store, joinValues, delimiter, disabled, validateOnChange} = this.props; if (disabled) { return; @@ -325,22 +277,22 @@ export default class ComboControl extends React.Component { store.forms.forEach(item => item.items.forEach(item => item.unique && item.syncOptions())); } - handleSingleFormChange(values:object) { + handleSingleFormChange(values: object) { this.props.onChange({ ...values }); } - handleSingleFormInit(values:any) { - this.props.syncDefaultValue !== false && this.props.setPrinstineValue && this.props.setPrinstineValue({ - ...values - }); + handleSingleFormInit(values: any) { + this.props.syncDefaultValue !== false && + this.props.setPrinstineValue && + this.props.setPrinstineValue({ + ...values + }); } - handleAction(action: Action):any { - const { - onAction - } = this.props; + handleAction(action: Action): any { + const {onAction} = this.props; if (action.actionType === 'delete') { action.index !== void 0 && this.removeItem(action.index); @@ -350,37 +302,35 @@ export default class ComboControl extends React.Component { onAction && onAction.apply(null, arguments); } - validate():any { - - const { - value, - minLength, - maxLength, - messages - } = this.props; + validate(): any { + const {value, minLength, maxLength, messages} = this.props; if (minLength && (!Array.isArray(value) || value.length < minLength)) { - return messages && messages.minLengthValidateFailed || `组合表单成员数量不够,低于设定的最小${minLength}个,请添加更多的成员。`; + return ( + (messages && messages.minLengthValidateFailed) || + `组合表单成员数量不够,低于设定的最小${minLength}个,请添加更多的成员。` + ); } else if (maxLength && Array.isArray(value) && value.length > maxLength) { - return messages && messages.maxLengthValidateFailed || `组合表单成员数量超出,超出设定的最大${maxLength}个,请删除多余的成员。`; + return ( + (messages && messages.maxLengthValidateFailed) || + `组合表单成员数量超出,超出设定的最大${maxLength}个,请删除多余的成员。` + ); } else if (this.subForms.length) { - return Promise - .all(this.subForms.map(item => item.validate())) - .then((values) => { - if (~values.indexOf(false)) { - return messages && messages.validateFailed || '子表单验证失败,请仔细检查'; - } + return Promise.all(this.subForms.map(item => item.validate())).then(values => { + if (~values.indexOf(false)) { + return (messages && messages.validateFailed) || '子表单验证失败,请仔细检查'; + } - return; - }) + return; + }); } } - dragTipRef(ref:any) { + dragTipRef(ref: any) { if (!this.dragTip && ref) { this.initDragging(); } else if (this.dragTip && !ref) { - this.destroyDragging() + this.destroyDragging(); } this.dragTip = ref; @@ -394,7 +344,7 @@ export default class ComboControl extends React.Component { animation: 150, handle: `.${ns}Combo-itemDrager`, ghostClass: `${ns}Combo-item--dragging`, - onEnd: (e:any) => { + onEnd: (e: any) => { // 没有移动 if (e.newIndex === e.oldIndex) { return; @@ -402,7 +352,7 @@ export default class ComboControl extends React.Component { // 换回来 const parent = e.to as HTMLElement; - if (e.oldIndex < parent.childNodes.length -1) { + if (e.oldIndex < parent.childNodes.length - 1) { parent.insertBefore(e.item, parent.childNodes[e.oldIndex]); } else { parent.appendChild(e.item); @@ -424,7 +374,7 @@ export default class ComboControl extends React.Component { this.sortable && this.sortable.destroy(); } - formRef(ref:any, index:number = 0) { + formRef(ref: any, index: number = 0) { if (ref) { while (ref && ref.getWrappedInstance) { ref = ref.getWrappedInstance(); @@ -435,11 +385,8 @@ export default class ComboControl extends React.Component { } } - formatValue(value:any, index:number) { - const { - flat, - data - } = this.props; + formatValue(value: any, index: number) { + const {flat, data} = this.props; if (flat) { value = { @@ -451,22 +398,17 @@ export default class ComboControl extends React.Component { return createObject(extendObject(data, {index, __index: index, ...data}), value); } - pickCondition(value:any):Condition { - const conditions:Array = this.props.conditions as Array; - return (find(conditions, (item) => item.test && evalExpression(item.test, value)) || conditions[0]) as Condition; + pickCondition(value: any): Condition { + const conditions: Array = this.props.conditions as Array; + return (find(conditions, item => item.test && evalExpression(item.test, value)) || conditions[0]) as Condition; } - handleComboTypeChange(index:number, selection:any) { - const { - multiple, - onChange, - value, - flat - } = this.props; + handleComboTypeChange(index: number, selection: any) { + const {multiple, onChange, value, flat} = this.props; - const conditions:Array = this.props.conditions as Array; + const conditions: Array = this.props.conditions as Array; const condition = find(conditions, item => item.label === selection.label); - + if (!condition) { return; } @@ -487,18 +429,14 @@ export default class ComboControl extends React.Component { } @autobind - handleTabSelect(key:number) { - const { - store - } = this.props; + handleTabSelect(key: number) { + const {store} = this.props; store.setActiveKey(key); } renderPlaceholder() { - return ( - {this.props.placeholder || '没有数据'} - ); + return {this.props.placeholder || '没有数据'}; } renderTabsMode() { @@ -532,9 +470,10 @@ export default class ComboControl extends React.Component { value = value.split(delimiter || ','); } - const finnalRemovable = store.removable !== false // minLength ? - && !disabled // 控件自身是否禁用 - && removable !== false; // 是否可以删除 + const finnalRemovable = + store.removable !== false && // minLength ? + !disabled && // 控件自身是否禁用 + removable !== false; // 是否可以删除 if (!Array.isArray(value)) { return this.renderPlaceholder(); @@ -547,58 +486,64 @@ export default class ComboControl extends React.Component { mode={tabsStyle} activeKey={store.activeKey} handleSelect={this.handleTabSelect} - additionBtns={!disabled ? ( -
  • - {store.addable && addable !== false ? Array.isArray(conditions) && conditions.length ? ( - render('add-button', { - type: 'dropdown-button', - icon: addIcon, - label: addButtonText || '新增', - level: 'info', - size: 'sm', - closeOnClick: true - }, { - buttons: conditions.map(item => ({ - label: item.label, - onClick: (e:any) => { - this.addItemWith(item) - return false; - } - })) - }) - ) : ( - - {addIcon ? () : null} - {addButtonText || '新增'} - - ) : null} -
  • - ) : null} + additionBtns={ + !disabled ? ( +
  • + {store.addable && addable !== false ? ( + Array.isArray(conditions) && conditions.length ? ( + render( + 'add-button', + { + type: 'dropdown-button', + icon: addIcon, + label: addButtonText || '新增', + level: 'info', + size: 'sm', + closeOnClick: true + }, + { + buttons: conditions.map(item => ({ + label: item.label, + onClick: (e: any) => { + this.addItemWith(item); + return false; + } + })) + } + ) + ) : ( + + {addIcon ? : null} + {addButtonText || '新增'} + + ) + ) : null} +
  • + ) : null + } > {value.map((value, index) => { const data = this.formatValue(value, index); - let condition:Condition | null = null; - + let condition: Condition | null = null; + if (Array.isArray(conditions) && conditions.length) { condition = this.pickCondition(data); controls = condition.controls; } - let finnalControls = flat ? [{ - ...controls && controls[0], - name: 'flat' - }] : controls; + let finnalControls = flat + ? [ + { + ...(controls && controls[0]), + name: 'flat' + } + ] + : controls; let toolbar = undefined; if ( - finnalRemovable - && ( // 表达式判断单条是否可删除 - !itemRemovableOn - || evalExpression(itemRemovableOn, value) !== false - ) + finnalRemovable && // 表达式判断单条是否可删除 + (!itemRemovableOn || evalExpression(itemRemovableOn, value) !== false) ) { toolbar = ( { ).map(item => ({label: item.label , value: item.label}))} - value={condition.label} - /> -
    - ) : null} -
    - {render(`multiple/${index}`, { - type: 'form', - controls: finnalControls, - wrapperComponent: 'div', - wrapWithPanel: false, - mode: multiLine ? subFormMode : 'row', - className: cx(`Combo-form`, formClassName) - }, { - index, - disabled, - data, - onChange: this.handleChange.bind(this, index), - onAction: this.handleAction, - ref: (ref:any) => this.formRef(ref, index), - canAccessSuperData - })} -
    - {toolbar.length ? ( -
    {toolbar}
    - ) : null} -
    - ); - }) : null} + let finnalControls = flat + ? [ + { + ...(controls && controls[0]), + name: 'flat' + } + ] + : controls; + + return ( +
    + {condition && typeSwitchable !== false ? ( +
    + + ).map(item => ({label: item.label , value: item.label}))} + options={(conditions as Array).map(item => ({ + label: item.label, + value: item.label + }))} value={condition.label} />
    ) : null}
    - {render('single', { - type: 'form', - controls, - wrapperComponent: 'div', - wrapWithPanel: false, - mode: multiLine ? 'normal' : 'row', - className: cx(`Combo-form`, formClassName) - }, { - disabled: disabled, - data: isObject(value) ? value : this.defaultValue, - onChange: this.handleSingleFormChange, - ref: (ref:any) => this.formRef(ref), - onInit: this.handleSingleFormInit, - canAccessSuperData - })} + {render( + 'single', + { + type: 'form', + controls, + wrapperComponent: 'div', + wrapWithPanel: false, + mode: multiLine ? 'normal' : 'row', + className: cx(`Combo-form`, formClassName) + }, + { + disabled: disabled, + data: isObject(value) ? value : this.defaultValue, + onChange: this.handleSingleFormChange, + ref: (ref: any) => this.formRef(ref), + onInit: this.handleSingleFormInit, + canAccessSuperData + } + )}
    @@ -895,26 +879,17 @@ export default class ComboControl extends React.Component { } render() { - const { - multiple, - className, - classPrefix: ns, - classnames: cx, - } = this.props; + const {multiple, className, classPrefix: ns, classnames: cx} = this.props; return ( -
    - {multiple ? this.renderMultipe() : this.renderSingle()} -
    +
    {multiple ? this.renderMultipe() : this.renderSingle()}
    ); } } - @FormItem({ type: 'combo', storeType: ComboStore.name, extendsData: false }) -export class ComboControlRenderer extends ComboControl {}; - +export class ComboControlRenderer extends ComboControl {} diff --git a/src/renderers/Form/Container.tsx b/src/renderers/Form/Container.tsx index d9e9dc2a4..797edccef 100644 --- a/src/renderers/Form/Container.tsx +++ b/src/renderers/Form/Container.tsx @@ -1,12 +1,10 @@ import React from 'react'; -import { - Renderer -} from '../../factory'; +import {Renderer} from '../../factory'; import cx from 'classnames'; import Container from '../Container'; -import FormItem, { FormControlProps } from './Item'; +import FormItem, {FormControlProps} from './Item'; -export interface ContainerProps extends FormControlProps {}; +export interface ContainerProps extends FormControlProps {} @FormItem({ type: 'container', @@ -14,7 +12,7 @@ export interface ContainerProps extends FormControlProps {}; sizeMutable: false }) export class ContainerControlRenderer extends Container { - renderBody():JSX.Element | null { + renderBody(): JSX.Element | null { const { renderFormItems, body, @@ -32,7 +30,7 @@ export class ContainerControlRenderer extends Container { } = this.props; if (!body && (controls || tabs || fieldSet)) { - let props:any = { + let props: any = { store, data: store.data, render @@ -42,11 +40,15 @@ export class ContainerControlRenderer extends Container { return (
    - {renderFormItems({ - controls, - tabs, - fieldSet - }, ($path as string).replace(/^.*form\//, ''), props)} + {renderFormItems( + { + controls, + tabs, + fieldSet + }, + ($path as string).replace(/^.*form\//, ''), + props + )}
    ); } diff --git a/src/renderers/Form/Control.tsx b/src/renderers/Form/Control.tsx index a480d09e9..0eb5f7baf 100644 --- a/src/renderers/Form/Control.tsx +++ b/src/renderers/Form/Control.tsx @@ -3,26 +3,12 @@ import PropTypes from 'prop-types'; import {IFormStore, IFormItemStore} from '../../store/form'; import debouce = require('lodash/debounce'); -import { - RendererProps, - Renderer -} from '../../factory'; -import { - ComboStore, - IComboStore, - IUniqueGroup -} from '../../store/combo'; -import { - anyChanged, - promisify, - isObject, - getVariable -} from '../../utils/helper'; -import { Schema } from '../../types'; -import { IIRendererStore } from '../../store'; -import { ScopedContext, IScopedContext } from '../../Scoped'; - - +import {RendererProps, Renderer} from '../../factory'; +import {ComboStore, IComboStore, IUniqueGroup} from '../../store/combo'; +import {anyChanged, promisify, isObject, getVariable} from '../../utils/helper'; +import {Schema} from '../../types'; +import {IIRendererStore} from '../../store'; +import {ScopedContext, IScopedContext} from '../../Scoped'; export interface FormControlProps extends RendererProps { control: { @@ -30,8 +16,8 @@ export interface FormControlProps extends RendererProps { name?: string; value?: any; required?: boolean; - validations: string | {[propsName:string]: any}; - validationErrors: {[propsName:string]: any}; + validations: string | {[propsName: string]: any}; + validationErrors: {[propsName: string]: any}; validateOnChange: boolean; multiple?: boolean; delimiter?: string; @@ -40,9 +26,9 @@ export interface FormControlProps extends RendererProps { valueField?: string; labelField?: string; unique?: boolean; - pipeIn?: (value:any, data:any) => any; - pipeOut?: (value:any, originValue:any, data:any) => any; - validate?: (value:any, values:any) => any; + pipeIn?: (value: any, data: any) => any; + pipeOut?: (value: any, originValue: any, data: any) => any; + validate?: (value: any, values: any) => any; } & Schema; formStore: IFormStore; store: IIRendererStore; @@ -51,15 +37,14 @@ export interface FormControlProps extends RendererProps { } export default class FormControl extends React.Component { - public model:IFormItemStore | undefined; - control:any; + public model: IFormItemStore | undefined; + control: any; hook?: () => any; hook2?: () => any; - static defaultProps:Partial = { - }; + static defaultProps: Partial = {}; - lazyValidate:Function; + lazyValidate: Function; componentWillMount() { const { formStore: form, @@ -77,7 +62,7 @@ export default class FormControl extends React.Component valueField, labelField, joinValues, - extractValue, + extractValue } } = this.props; @@ -110,7 +95,7 @@ export default class FormControl extends React.Component valueField, labelField, joinValues, - extractValue, + extractValue }); if (this.model.unique && form.parentStore && form.parentStore.storeType === ComboStore.name) { @@ -123,17 +108,14 @@ export default class FormControl extends React.Component const { store, formStore: form, - control: { - name, - validate, - }, + control: {name, validate}, addHook } = this.props; if (name && form !== store) { const value = getVariable(store.data, name); if (typeof value !== 'undefined' && value !== this.getValue()) { - this.handleChange(value) + this.handleChange(value); } } @@ -142,23 +124,21 @@ export default class FormControl extends React.Component let finalValidate = promisify(validate.bind(formItem)); this.hook2 = function() { formItem.clearError('control:valdiate'); - return finalValidate(form.data, formItem.value) - .then((ret:any) => { - if ((typeof ret === 'string' || Array.isArray(ret)) && ret) { - formItem.addError(ret, 'control:valdiate'); - } - }); - } + return finalValidate(form.data, formItem.value).then((ret: any) => { + if ((typeof ret === 'string' || Array.isArray(ret)) && ret) { + formItem.addError(ret, 'control:valdiate'); + } + }); + }; addHook(this.hook2); } } - componentWillReceiveProps(nextProps:FormControlProps) { + componentWillReceiveProps(nextProps: FormControlProps) { const props = this.props; const form = nextProps.formStore; if (!nextProps.control.name) { - // 把 name 删了, 对 model 做清理 this.model && this.disposeModel(); this.model = undefined; @@ -187,21 +167,25 @@ export default class FormControl extends React.Component } if ( - this.model - && anyChanged([ - 'id', - 'validations', - 'validationErrors', - 'value', - 'required', - 'unique', - 'multiple', - 'delimiter', - 'valueField', - 'labelField', - 'joinValues', - 'extractValue', - ], props.control, nextProps.control) + this.model && + anyChanged( + [ + 'id', + 'validations', + 'validationErrors', + 'value', + 'required', + 'unique', + 'multiple', + 'delimiter', + 'valueField', + 'labelField', + 'joinValues', + 'extractValue' + ], + props.control, + nextProps.control + ) ) { this.model.config({ required: nextProps.control.required, @@ -220,14 +204,12 @@ export default class FormControl extends React.Component } } - componentDidUpdate(prevProps:FormControlProps) { + componentDidUpdate(prevProps: FormControlProps) { const { store, formStore: form, data, - control: { - name - } + control: {name} } = this.props; if (!name) { @@ -235,8 +217,12 @@ export default class FormControl extends React.Component } // form 里面部分塞 service 的用法 - let value:any; - if (form !== store && data !== prevProps.data && (value = getVariable(data as any, name)) !== getVariable(prevProps.data, name)) { + let value: any; + if ( + form !== store && + data !== prevProps.data && + (value = getVariable(data as any, name)) !== getVariable(prevProps.data, name) + ) { this.handleChange(value); } } @@ -248,24 +234,18 @@ export default class FormControl extends React.Component } disposeModel() { - const { - formStore: form - } = this.props; + const {formStore: form} = this.props; if (this.model && this.model.unique && form.parentStore && form.parentStore.storeType === ComboStore.name) { const combo = form.parentStore as IComboStore; combo.unBindUniuqueItem(this.model); } - + this.model && form.unRegistryItem(this.model); } - controlRef(control:any) { - const { - addHook, - removeHook, - formStore: form - } = this.props; + controlRef(control: any) { + const {addHook, removeHook, formStore: form} = this.props; // 因为 control 有可能被 n 层 hoc 包裹。 while (control && control.getWrappedInstance) { @@ -278,13 +258,12 @@ export default class FormControl extends React.Component this.hook = function() { formItem.clearError('component:valdiate'); - return validate(form.data, formItem.value) - .then(ret => { - if ((typeof ret === 'string' || Array.isArray(ret)) && ret) { - formItem.setError(ret, 'component:valdiate'); - } - }); - } + return validate(form.data, formItem.value).then(ret => { + if ((typeof ret === 'string' || Array.isArray(ret)) && ret) { + formItem.setError(ret, 'component:valdiate'); + } + }); + }; addHook(this.hook); } else if (!control && this.hook) { removeHook(this.hook); @@ -295,9 +274,7 @@ export default class FormControl extends React.Component } validate() { - const { - formStore: form, - } = this.props; + const {formStore: form} = this.props; if (this.model) { if (this.model.unique && form.parentStore && form.parentStore.storeType === ComboStore.name) { @@ -306,23 +283,16 @@ export default class FormControl extends React.Component group.items.forEach(item => item.validate()); } else { this.model.validate(this.hook); - form.getItemsByName(this.model.name) - .forEach(item => item !== this.model && item.validate()) + form.getItemsByName(this.model.name).forEach(item => item !== this.model && item.validate()); } } } - handleChange(value:any, submitOnChange:boolean = this.props.control.submitOnChange) { + handleChange(value: any, submitOnChange: boolean = this.props.control.submitOnChange) { const { formStore: form, onChange, - control: { - validateOnChange, - name, - pipeOut, - onChange: onFormItemChange, - type - } + control: {validateOnChange, name, pipeOut, onChange: onFormItemChange, type} } = this.props; // todo 以后想办法不要強耦合类型。 @@ -335,14 +305,14 @@ export default class FormControl extends React.Component if (pipeOut) { value = pipeOut(value, oldValue, form.data); } - + if (oldValue === value) { return; } this.model.changeValue(value); - if (validateOnChange === true || validateOnChange !== false && (form.submited || this.model.validated)) { + if (validateOnChange === true || (validateOnChange !== false && (form.submited || this.model.validated))) { this.lazyValidate(); } else if (validateOnChange === false && !this.model.valid) { this.model.reset(); @@ -352,12 +322,10 @@ export default class FormControl extends React.Component onChange && onChange(value, name, submitOnChange === true); } - handleBlur(e:any) { + handleBlur(e: any) { const { onBlur, - control: { - validateOnBlur - } + control: {validateOnBlur} } = this.props; if (validateOnBlur && this.model) { @@ -367,18 +335,14 @@ export default class FormControl extends React.Component onBlur && onBlur(e); } - handleBulkChange(values:any, submitOnChange:boolean = this.props.control.submitOnChange) { + handleBulkChange(values: any, submitOnChange: boolean = this.props.control.submitOnChange) { const { formStore: form, onChange, - control: { - validateOnChange, - type - }, + control: {validateOnChange, type}, onBulkChange } = this.props; - if (!isObject(values)) { return; } else if (!this.model || ~['service'].indexOf(type)) { @@ -386,7 +350,8 @@ export default class FormControl extends React.Component return; } - let lastKey:string = '', lastValue:any; + let lastKey: string = '', + lastValue: any; Object.keys(values).forEach(key => { const value = values[key]; lastKey = key; @@ -397,7 +362,7 @@ export default class FormControl extends React.Component if (!lastKey) { return; } - + form.setValues(values); if (validateOnChange !== false && (form.submited || this.model.validated)) { @@ -407,7 +372,7 @@ export default class FormControl extends React.Component onChange && onChange(lastValue, lastKey, submitOnChange === true); } - setPrinstineValue(value:any) { + setPrinstineValue(value: any) { if (!this.model) { return; } @@ -416,14 +381,11 @@ export default class FormControl extends React.Component } getValue() { - const { - control, - formStore: form - } = this.props; + const {control, formStore: form} = this.props; const model = this.model; // let value:any = model ? (typeof model.value === 'undefined' ? '' : model.value) : (control.value || ''); - let value:any = model ? model.value : control.value; + let value: any = model ? model.value : control.value; if (control.pipeIn) { value = control.pipeIn(value, form.data); @@ -433,11 +395,9 @@ export default class FormControl extends React.Component } // 兼容老版本用法,新版本直接用 onChange 就可以。 - setValue(value:any, key?:string) { + setValue(value: any, key?: string) { const { - control: { - name - } + control: {name} } = this.props; if (!key || key === name) { @@ -452,11 +412,7 @@ export default class FormControl extends React.Component render() { const { render, - control: { - pipeIn, - pipeOut, - ...control - }, + control: {pipeIn, pipeOut, ...control}, formMode, controlWidth, type, @@ -493,14 +449,14 @@ export default class FormControl extends React.Component } @Renderer({ - test: (path:string) => /(^|\/)form(?:\/.*)?\/control$/i.test(path) && !/\/control\/control$/i.test(path), - name: "control" + test: (path: string) => /(^|\/)form(?:\/.*)?\/control$/i.test(path) && !/\/control\/control$/i.test(path), + name: 'control' }) export class FormControlRenderer extends FormControl { static displayName = 'Control'; static contextType = ScopedContext; - controlRef(ref:any) { + controlRef(ref: any) { const originRef = this.control; super.controlRef(ref); const scoped = this.context as IScopedContext; @@ -516,4 +472,3 @@ export class FormControlRenderer extends FormControl { } } } - diff --git a/src/renderers/Form/Date.tsx b/src/renderers/Form/Date.tsx index e508d34cd..e2f584f4d 100644 --- a/src/renderers/Form/Date.tsx +++ b/src/renderers/Form/Date.tsx @@ -1,12 +1,7 @@ import React from 'react'; -import { - FormItem, - FormControlProps -} from './Item'; +import {FormItem, FormControlProps} from './Item'; import cx from 'classnames'; -import { - filterDate -} from '../../utils/tpl-builtin'; +import {filterDate} from '../../utils/tpl-builtin'; import moment from 'moment'; import 'moment/locale/zh-cn'; import DatePicker from '../../components/DatePicker'; @@ -20,7 +15,7 @@ export interface DateProps extends FormControlProps { closeOnSelect?: boolean; disabled?: boolean; iconClassName?: string; -}; +} interface DateControlState { minDate?: moment.Moment; @@ -42,15 +37,7 @@ export default class DateControl extends React.PureComponent { }; componentWillMount() { - const { - minDate, - maxDate, - value, - defaultValue, - setPrinstineValue, - data, - format - } = this.props; + const {minDate, maxDate, value, defaultValue, setPrinstineValue, data, format} = this.props; if (defaultValue && value === defaultValue) { setPrinstineValue(filterDate(defaultValue, data).format(format)); @@ -69,24 +56,26 @@ export default class DateControl extends React.PureComponent { nextProps.setPrinstineValue(filterDate(nextProps.defaultValue, nextProps.data)); } - if (props.minDate !== nextProps.minDate || props.maxDate !== nextProps.maxDate || props.data !== nextProps.data) { + if ( + props.minDate !== nextProps.minDate || + props.maxDate !== nextProps.maxDate || + props.data !== nextProps.data + ) { this.setState({ - minDate: nextProps.minDate ? filterDate(nextProps.minDate, nextProps.data, this.props.format) : undefined, - maxDate: nextProps.maxDate ? filterDate(nextProps.maxDate, nextProps.data, this.props.format) : undefined + minDate: nextProps.minDate + ? filterDate(nextProps.minDate, nextProps.data, this.props.format) + : undefined, + maxDate: nextProps.maxDate + ? filterDate(nextProps.maxDate, nextProps.data, this.props.format) + : undefined }); } } render() { - const { - className, - classPrefix: ns, - defaultValue, - defaultData, - ...rest - } = this.props; + const {className, classPrefix: ns, defaultValue, defaultData, ...rest} = this.props; - return ( + return (
    @@ -106,7 +95,7 @@ export class DateControlRenderer extends DateControl { timeFormat: '', strictMode: false }; -}; +} @FormItem({ type: 'datetime' @@ -121,7 +110,7 @@ export class DatetimeControlRenderer extends DateControl { closeOnSelect: false, strictMode: false }; -}; +} @FormItem({ type: 'time' @@ -136,4 +125,4 @@ export class TimeControlRenderer extends DateControl { viewMode: 'time', closeOnSelect: false }; -}; \ No newline at end of file +} diff --git a/src/renderers/Form/DateRange.tsx b/src/renderers/Form/DateRange.tsx index d1032b49b..8e8b2c442 100644 --- a/src/renderers/Form/DateRange.tsx +++ b/src/renderers/Form/DateRange.tsx @@ -1,12 +1,7 @@ import React from 'react'; -import { - FormItem, - FormControlProps -} from './Item'; +import {FormItem, FormControlProps} from './Item'; import cx from 'classnames'; -import { - filterDate -} from '../../utils/tpl-builtin'; +import {filterDate} from '../../utils/tpl-builtin'; import moment from 'moment'; import 'moment/locale/zh-cn'; import DateRangePicker from '../../components/DateRangePicker'; @@ -19,7 +14,7 @@ export interface DateRangeProps extends FormControlProps { delimiter: string; minDate?: any; maxDate?: any; -}; +} interface DateControlState { minDate?: moment.Moment; @@ -27,21 +22,16 @@ interface DateControlState { } export default class DateRangeControl extends React.Component { - static defaultProps = { format: 'X', joinValues: true, delimiter: ',' }; - constructor(props:DateRangeProps) { + constructor(props: DateRangeProps) { super(props); - const { - minDate, - maxDate, - data - } = props; + const {minDate, maxDate, data} = props; this.state = { minDate: minDate ? filterDate(minDate, data) : undefined, @@ -50,31 +40,26 @@ export default class DateRangeControl extends React.Component @@ -132,7 +111,7 @@ export class DateRangeControlRenderer extends DateRangeControl { ...DateRangeControl.defaultProps, timeFormat: '' }; -}; +} @FormItem({ type: 'datetime-range', @@ -144,5 +123,4 @@ export class DateTimeRangeControlRenderer extends DateRangeControl { timeFormat: 'HH:mm', inputFormat: 'YYYY-MM-DD HH:mm' }; -}; - +} diff --git a/src/renderers/Form/DiffEditor.tsx b/src/renderers/Form/DiffEditor.tsx index bef559263..beb37ab1a 100644 --- a/src/renderers/Form/DiffEditor.tsx +++ b/src/renderers/Form/DiffEditor.tsx @@ -1,20 +1,15 @@ import React from 'react'; -import { - Renderer -} from '../../factory'; -import { - FormItem, - FormControlProps -} from './Item'; -import { - filter, -} from '../../utils/tpl'; +import {Renderer} from '../../factory'; +import {FormItem, FormControlProps} from './Item'; +import {filter} from '../../utils/tpl'; import cx from 'classnames'; import LazyComponent from '../../components/LazyComponent'; import debouce = require('lodash/debounce'); function loadComponent(): Promise { - return new Promise((resolve) => (require as any)(['../../components/Editor'], (component: any) => resolve(component.default))); + return new Promise(resolve => + (require as any)(['../../components/Editor'], (component: any) => resolve(component.default)) + ); } export interface DiffEditorProps extends FormControlProps { @@ -30,7 +25,7 @@ function normalizeValue(value: any) { return value; } -export class DiffEditor extends React.Component{ +export class DiffEditor extends React.Component { static defaultProps: Partial = { language: 'javascript', theme: 'vs', @@ -44,10 +39,10 @@ export class DiffEditor extends React.Component{ } }, diffValue: '' - } + }; state = { - focused: false, + focused: false }; editor: any; @@ -88,15 +83,16 @@ export class DiffEditor extends React.Component{ } componentDidUpdate(prevProps: any) { - const { - data, - value, - diffValue - } = this.props; + const {data, value, diffValue} = this.props; if (this.originalEditor && diffValue && (diffValue !== prevProps.diffValue || data !== prevProps.data)) { - this.originalEditor.getModel().setValue(/^\$(?:([a-z0-9_.]+)|{.+})$/.test(diffValue as string) - ? filter(normalizeValue(diffValue || ''), data, '| raw') : normalizeValue(diffValue)); + this.originalEditor + .getModel() + .setValue( + /^\$(?:([a-z0-9_.]+)|{.+})$/.test(diffValue as string) + ? filter(normalizeValue(diffValue || ''), data, '| raw') + : normalizeValue(diffValue) + ); } if (this.modifiedEditor && value && value !== prevProps.value && !this.state.focused) { @@ -109,12 +105,7 @@ export class DiffEditor extends React.Component{ } handleEditorMounted(editor: any, monaco: any) { - const { - value, - data, - language, - diffValue - } = this.props; + const {value, data, language, diffValue} = this.props; this.monaco = monaco; this.editor = editor; @@ -126,8 +117,12 @@ export class DiffEditor extends React.Component{ this.toDispose.push(this.modifiedEditor.onDidChangeModelContent(this.handleModifiedEditorChange).dispose); this.editor.setModel({ - original: this.monaco.editor.createModel(/^\$(?:([a-z0-9_.]+)|{.+})$/.test(diffValue as string) - ? filter(normalizeValue(diffValue || ''), data, '| raw') : normalizeValue(diffValue), language), + original: this.monaco.editor.createModel( + /^\$(?:([a-z0-9_.]+)|{.+})$/.test(diffValue as string) + ? filter(normalizeValue(diffValue || ''), data, '| raw') + : normalizeValue(diffValue), + language + ), modified: this.monaco.editor.createModel(normalizeValue(value), language) }); @@ -135,7 +130,7 @@ export class DiffEditor extends React.Component{ } handleModifiedEditorChange() { - const { onChange } = this.props; + const {onChange} = this.props; onChange && onChange(this.modifiedEditor.getModel().getValue()); this.updateContainerSize(); } @@ -153,21 +148,13 @@ export class DiffEditor extends React.Component{ } render() { - const { - className, - value, - onChange, - disabled, - size, - options, - language, - theme, - classnames: cx - } = this.props; + const {className, value, onChange, disabled, size, options, language, theme, classnames: cx} = this.props; return (
    { }) export class DiffEditorControlRenderer extends DiffEditor { static defaultProps = { - ...DiffEditor.defaultProps, + ...DiffEditor.defaultProps }; -}; +} @Renderer({ test: /(^|\/)diff-editor$/, sizeMutable: false, - name: "diff-editor" + name: 'diff-editor' }) export class DiffEditorRenderer extends DiffEditor { static defaultProps = { diff --git a/src/renderers/Form/FieldSet.tsx b/src/renderers/Form/FieldSet.tsx index 9302b26c8..c69f5ee04 100644 --- a/src/renderers/Form/FieldSet.tsx +++ b/src/renderers/Form/FieldSet.tsx @@ -1,8 +1,5 @@ import React from 'react'; -import { - Renderer, - RendererProps -} from '../../factory'; +import {Renderer, RendererProps} from '../../factory'; import Collapse from '../Collapse'; import cx from 'classnames'; @@ -10,19 +7,19 @@ export interface FieldSetProps extends RendererProps { title?: string; collapsed?: boolean; mode?: 'normal' | 'inline' | 'horizontal' | 'row'; - size?: 'xs' | 'sm' | 'md' | 'lg' | 'base', + size?: 'xs' | 'sm' | 'md' | 'lg' | 'base'; collapsable?: boolean; horizontal: { left: string; right: string; offset: string; }; -}; +} export default class FieldSetControl extends React.Component { - constructor(props:FieldSetProps) { + constructor(props: FieldSetProps) { super(props); - this.renderBody = this.renderBody.bind(this); + this.renderBody = this.renderBody.bind(this); } static defaultProps = { @@ -30,7 +27,7 @@ export default class FieldSetControl extends React.Component collapsable: false }; - renderBody():JSX.Element { + renderBody(): JSX.Element { const { renderFormItems, controls, @@ -49,7 +46,7 @@ export default class FieldSetControl extends React.Component return render('body', body) as JSX.Element; } - let props:any = { + let props: any = { store, data: store.data, render @@ -66,15 +63,10 @@ export default class FieldSetControl extends React.Component } render() { - const { - controls, - className, - mode, - ...rest - } = this.props; + const {controls, className, mode, ...rest} = this.props; return ( - @Renderer({ test: /(^|\/)form(?:.+)?\/control\/fieldSet$/i, weight: -100, - name: "fieldset" + name: 'fieldset' }) -export class FieldSetRenderer extends FieldSetControl {}; \ No newline at end of file +export class FieldSetRenderer extends FieldSetControl {} diff --git a/src/renderers/Form/File.tsx b/src/renderers/Form/File.tsx index 52e17a054..58049e1ea 100644 --- a/src/renderers/Form/File.tsx +++ b/src/renderers/Form/File.tsx @@ -1,8 +1,5 @@ import React from 'react'; -import { - FormItem, - FormControlProps -} from './Item'; +import {FormItem, FormControlProps} from './Item'; import cx from 'classnames'; import qs from 'qs'; import find = require('lodash/find'); @@ -10,7 +7,7 @@ import isPlainObject = require('lodash/isPlainObject'); import {mapLimit} from 'async'; import ImageControl from './Image'; import {Payload} from '../../types'; -import { filter } from '../../utils/tpl'; +import {filter} from '../../utils/tpl'; import Alert from '../../components/Alert2'; export interface FileProps extends FormControlProps { @@ -41,12 +38,12 @@ export interface FileProps extends FormControlProps { uploading: string; error: string; uploaded: string; - [propName:string]: string; + [propName: string]: string; }; asBase64?: boolean; asBlob?: boolean; resetValue?: string; -}; +} export interface FileX extends File { state?: 'init' | 'error' | 'pending' | 'uploading' | 'uploaded' | 'invalid' | 'ready'; @@ -58,17 +55,17 @@ export interface FileValue { name?: string; url?: string; state: 'init' | 'error' | 'pending' | 'uploading' | 'uploaded' | 'invalid' | 'ready'; - [propName:string]: any; -}; + [propName: string]: any; +} export interface FileState { uploading: boolean; files: Array; error?: string | null; -}; +} export default class FileControl extends React.Component { - static defaultProps:Partial = { + static defaultProps: Partial = { btnClassName: 'btn-sm btn-info', btnUploadClassName: 'btn-sm btn-success', maxSize: 0, @@ -91,52 +88,69 @@ export default class FileControl extends React.Component { autoUpload: true, hideUploadButton: false, stateTextMap: { - 'init': "", - 'pending': "等待上传", - 'uploading': "上传中", - 'error': "上传出错", - 'uploaded': "已上传", - "ready": "" + init: '', + pending: '等待上传', + uploading: '上传中', + error: '上传出错', + uploaded: '已上传', + ready: '' }, asBase64: false }; state: FileState; current: FileValue | FileX | null; - resolve?: (value?:any) => void; + resolve?: (value?: any) => void; - static valueToFile(value:string | FileValue, props:FileProps, files?: Array):FileValue|undefined { - let file:FileValue | FileX | undefined = files && typeof value === 'string' - ? find(files, item => (item as FileValue).value === value) + static valueToFile( + value: string | FileValue, + props: FileProps, + files?: Array + ): FileValue | undefined { + let file: FileValue | FileX | undefined = + files && typeof value === 'string' ? find(files, item => (item as FileValue).value === value) : undefined; + return value + ? value instanceof File + ? { + state: 'ready', + value: value, + name: value.name, + url: '' + } + : { + ...(typeof value === 'string' + ? { + state: file && file.state ? file.state : 'init', + value, + name: /^data:/.test(value) ? (file && file.name) || 'base64数据' : '', + url: + typeof props.downloadUrl === 'string' && value && !/^data:/.test(value) + ? `${props.downloadUrl}${value}` + : undefined + } + : (value as FileValue)) + } : undefined; - return value ? value instanceof File ? { - state: 'ready', - value: value, - name: value.name, - url: '' - } : { - ...(typeof value === 'string' ? { - state: file && file.state ? file.state : 'init', - value, - name: /^data:/.test(value) ? (file && file.name || 'base64数据') : '', - url: typeof props.downloadUrl === 'string' && value && !/^data:/.test(value) ? `${props.downloadUrl}${value}` : undefined - } : (value as FileValue)) - } : undefined; } - constructor(props:FileProps) { + constructor(props: FileProps) { super(props); - const value:string|Array|FileValue = props.value; + const value: string | Array | FileValue = props.value; const multiple = props.multiple; const joinValues = props.joinValues; const delimiter = props.delimiter as string; - let files:Array = []; + let files: Array = []; if (value) { - files = (Array.isArray(value) ? value : joinValues ? (((value as any).value || value) as string).split(delimiter) : [((value as any).value || value) as string]) - .map(item => FileControl.valueToFile(item, props) as FileValue) - .filter(item => item); + files = (Array.isArray(value) + ? value + : joinValues + ? (((value as any).value || value) as string).split(delimiter) + : [((value as any).value || value) as string] + ) + .map(item => FileControl.valueToFile(item, props) as FileValue) + .filter(item => item); } this.state = { @@ -157,42 +171,49 @@ export default class FileControl extends React.Component { this.uploadBigFile = this.uploadBigFile.bind(this); } - componentWillReceiveProps(nextProps:FileProps) { + componentWillReceiveProps(nextProps: FileProps) { const props = this.props; if (props.value !== nextProps.value) { - const value:string|Array|FileValue = nextProps.value; + const value: string | Array | FileValue = nextProps.value; const multiple = nextProps.multiple; - const joinValues =nextProps.joinValues; + const joinValues = nextProps.joinValues; const delimiter = nextProps.delimiter as string; - let files:Array = []; + let files: Array = []; if (value) { - files = (Array.isArray(value) ? value : joinValues && typeof value === 'string' ? value.split(delimiter) : [value as any]) - .map(item => { - let obj = FileControl.valueToFile(item, nextProps, this.state.files) as FileValue; - let org; + files = (Array.isArray(value) + ? value + : joinValues && typeof value === 'string' + ? value.split(delimiter) + : [value as any] + ) + .map(item => { + let obj = FileControl.valueToFile(item, nextProps, this.state.files) as FileValue; + let org; - if (obj && (org = find(this.state.files, (item:FileValue) => item.value === obj.value)) as FileValue) { - obj = { - ...org, - ...obj - }; - } + if ( + obj && + ((org = find(this.state.files, (item: FileValue) => item.value === obj.value)) as FileValue) + ) { + obj = { + ...org, + ...obj + }; + } - return obj; - }) - .filter(item => item); + return obj; + }) + .filter(item => item); } - this.setState({ - files: files, + files: files }); } } - handleDrop(e:React.ChangeEvent) { + handleDrop(e: React.ChangeEvent) { const files = e.currentTarget.files; if (!files.length) { @@ -200,13 +221,18 @@ export default class FileControl extends React.Component { } const {maxSize, multiple, maxLength} = this.props; - const allowed = (multiple ? maxLength ? maxLength : (files.length + this.state.files.length) : 1) - this.state.files.length; + const allowed = + (multiple ? (maxLength ? maxLength : files.length + this.state.files.length) : 1) - this.state.files.length; - const inputFiles:Array = []; + const inputFiles: Array = []; - [].slice.call(files, 0, allowed).forEach((file:FileX) => { + [].slice.call(files, 0, allowed).forEach((file: FileX) => { if (maxSize && file.size > maxSize) { - alert(`您选择的文件 ${file.name} 大小为 ${ImageControl.formatFileSize(file.size)} 超出了最大为 ${ImageControl.formatFileSize(maxSize)} 的限制,请重新选择`); + alert( + `您选择的文件 ${file.name} 大小为 ${ImageControl.formatFileSize( + file.size + )} 超出了最大为 ${ImageControl.formatFileSize(maxSize)} 的限制,请重新选择` + ); return; } @@ -218,18 +244,19 @@ export default class FileControl extends React.Component { return; } - this.setState({ - error: null, - files: this.state.files.concat(inputFiles) - }, () => { - const { - autoUpload - } = this.props; + this.setState( + { + error: null, + files: this.state.files.concat(inputFiles) + }, + () => { + const {autoUpload} = this.props; - if (autoUpload) { - this.startUpload(); + if (autoUpload) { + this.startUpload(); + } } - }); + ); } startUpload() { @@ -237,19 +264,22 @@ export default class FileControl extends React.Component { return; } - this.setState({ - uploading: true, - files: this.state.files.map(file => { - if (file.state === 'error') { - file.state = 'pending'; - } + this.setState( + { + uploading: true, + files: this.state.files.map(file => { + if (file.state === 'error') { + file.state = 'pending'; + } - return file; - }) - }, this.tick); + return file; + }) + }, + this.tick + ); } - toggleUpload(e:React.MouseEvent) { + toggleUpload(e: React.MouseEvent) { e.preventDefault(); return this.state.uploading ? this.stopUpload() : this.startUpload(); } @@ -265,7 +295,9 @@ export default class FileControl extends React.Component { } tick() { - if (this.current || !this.state.uploading) {return;} + if (this.current || !this.state.uploading) { + return; + } const file = find(this.state.files, item => item.state === 'pending') as FileX; if (file) { @@ -273,47 +305,58 @@ export default class FileControl extends React.Component { file.state = 'uploading'; - this.setState({ - files: this.state.files.concat() - }, () => this.sendFile(file, (error, file, obj) => { - const files = this.state.files.concat(); - const idx = files.indexOf(file as FileX); + this.setState( + { + files: this.state.files.concat() + }, + () => + this.sendFile(file, (error, file, obj) => { + const files = this.state.files.concat(); + const idx = files.indexOf(file as FileX); - if (!~idx) { - return; - } + if (!~idx) { + return; + } - let newFile:FileValue = file as FileValue; + let newFile: FileValue = file as FileValue; - if (error) { - newFile.state = 'error'; - newFile.error = error; - } else { - newFile = obj as FileValue; - } - files.splice(idx, 1, newFile); - this.current = null; - this.setState({ - error: error ? error : null, - files: files - }, this.tick); - })); + if (error) { + newFile.state = 'error'; + newFile.error = error; + } else { + newFile = obj as FileValue; + } + files.splice(idx, 1, newFile); + this.current = null; + this.setState( + { + error: error ? error : null, + files: files + }, + this.tick + ); + }) + ); } else { - this.setState({ - uploading: false - }, () => { - this.onChange(); + this.setState( + { + uploading: false + }, + () => { + this.onChange(); - if (this.resolve) { - this.resolve(this.state.files.some(file => file.state === 'error') ? '文件上传失败请重试' : null); - this.resolve = undefined; + if (this.resolve) { + this.resolve( + this.state.files.some(file => file.state === 'error') ? '文件上传失败请重试' : null + ); + this.resolve = undefined; + } } - }); + ); } } - - sendFile(file:FileX, cb:(error:null|string, file?:FileX, obj?: FileValue) => void) { + sendFile(file: FileX, cb: (error: null | string, file?: FileX, obj?: FileValue) => void) { const { reciever, fileField, @@ -337,55 +380,75 @@ export default class FileControl extends React.Component { url: '', state: 'ready' }); - } - reader.onerror = (error:any) => cb(error.message); + }; + reader.onerror = (error: any) => cb(error.message); return; } else if (asBlob) { - setTimeout(() => cb(null, file, { - name: file.name, - value: file, - url: '', - state: 'ready' - }), 4); + setTimeout( + () => + cb(null, file, { + name: file.name, + value: file, + url: '', + state: 'ready' + }), + 4 + ); return; } - let fn = useChunk === 'auto' && chunkSize && file.size > chunkSize || useChunk === true ? this.uploadBigFile : this.uploadFile; + let fn = + (useChunk === 'auto' && chunkSize && file.size > chunkSize) || useChunk === true + ? this.uploadBigFile + : this.uploadFile; - fn(file, reciever as string, {}, { - fieldName: fileField, - chunkSize, - startChunkApi, - chunkApi, - finishChunkApi - }) - .then(ret => { - if (ret.status || !ret.data) { - throw new Error(ret.msg || '上传失败, 请重试'); + fn( + file, + reciever as string, + {}, + { + fieldName: fileField, + chunkSize, + startChunkApi, + chunkApi, + finishChunkApi } + ) + .then(ret => { + if (ret.status || !ret.data) { + throw new Error(ret.msg || '上传失败, 请重试'); + } - const value = (ret.data as any).value || ret.data; + const value = (ret.data as any).value || ret.data; - cb(null, file, { - ...isPlainObject(ret.data) ? ret.data : null, - value: value, - url: typeof downloadUrl === 'string' && value ? `${downloadUrl}${value}` : ret.data ? (ret.data as any).url : null, - state: 'uploaded' + cb(null, file, { + ...(isPlainObject(ret.data) ? ret.data : null), + value: value, + url: + typeof downloadUrl === 'string' && value + ? `${downloadUrl}${value}` + : ret.data + ? (ret.data as any).url + : null, + state: 'uploaded' + }); + }) + .catch(error => { + cb(error.message || '上传失败, 请重试', file); }); - }) - .catch(error => { - cb(error.message || '上传失败, 请重试', file); - }) } - removeFile(file:FileX | FileValue, index:number) { + removeFile(file: FileX | FileValue, index: number) { const files = this.state.files.concat(); files.splice(index, 1); - this.setState({ - files: files - }, this.onChange); + this.setState( + { + files: files + }, + this.onChange + ); } clearError() { @@ -395,26 +458,21 @@ export default class FileControl extends React.Component { } onChange() { - const { - multiple, - onChange, - joinValues, - extractValue, - valueField, - delimiter, - resetValue, - asBlob - } = this.props; + const {multiple, onChange, joinValues, extractValue, valueField, delimiter, resetValue, asBlob} = this.props; const files = this.state.files.filter(file => ~['uploaded', 'init', 'ready'].indexOf(file.state as string)); - let value:any = multiple ? files : files[0]; + let value: any = multiple ? files : files[0]; if (value) { if (extractValue || asBlob) { - value = Array.isArray(value) ? value.map((item: any) => item[valueField || 'value']) : value[valueField || 'value']; + value = Array.isArray(value) + ? value.map((item: any) => item[valueField || 'value']) + : value[valueField || 'value']; } else if (joinValues) { - value = Array.isArray(value) ? value.map((item: any) => item[valueField || 'value']).join(delimiter || ',') : value[valueField || 'value']; - } + value = Array.isArray(value) + ? value.map((item: any) => item[valueField || 'value']).join(delimiter || ',') + : value[valueField || 'value']; + } } else { value = typeof resetValue === 'undefined' ? '' : resetValue; } @@ -422,7 +480,7 @@ export default class FileControl extends React.Component { onChange(value); } - uploadFile(file:FileX, reciever:string, params:object, config:Partial = {}):Promise { + uploadFile(file: FileX, reciever: string, params: object, config: Partial = {}): Promise { const fd = new FormData(); reciever = filter(reciever, this.props.data); @@ -445,7 +503,7 @@ export default class FileControl extends React.Component { }); } - uploadBigFile(file:FileX, reciever:string, params:object, config:Partial = {}):Promise { + uploadBigFile(file: FileX, reciever: string, params: object, config: Partial = {}): Promise { const chunkSize = config.chunkSize || 5 * 1024 * 1024; const self = this; @@ -454,8 +512,8 @@ export default class FileControl extends React.Component { uploadId: string; loaded: number; total: number; - [propName:string]: any; - }; + [propName: string]: any; + } interface Task { file: File; @@ -463,18 +521,17 @@ export default class FileControl extends React.Component { partSize: number; start: number; stop: number; - [propName:string]: any; - }; + [propName: string]: any; + } return new Promise((resolve, reject) => { - - let state:ObjectState; + let state: ObjectState; self._send(config.startChunkApi as string, {filename: file.name}) - .then(startChunk) - .catch(reject); + .then(startChunk) + .catch(reject); - function startChunk(ret:Payload) { + function startChunk(ret: Payload) { const tasks = getTasks(file); if (!ret.data) { @@ -488,7 +545,7 @@ export default class FileControl extends React.Component { total: tasks.length }; - mapLimit(tasks, 3, uploadPartFile(state, config), function (err, results) { + mapLimit(tasks, 3, uploadPartFile(state, config), function(err, results) { if (err) { reject(err); } else { @@ -497,20 +554,22 @@ export default class FileControl extends React.Component { }); } - function finishChunk(partList:Array|undefined, state:ObjectState) { + function finishChunk(partList: Array | undefined, state: ObjectState) { self._send(config.finishChunkApi as string, { ...params, uploadId: state.uploadId, key: state.key, filename: file.name, partList - }).then(resolve).catch(reject); + }) + .then(resolve) + .catch(reject); } - function uploadPartFile(state:ObjectState, conf:Partial) { + function uploadPartFile(state: ObjectState, conf: Partial) { reciever = conf.chunkApi as string; - return (task:Task, callback:(error:any, value?:any) => void) => { + return (task: Task, callback: (error: any, value?: any) => void) => { const fd = new FormData(); let blob = task.file.slice(task.start, task.stop + 1); @@ -520,26 +579,27 @@ export default class FileControl extends React.Component { fd.append('partSize', task.partSize.toString()); fd.append(config.fieldName || 'file', blob, file.name); - return self._send(reciever, fd, { - withCredentials: true - }) - .then(ret => { - state.loaded++; - callback(null, { - partNumber: task.partNumber, - eTag: (ret.data as any).eTag - }); - }) - .catch(callback); - } + return self + ._send(reciever, fd, { + withCredentials: true + }) + .then(ret => { + state.loaded++; + callback(null, { + partNumber: task.partNumber, + eTag: (ret.data as any).eTag + }); + }) + .catch(callback); + }; } - function getTasks(file:FileX):Array { + function getTasks(file: FileX): Array { let leftSize = file.size; let offset = 0; let partNumber = 1; - let tasks:Array = []; + let tasks: Array = []; while (leftSize > 0) { let partSize = Math.min(leftSize, chunkSize); @@ -558,10 +618,10 @@ export default class FileControl extends React.Component { return tasks; } - }) + }); } - _send(reciever:string, data:any, options?:object):Promise { + _send(reciever: string, data: any, options?: object): Promise { const env = this.props.env; if (!env || !env.fetcher) { @@ -575,9 +635,9 @@ export default class FileControl extends React.Component { }); } - validate():any { + validate(): any { if (this.state.uploading || this.state.files.some(item => item.state === 'pending')) { - return new Promise((resolve) => { + return new Promise(resolve => { this.resolve = resolve; this.startUpload(); }); @@ -602,11 +662,7 @@ export default class FileControl extends React.Component { asBlob, joinValues } = this.props; - let { - files, - uploading, - error - } = this.state; + let {files, uploading, error} = this.state; const hasPending = files.some(file => file.state == 'pending'); @@ -620,47 +676,67 @@ export default class FileControl extends React.Component { {files && files.length ? ( ) : null}
    - {multiple && (!maxLength || files.length < maxLength) || !multiple && !files.length ? ( - - ) : null} + {(multiple && (!maxLength || files.length < maxLength)) || (!multiple && !files.length) ? ( + + ) : null} - {!autoUpload && !hideUploadButton && files.length ? ( - - ) : null} + {!autoUpload && !hideUploadButton && files.length ? ( + + ) : null} - {this.state.uploading ? () : null} + {this.state.uploading ? : null}
    ); } } - @FormItem({ type: 'file', sizeMutable: false }) -export class FileControlRenderer extends FileControl {}; - +export class FileControlRenderer extends FileControl {} diff --git a/src/renderers/Form/Formula.tsx b/src/renderers/Form/Formula.tsx index 939050fbd..aec09491c 100644 --- a/src/renderers/Form/Formula.tsx +++ b/src/renderers/Form/Formula.tsx @@ -1,15 +1,7 @@ import React from 'react'; -import { - FormItem, - FormControlProps -} from './Item'; -import { - evalJS, - filter -} from '../../utils/tpl'; -import { - isObjectShallowModified -} from '../../utils/helper'; +import {FormItem, FormControlProps} from './Item'; +import {evalJS, filter} from '../../utils/tpl'; +import {isObjectShallowModified} from '../../utils/helper'; export interface FormulaProps extends FormControlProps { formula?: string; @@ -19,14 +11,8 @@ export interface FormulaProps extends FormControlProps { } export default class FormulaControl extends React.Component { - componentDidMount() { - const { - formula, - data, - setPrinstineValue, - initSet - } = this.props; + const {formula, data, setPrinstineValue, initSet} = this.props; if (!formula || initSet === false) { return; @@ -37,24 +23,25 @@ export default class FormulaControl extends React.Component { - static propsList: Array = ["columns"]; + static propsList: Array = ['columns']; static defaultProps = {}; - - renderChild(region:string, node:Schema, key: number, length: number) { - const { - render, - renderFormItems, - classnames: cx, - $path, - itemRender, - store - } = this.props; + + renderChild(region: string, node: Schema, key: number, length: number) { + const {render, renderFormItems, classnames: cx, $path, itemRender, store} = this.props; if (node && !node.type && (node.controls || node.tabs || node.feildSet)) { return ( @@ -53,6 +40,6 @@ export class GridRenderer extends Grid { ); } - return itemRender ? itemRender(node, key, length, this.props) : render(region, node.body || node); + return itemRender ? itemRender(node, key, length, this.props) : render(region, node.body || node); } } diff --git a/src/renderers/Form/Group.tsx b/src/renderers/Form/Group.tsx index c0d3c5bb5..08c306c7d 100644 --- a/src/renderers/Form/Group.tsx +++ b/src/renderers/Form/Group.tsx @@ -1,44 +1,42 @@ import React from 'react'; -import { - Renderer, - RendererProps -} from '../../factory'; -import { Schema } from '../../types'; +import {Renderer, RendererProps} from '../../factory'; +import {Schema} from '../../types'; import {isVisible, getWidthRate, makeHorizontalDeeper} from '../../utils/helper'; import cx from 'classnames'; -import { FormItemWrap } from './Item'; +import {FormItemWrap} from './Item'; export interface InputGroupProps extends RendererProps { formMode?: string; controls: Array; gap?: 'xs' | 'sm' | 'normal'; direction: 'horizontal' | 'vertical'; -}; +} @Renderer({ test: /(^|\/)form(?:\/.+)?\/control\/(?:\d+\/)?group$/, sizeMutable: false, - name: "group-control" + name: 'group-control' }) export class ControlGroupRenderer extends React.Component { - constructor(props:InputGroupProps) { - super(props) + constructor(props: InputGroupProps) { + super(props); this.renderInput = this.renderInput.bind(this); } - renderControl(control:any, index:any, otherProps?: any) { - const { - render - } = this.props; + renderControl(control: any, index: any, otherProps?: any) { + const {render} = this.props; if (!control) { return null; } - const subSchema: any = control && (control as Schema).type === 'control' ? control : { - type: 'control', - control - }; + const subSchema: any = + control && (control as Schema).type === 'control' + ? control + : { + type: 'control', + control + }; if (subSchema.control) { let control = subSchema.control as Schema; @@ -52,26 +50,19 @@ export class ControlGroupRenderer extends React.Component { } renderVertical(props = this.props) { - let { - controls, - className, - classnames: cx, - mode, - formMode, - data, - } = props; + let {controls, className, classnames: cx, mode, formMode, data} = props; formMode = mode || formMode; controls = controls.filter(item => isVisible(item, data)); - + return (
    {controls.map((control, index) => { if (!isVisible(control, data)) { return null; } - - const controlMode = control && control.mode || formMode; + + const controlMode = (control && control.mode) || formMode; return this.renderControl(control, index, { key: index, @@ -79,7 +70,7 @@ export class ControlGroupRenderer extends React.Component { }); })}
    - ) + ); } renderHorizontal(props = this.props) { @@ -93,20 +84,26 @@ export class ControlGroupRenderer extends React.Component { formMode, formHorizontal, data, - gap, + gap } = props; formMode = mode || formMode; - + return ( -
    +
    {controls.map((control, index) => { if (!isVisible(control, data)) { return null; } - const controlMode = control && control.mode || formMode; + const controlMode = (control && control.mode) || formMode; - if (controlMode === 'inline' || control && control.type === "formula") { + if (controlMode === 'inline' || (control && control.type === 'formula')) { return this.renderControl(control, index, { formMode: 'inline', key: index, @@ -115,10 +112,18 @@ export class ControlGroupRenderer extends React.Component { } const columnWidth = control.columnRatio || getWidthRate(control && control.columnClassName); - let horizontalDeeper = horizontal || makeHorizontalDeeper(formHorizontal, controls.filter(item => item.mode !== 'inline').length); + let horizontalDeeper = + horizontal || + makeHorizontalDeeper(formHorizontal, controls.filter(item => item.mode !== 'inline').length); return ( -
    +
    {this.renderControl(control, index, { formHorizontal: horizontalDeeper, formMode: controlMode @@ -127,29 +132,19 @@ export class ControlGroupRenderer extends React.Component { ); })}
    - ) + ); } renderInput(props = this.props) { const direction = props.direction; - return direction === "vertical" ? this.renderVertical(props) : this.renderHorizontal(props); + return direction === 'vertical' ? this.renderVertical(props) : this.renderHorizontal(props); } render() { - const { - label, - ...rest - } = this.props; + const {label, ...rest} = this.props; if (label) { - return ( - - ); + return ; } return this.renderInput(); diff --git a/src/renderers/Form/HBox.tsx b/src/renderers/Form/HBox.tsx index 8581bd1a7..f2d4c1f4f 100644 --- a/src/renderers/Form/HBox.tsx +++ b/src/renderers/Form/HBox.tsx @@ -1,20 +1,14 @@ import React from 'react'; -import { - Renderer, - RendererProps -} from '../../factory'; -import { - FormItem, - FormControlProps -} from './Item'; +import {Renderer, RendererProps} from '../../factory'; +import {FormItem, FormControlProps} from './Item'; import HBox from '../HBox'; -import { Schema } from '../../types'; +import {Schema} from '../../types'; import cx from 'classnames'; -import { isVisible } from '../../utils/helper'; +import {isVisible} from '../../utils/helper'; interface HBoxProps extends FormControlProps { size?: string; -}; +} @FormItem({ type: 'hbox', @@ -22,15 +16,11 @@ interface HBoxProps extends FormControlProps { sizeMutable: false }) export class HBoxRenderer extends React.Component { - static propsList: Array = ["columns"]; + static propsList: Array = ['columns']; static defaultProps: Partial = {}; renderColumn(column: any, key: number, length: number) { - const { - itemRender, - data, - classPrefix: ns - } = this.props; + const {itemRender, data, classPrefix: ns} = this.props; if (!isVisible(column, data)) { return null; @@ -53,14 +43,8 @@ export class HBoxRenderer extends React.Component { ); } - renderChild(region:string, node:Schema) { - const { - render, - renderFormItems, - formMode, - store, - $path - } = this.props; + renderChild(region: string, node: Schema) { + const {render, renderFormItems, formMode, store, $path} = this.props; if (node && !node.type && (node.controls || node.tabs || node.feildSet)) { return renderFormItems(node, ($path as string).replace(/^.*form\//, ''), { @@ -80,19 +64,12 @@ export class HBoxRenderer extends React.Component { } render() { - const { - className, - columns, - gap, - classPrefix: ns - } = this.props; + const {className, columns, gap, classPrefix: ns} = this.props; return (
    - {columns.map((column:any, key:number) => - this.renderColumn(column, key, columns.length) - )} + {columns.map((column: any, key: number) => this.renderColumn(column, key, columns.length))}
    ); diff --git a/src/renderers/Form/Hidden.tsx b/src/renderers/Form/Hidden.tsx index c0d79bb22..1b0c2127e 100644 --- a/src/renderers/Form/Hidden.tsx +++ b/src/renderers/Form/Hidden.tsx @@ -1,8 +1,5 @@ import React from 'react'; -import { - FormItem, - FormControlProps -} from './Item'; +import {FormItem, FormControlProps} from './Item'; export default class HiddenControl extends React.Component { render() { @@ -15,4 +12,4 @@ export default class HiddenControl extends React.Component { - input?:HTMLInputElement; + input?: HTMLInputElement; - state:IconPickerState = { + state: IconPickerState = { isOpen: false, inputValue: '', isFocused: false, vendorIndex: 0 }; - static defaultProps:Pick = { + static defaultProps: Pick = { resetValue: '', placeholder: '', noDataTip: '未找到匹配的图标' }; - componentWillReceiveProps(nextProps:IconPickerProps) { + componentWillReceiveProps(nextProps: IconPickerProps) { const props = this.props; if (props.value !== nextProps.value) { @@ -55,19 +52,20 @@ export default class IconPickerControl extends React.PureComponent ( - {label: prefix + icon, value: prefix + icon} - )); + return icons.map((icon: string) => ({label: prefix + icon, value: prefix + icon})); } @autobind @@ -76,9 +74,9 @@ export default class IconPickerControl extends React.PureComponent { - if (trimContents && value && typeof value === "string") { - onChange(value.trim()); + this.setState( + { + isFocused: false + }, + () => { + if (trimContents && value && typeof value === 'string') { + onChange(value.trim()); + } } - }); + ); onBlur && onBlur(e); } @autobind - handleInputChange(evt:React.ChangeEvent) { + handleInputChange(evt: React.ChangeEvent) { let value = evt.currentTarget.value; this.setState({ @@ -140,15 +136,13 @@ export default class IconPickerControl extends React.PureComponent) { + handleKeyDown(evt: React.KeyboardEvent) { const code = keycode(evt.keyCode); if (code !== 'backspace') { return; } - const { - onChange - } = this.props; + const {onChange} = this.props; if (!this.state.inputValue) { onChange(''); @@ -159,7 +153,7 @@ export default class IconPickerControl extends React.PureComponent) { + handleStateChange(changes: StateChangeOptions) { switch (changes.type) { case Downshift.stateChangeTypes.itemMouseEnter: case Downshift.stateChangeTypes.changeInput: @@ -179,7 +173,7 @@ export default class IconPickerControl extends React.PureComponent option['value'])} - >{({ - getInputProps, - getItemProps, - isOpen, - inputValue, - selectedItem - }) => { - let filteredOptions = inputValue && isOpen ? matchSorter(options, inputValue, {keys: ['label', 'value']}) : options; - filteredOptions = filteredOptions.filter((option:any) => !~selectedItem.indexOf(option.value)); + selectedItem={selectedOptions.map((option: Option) => option['value'])} + > + {({getInputProps, getItemProps, isOpen, inputValue, selectedItem}) => { + let filteredOptions = + inputValue && isOpen ? matchSorter(options, inputValue, {keys: ['label', 'value']}) : options; + filteredOptions = filteredOptions.filter((option: any) => !~selectedItem.indexOf(option.value)); - return ( -
    -
    - {placeholder && !selectedOptions.length && !this.state.inputValue ? ( -
    {placeholder}
    - ) : null} + return ( +
    +
    + {placeholder && !selectedOptions.length && !this.state.inputValue ? ( +
    {placeholder}
    + ) : null} - {selectedOptions.map((option:Option, index:number) => inputValue && isOpen ? null : ( -
    - - {option.label} -
    - ))} - - -
    - {isOpen ? ( -
    - {vendors.length > 1 ?
    - {vendors.map((vendor:string, index: number) => ( -
    this.changeVendor(index)} - key={index} - > - {vendor} + {selectedOptions.map((option: Option, index: number) => + inputValue && isOpen ? null : ( +
    + + {option.label}
    - ))} -
    : null} + ) + )} - {filteredOptions.length ?
    1 ? 'IconPickerControl-multiVendor' : 'IconPickerControl-singleVendor')}> - {filteredOptions.map((option:Option, index:number) => ( -
    - -
    - ))} -
    :
    1 ? 'IconPickerControl-multiVendor' : 'IconPickerControl-singleVendor')}>{noDataTip}
    } +
    - ) : null} -
    - ); - }} + {isOpen ? ( +
    + {vendors.length > 1 ? ( +
    + {vendors.map((vendor: string, index: number) => ( +
    this.changeVendor(index)} + key={index} + > + {vendor} +
    + ))} +
    + ) : null} + + {filteredOptions.length ? ( +
    1 + ? 'IconPickerControl-multiVendor' + : 'IconPickerControl-singleVendor' + )} + > + {filteredOptions.map((option: Option, index: number) => ( +
    + +
    + ))} +
    + ) : ( +
    1 + ? 'IconPickerControl-multiVendor' + : 'IconPickerControl-singleVendor' + )} + > + {noDataTip} +
    + )} +
    + ) : null} +
    + ); + }} + ); } - render():JSX.Element { - const { - className, - classPrefix: ns, - inputOnly - } = this.props; + render(): JSX.Element { + const {className, classPrefix: ns, inputOnly} = this.props; let input = this.renderFontIcons(); @@ -305,9 +317,11 @@ export default class IconPickerControl extends React.PureComponent +
    {input}
    ); @@ -317,4 +331,4 @@ export default class IconPickerControl extends React.PureComponent; + files: Array; crop?: object; error?: string; cropFile?: FileValue; submitOnChange?: boolean; -}; +} export interface FileValue { value?: any; - state: 'init' | 'error' | 'pending' | 'uploading' | 'uploaded' | 'invalid', + state: 'init' | 'error' | 'pending' | 'uploading' | 'uploaded' | 'invalid'; url?: string; error?: string; info?: { @@ -66,13 +63,13 @@ export interface FileValue { height: number; len?: number; }; - [propName:string]: any; + [propName: string]: any; } export interface FileX extends File { preview?: string; state?: 'init' | 'error' | 'pending' | 'uploading' | 'uploaded' | 'invalid'; - [propName:string]: any; + [propName: string]: any; } export default class ImageControl extends React.Component { @@ -92,7 +89,7 @@ export default class ImageControl extends React.Component 1024 && units.length > 1) { @@ -103,17 +100,21 @@ export default class ImageControl extends React.Component void; + current: FileValue | FileX | null = null; + resolve?: (value?: any) => void; - constructor(props:ImageProps) { + constructor(props: ImageProps) { super(props); - const value:string|Array|FileValue = props.value; + const value: string | Array | FileValue = props.value; const multiple = props.multiple; const joinValues = props.joinValues; const delimiter = props.delimiter as string; - let files:Array = []; + let files: Array = []; if (value) { // files = (multiple && Array.isArray(value) ? value : joinValues ? (value as string).split(delimiter) : [value]) - files = (Array.isArray(value) ? value : (joinValues && typeof value === 'string' && multiple) ? (value as string).split(delimiter) : [value]) - .map(item => ImageControl.valueToFile(item) as FileValue) - .filter(item => item); + files = (Array.isArray(value) + ? value + : joinValues && typeof value === 'string' && multiple + ? (value as string).split(delimiter) + : [value] + ) + .map(item => ImageControl.valueToFile(item) as FileValue) + .filter(item => item); } this.state = { @@ -176,33 +182,38 @@ export default class ImageControl extends React.Component|FileValue = nextProps.value; + const value: string | Array | FileValue = nextProps.value; const multiple = nextProps.multiple; const joinValues = nextProps.joinValues; const delimiter = nextProps.delimiter as string; - let files:Array = []; + let files: Array = []; if (value) { - files = (Array.isArray(value) ? value : (joinValues && typeof value === 'string') ? (value as string).split(delimiter) : [value]) - .map(item => { - let obj = ImageControl.valueToFile(item, nextProps) as FileValue; - let org; + files = (Array.isArray(value) + ? value + : joinValues && typeof value === 'string' + ? (value as string).split(delimiter) + : [value] + ) + .map(item => { + let obj = ImageControl.valueToFile(item, nextProps) as FileValue; + let org; - if (obj && (org = find(this.state.files, item => (item as FileValue).value === obj.value))) { - obj = { - ...org, - ...obj - }; - } + if (obj && (org = find(this.state.files, item => (item as FileValue).value === obj.value))) { + obj = { + ...org, + ...obj + }; + } - return obj; - }) - .filter(item => item); + return obj; + }) + .filter(item => item); } this.setState({ @@ -217,7 +228,7 @@ export default class ImageControl extends React.Component) { + handleDropRejected(rejectedFiles: any, evt: React.DragEvent) { evt.type === 'change' && alert('您选择的文件类型不符已被过滤!'); } @@ -253,17 +264,20 @@ export default class ImageControl extends React.Component { - if (file.state === 'error') { - file.state = 'pending'; - } + this.setState( + { + uploading: true, + locked: true, + files: this.state.files.map(file => { + if (file.state === 'error') { + file.state = 'pending'; + } - return file; - }) - }, this.tick); + return file; + }) + }, + this.tick + ); } toggleUpload() { @@ -281,78 +295,94 @@ export default class ImageControl extends React.Component item.state === 'pending'); if (file) { this.current = file; file.state = 'uploading'; - this.setState({ - files: this.state.files.concat() - }, () => this.sendFile(file as FileX, (error, file, obj) => { - const files = this.state.files.concat(); - const idx = files.indexOf(file); + this.setState( + { + files: this.state.files.concat() + }, + () => + this.sendFile(file as FileX, (error, file, obj) => { + const files = this.state.files.concat(); + const idx = files.indexOf(file); - if (!~idx) { - return; - } + if (!~idx) { + return; + } - let newFile:FileX | FileValue = file; + let newFile: FileX | FileValue = file; - if (error) { - newFile.state = file.state !== 'uploading' ? file.state : 'error'; - newFile.error = error; + if (error) { + newFile.state = file.state !== 'uploading' ? file.state : 'error'; + newFile.error = error; - if (!this.props.multiple && newFile.state === 'invalid') { - files.splice(idx, 1); + if (!this.props.multiple && newFile.state === 'invalid') { + files.splice(idx, 1); + this.current = null; + + return this.setState( + { + files: files, + error: error + }, + this.tick + ); + } + } else { + newFile = obj as FileValue; + } + files.splice(idx, 1, newFile); this.current = null; - - return this.setState({ - files: files, - error: error - }, this.tick); - } - - } else { - newFile = obj as FileValue; - } - files.splice(idx, 1, newFile); - this.current = null; - this.setState({ - files: files - }, this.tick); - })); + this.setState( + { + files: files + }, + this.tick + ); + }) + ); } else { - this.setState({ - uploading: false, - locked: false - }, () => { - this.onChange(); + this.setState( + { + uploading: false, + locked: false + }, + () => { + this.onChange(); - if (this.resolve) { - this.resolve(this.state.files.some(file => file.state === 'error') ? '文件上传失败请重试' : null); - this.resolve = undefined; + if (this.resolve) { + this.resolve( + this.state.files.some(file => file.state === 'error') ? '文件上传失败请重试' : null + ); + this.resolve = undefined; + } } - }); - + ); } } - removeFile(file:FileValue, index:number) { + removeFile(file: FileValue, index: number) { const files = this.state.files.concat(); files.splice(index, 1); - this.setState({ - files: files - }, this.onChange); + this.setState( + { + files: files + }, + this.onChange + ); } - editImage(index:number) { - const { - multiple - } = this.props; + editImage(index: number) { + const {multiple} = this.props; const files = this.state.files; @@ -362,27 +392,27 @@ export default class ImageControl extends React.Component file.state == 'uploaded' || file.state == 'init'); - let newValue:any = files.length ? joinValues ? files[0].value : files[0] : ''; + let newValue: any = files.length ? (joinValues ? files[0].value : files[0]) : ''; if (multiple) { - newValue = joinValues ? files.map(item => item.value).join(delimiter) : extractValue ? files.map(item => item.value) : files; + newValue = joinValues + ? files.map(item => item.value).join(delimiter) + : extractValue + ? files.map(item => item.value) + : files; } else { - newValue = joinValues ? newValue.value || newValue : extractValue ? newValue[valueField || 'value'] : newValue; + newValue = joinValues + ? newValue.value || newValue + : extractValue + ? newValue[valueField || 'value'] + : newValue; } onChange(newValue); @@ -392,10 +422,10 @@ export default class ImageControl extends React.Component) { + handleDrop(files: Array) { const {multiple, crop} = this.props; - if (crop && !multiple ) { + if (crop && !multiple) { return this.setState({ locked: true, lockedReason: '请选择放弃或者应用', @@ -406,13 +436,13 @@ export default class ImageControl extends React.Component) { + handlePaste(e: React.ClipboardEvent) { const event = e.nativeEvent; - const files:Array = []; + const files: Array = []; const items = event.clipboardData.items; - [].slice.call(items).forEach((item:DataTransferItem) => { - let blob:FileX; + [].slice.call(items).forEach((item: DataTransferItem) => { + let blob: FileX; if (item.kind !== 'file' || !(blob = item.getAsFile() as File) || !/^image/i.test(blob.type)) { return; @@ -426,7 +456,7 @@ export default class ImageControl extends React.Component { + (this.refs.cropper as any).getCroppedCanvas().toBlob((file: File) => { this.addFiles([file]); this.setState({ cropFile: undefined, @@ -437,14 +467,17 @@ export default class ImageControl extends React.Component) { + addFiles(files: Array) { if (!files.length) { return; } @@ -456,12 +489,17 @@ export default class ImageControl extends React.Component = []; + const allowed = + (multiple ? (maxLength ? maxLength : files.length + currentFiles.length) : 1) - currentFiles.length; + const inputFiles: Array = []; [].slice.call(files, 0, allowed).forEach((file: FileX) => { if (maxSize && file.size > maxSize) { - alert(`您选择的文件 ${file.name} 大小为 ${ImageControl.formatFileSize(file.size)} 超出了最大为 ${ImageControl.formatFileSize(maxSize)} 的限制,请重新选择`); + alert( + `您选择的文件 ${file.name} 大小为 ${ImageControl.formatFileSize( + file.size + )} 超出了最大为 ${ImageControl.formatFileSize(maxSize)} 的限制,请重新选择` + ); return; } @@ -476,22 +514,23 @@ export default class ImageControl extends React.Component { - const { - autoUpload - } = this.props; + this.setState( + { + error: undefined, + files: currentFiles.concat(inputFiles), + locked: true + }, + () => { + const {autoUpload} = this.props; - if (autoUpload) { - this.startUpload(); + if (autoUpload) { + this.startUpload(); + } } - }); + ); } - sendFile(file:FileX, cb:(error:null|string, file:FileX, obj?: FileValue) => void) { + sendFile(file: FileX, cb: (error: null | string, file: FileX, obj?: FileValue) => void) { const {limit} = this.props; if (!limit) { @@ -504,14 +543,21 @@ export default class ImageControl extends React.Component width || limit.minHeight && limit.minHeight > height) { - error = `您选择的图片不符合尺寸要求, 请上传不要小于${ImageControl.sizeInfo(limit.minWidth, limit.minHeight)}的图片`; - } else if (limit.aspectRatio && Math.abs((width / height) - limit.aspectRatio) > 0.01) { - error = `您选择的图片不符合尺寸要求, 请上传尺寸比率为 ${limit.aspectRatioLabel || limit.aspectRatio} 的图片` + } else if ((limit.maxWidth && limit.maxWidth < width) || (limit.maxHeight && limit.maxHeight < height)) { + error = `您选择的图片不符合尺寸要求, 请上传不要超过${ImageControl.sizeInfo( + limit.maxWidth, + limit.maxHeight + )}的图片`; + } else if ((limit.minWidth && limit.minWidth > width) || (limit.minHeight && limit.minHeight > height)) { + error = `您选择的图片不符合尺寸要求, 请上传不要小于${ImageControl.sizeInfo( + limit.minWidth, + limit.minHeight + )}的图片`; + } else if (limit.aspectRatio && Math.abs(width / height - limit.aspectRatio) > 0.01) { + error = `您选择的图片不符合尺寸要求, 请上传尺寸比率为 ${limit.aspectRatioLabel || + limit.aspectRatio} 的图片`; } if (error) { @@ -524,7 +570,7 @@ export default class ImageControl extends React.Component void) { + _upload(file: Blob, cb: (error: null | string, file: Blob, obj?: FileValue) => void) { let compressOptions = this.state.compressOptions; if (this.props.showCompressOptions) { @@ -536,29 +582,29 @@ export default class ImageControl extends React.Component { - if (ret.status) { - throw new Error(ret.msg || '上传失败, 请重试'); - } + .then((ret: Payload) => { + if (ret.status) { + throw new Error(ret.msg || '上传失败, 请重试'); + } - const obj:FileValue = { - ...ret.data, - state: 'uploaded' - }; - obj.value = obj.value || obj.url; + const obj: FileValue = { + ...ret.data, + state: 'uploaded' + }; + obj.value = obj.value || obj.url; - cb(null, file, obj); - }) - .catch(error => cb(error.message || '上传失败,请重试', file)) + cb(null, file, obj); + }) + .catch(error => cb(error.message || '上传失败,请重试', file)); } - _send(file:Blob, reciever:string, params:object):Promise { + _send(file: Blob, reciever: string, params: object): Promise { const fd = new FormData(); const data = this.props.data; reciever = filter(reciever, data); const fileField = this.props.fileField || 'file'; fd.append(fileField, file, (file as File).name); - + const idx = reciever.indexOf('?'); if (~idx && params) { @@ -591,7 +637,7 @@ export default class ImageControl extends React.Component) { + handleImageLoaded(index: number, e: React.UIEvent) { const imgDom = e.currentTarget; const img = new Image(); img.onload = () => { @@ -612,18 +658,21 @@ export default class ImageControl extends React.Component file.state === 'pending')); - this.setState({ - files: files - }, !needUploading ? this.onChange : undefined); + this.setState( + { + files: files + }, + !needUploading ? this.onChange : undefined + ); }; img.src = imgDom.src; } - validate():any { + validate(): any { if (this.state.locked && this.state.lockedReason) { return this.state.lockedReason; } else if (this.state.uploading || this.state.files.some(item => item.state === 'pending')) { - return new Promise((resolve) => { + return new Promise(resolve => { this.resolve = resolve; this.startUpload(); }); @@ -643,43 +692,58 @@ export default class ImageControl extends React.Component + this.setState({compress: checked})} + disabled={this.props.disabled} + /> - this.setState({compress: checked})} - disabled={this.props.disabled} - /> + 开启缩放? - 开启缩放? + {this.state.compress && ( +
    + + this.setState({ + compressOptions: { + ...this.state.compressOptions, + maxWidth: parseInt(e.currentTarget.value, 10) || 0 + } + }) + } + disabled={this.props.disabled} + /> - {this.state.compress && ( -
    - this.setState({compressOptions: { - ...this.state.compressOptions, - maxWidth: parseInt(e.currentTarget.value, 10) || 0 - }})} - disabled={this.props.disabled} - /> + X - X - - this.setState({compressOptions: { - ...this.state.compressOptions, - maxHeight: parseInt(e.currentTarget.value, 10) || 0 - }})} - disabled={this.props.disabled} - /> -
    - )} + + this.setState({ + compressOptions: { + ...this.state.compressOptions, + maxHeight: parseInt(e.currentTarget.value, 10) || 0 + } + }) + } + disabled={this.props.disabled} + /> +
    + )}
    ); } @@ -699,41 +763,19 @@ export default class ImageControl extends React.Component file.state == 'pending'); return ( -
    +
    {cropFile ? (
    - - -
    @@ -751,11 +793,13 @@ export default class ImageControl extends React.Component - {files && files.length ? ( -
    + {files && files.length ? ( +
    + })} + > {files.map((file, key) => (
    -
    {file.name}
    - {file.info ? [ -

    {file.info.width} x {file.info.height}

    , - file.info.len ? (

    {ImageControl.formatFileSize(file.info.len)}

    ) : null - ] : (

    ...

    )} +
    + {file.name} +
    + {file.info ? ( + [ +

    + {file.info.width} x {file.info.height} +

    , + file.info.len ? ( +

    {ImageControl.formatFileSize(file.info.len)}

    + ) : null + ] + ) : ( +

    ...

    + )} - {file.error ? (

    {file.error}

    ) : null} + {file.error ?

    {file.error}

    : null}
    - {file.state === 'uploading' ? () : null} - {!disabled && file.state !== 'uploading' ? () : null} - {!!crop && !disabled && file.state !== 'uploading' ? () : null} - {!disabled && file.state !== 'uploading' ? () : null} + {file.state === 'uploading' ? ( + + ) : null} + {!disabled && file.state !== 'uploading' ? ( + + ) : null} + {!!crop && !disabled && file.state !== 'uploading' ? ( + + ) : null} + {!disabled && file.state !== 'uploading' ? ( + + + + ) : null}
    ))} - {multiple && (!maxLength || files.length < maxLength) || !multiple && !files.length ? ( -
    - ) : (
    {error || placeholder} - -
    )} +
    + ) : ( +
    + {error || placeholder} + +
    + )} )} {this.renderCompressOptions()} {!autoUpload && !hideUploadButton && files.length ? ( - ) : null} @@ -805,10 +902,8 @@ export default class ImageControl extends React.Component; - size?: 'xs' | 'sm' | 'normal' -}; + size?: 'xs' | 'sm' | 'normal'; +} interface InputGroupState { isFocused: boolean; -}; +} export class InputGroup extends React.Component { - constructor(props:InputGroupProps) { + constructor(props: InputGroupProps) { super(props); this.handleFocus = this.handleFocus.bind(this); @@ -37,7 +31,7 @@ export class InputGroup extends React.Component = []; + const errors: Array = []; - controls.forEach(({name})=> { + controls.forEach(({name}) => { const formItem = name ? formStore.getItemByName(name) : null; formItem && formItem.errors.length && errors.push(...formItem.errors); }); @@ -88,16 +80,7 @@ export class InputGroup extends React.Component {controls.map((control, index) => { - const isAddOn = ~['icon', 'plain', 'tpl', 'button', 'submit', 'reset'].indexOf(control && control.type); + const isAddOn = ~['icon', 'plain', 'tpl', 'button', 'submit', 'reset'].indexOf( + control && control.type + ); let dom = this.renderControl(control, index, { formHorizontal: horizontalDeeper, @@ -134,17 +119,28 @@ export class InputGroup extends React.Component{dom} - ) : dom; + + {dom} + + ) : ( + dom + ); })}
    - ) + ); } } - @FormItem({ type: 'input-group', strictMode: false }) -export default class InputGroupRenderer extends InputGroup {} \ No newline at end of file +export default class InputGroupRenderer extends InputGroup {} diff --git a/src/renderers/Form/Item.tsx b/src/renderers/Form/Item.tsx index e748c58da..0ca6e0485 100644 --- a/src/renderers/Form/Item.tsx +++ b/src/renderers/Form/Item.tsx @@ -1,21 +1,11 @@ import React from 'react'; import hoistNonReactStatic = require('hoist-non-react-statics'); -import { IFormItemStore } from '../../store/form'; -import { reaction } from 'mobx'; - -import { - RendererProps, - registerRenderer, - TestFunc, - RendererConfig, - HocStoreFactory -} from '../../factory'; -import { - anyChanged, - ucFirst, - getWidthRate} from '../../utils/helper'; -import { observer } from 'mobx-react'; +import {IFormItemStore} from '../../store/form'; +import {reaction} from 'mobx'; +import {RendererProps, registerRenderer, TestFunc, RendererConfig, HocStoreFactory} from '../../factory'; +import {anyChanged, ucFirst, getWidthRate} from '../../utils/helper'; +import {observer} from 'mobx-react'; export interface FormItemBasicConfig extends Partial { type?: string; @@ -33,8 +23,7 @@ export interface FormItemBasicConfig extends Partial { // 兼容老用法,新用法直接在 Component 里面定义 validate 方法即可。 validate?: (values: any, value: any) => string | boolean; -}; - +} export interface FormControlProps extends RendererProps { // error string @@ -43,7 +32,7 @@ export interface FormControlProps extends RendererProps { // error 详情 errors?: { - [propName: string]: string + [propName: string]: string; }; defaultValue: any; @@ -57,18 +46,18 @@ export interface FormControlProps extends RendererProps { formItem?: IFormItemStore; strictMode?: boolean; - renderControl?: (props:RendererProps) => JSX.Element; + renderControl?: (props: RendererProps) => JSX.Element; renderLabel?: boolean; sizeMutable?: boolean; wrap?: boolean; hint?: string; description?: string; descriptionClassName?: string; -}; +} export interface FormControlState { isFocused: boolean; -}; +} export type FormItemComponent = React.ComponentType; export type FormControlComponent = React.ComponentType; @@ -79,8 +68,8 @@ export interface FormItemConfig extends FormItemBasicConfig { export class FormItemWrap extends React.Component { reaction: any; - - constructor(props:FormControlProps) { + + constructor(props: FormControlProps) { super(props); this.state = { @@ -92,9 +81,7 @@ export class FormItemWrap extends React.Component model.errors.join(''), () => this.forceUpdate()); @@ -105,14 +92,14 @@ export class FormItemWrap extends React.Component +
    {label !== false ? ( - ) : null} -
    {this.renderControl()} - {caption ? render('caption', caption, { - className: cx(`Form-caption`, captionClassName) - }) : null} + {caption + ? render('caption', caption, { + className: cx(`Form-caption`, captionClassName) + }) + : null} - {remark ? render('remark', { - type: 'remark', - tooltip: remark, - className: cx(`Form-remark`), - container: env && env.getModalContainer ? env.getModalContainer() : undefined - }) : null} + {remark + ? render('remark', { + type: 'remark', + tooltip: remark, + className: cx(`Form-remark`), + container: env && env.getModalContainer ? env.getModalContainer() : undefined + }) + : null} + + {hint && this.state.isFocused + ? render('hint', hint, { + className: cx(`Form-hint`) + }) + : null} - {hint && this.state.isFocused ? (render('hint', hint, { - className: cx(`Form-hint`) - })) : null} - {model && !model.valid ? (
      - {model.errors.map((msg: string, key: number) => (
    • {msg}
    • ))} + {model.errors.map((msg: string, key: number) => ( +
    • {msg}
    • + ))}
    ) : null} - {description ? render('description', description, { - className: cx(`Form-description`, descriptionClassName) - }) : null} + {description + ? render('description', description, { + className: cx(`Form-description`, descriptionClassName) + }) + : null}
    ); @@ -273,51 +285,65 @@ export class FormItemWrap extends React.Component +
    {label && renderLabel !== false ? ( ) : null} - + {this.renderControl()} - {caption ? render('caption', caption, { - className: cx(`Form-caption`, captionClassName) - }) : null} + {caption + ? render('caption', caption, { + className: cx(`Form-caption`, captionClassName) + }) + : null} - {remark ? render('remark', { - type: 'remark', - className: cx(`Form-remark`), - tooltip: remark, - container: env && env.getModalContainer ? env.getModalContainer() : undefined - }) : null} + {remark + ? render('remark', { + type: 'remark', + className: cx(`Form-remark`), + tooltip: remark, + container: env && env.getModalContainer ? env.getModalContainer() : undefined + }) + : null} - {hint && this.state.isFocused ? (render('hint', hint, { - className: cx(`Form-hint`) - })) : null} + {hint && this.state.isFocused + ? render('hint', hint, { + className: cx(`Form-hint`) + }) + : null} {model && !model.valid ? (
      - {model.errors.map((msg: string, key: number) => (
    • {msg}
    • ))} + {model.errors.map((msg: string, key: number) => ( +
    • {msg}
    • + ))}
    ) : null} - {description ? render('description', description, { - className: cx(`Form-description`, descriptionClassName) - }) : null} + {description + ? render('description', description, { + className: cx(`Form-description`, descriptionClassName) + }) + : null}
    ); } @@ -346,21 +372,25 @@ export class FormItemWrap extends React.Component - {label && renderLabel !== false? ( +
    + {label && renderLabel !== false ? ( ) : null} @@ -368,32 +398,41 @@ export class FormItemWrap extends React.Component {this.renderControl()} - {caption ? render('caption', caption, { - className: cx(`Form-caption`, captionClassName) - }) : null} + {caption + ? render('caption', caption, { + className: cx(`Form-caption`, captionClassName) + }) + : null} - {remark ? render('remark', { - type: 'remark', - className: cx(`Form-remark`), - tooltip: remark, - container: env && env.getModalContainer ? env.getModalContainer() : undefined - }) : null} + {remark + ? render('remark', { + type: 'remark', + className: cx(`Form-remark`), + tooltip: remark, + container: env && env.getModalContainer ? env.getModalContainer() : undefined + }) + : null} - {hint && this.state.isFocused ? (render('hint', hint, { - className: cx(`Form-hint`) - })) : null} + {hint && this.state.isFocused + ? render('hint', hint, { + className: cx(`Form-hint`) + }) + : null} {model && !model.valid ? (
      - {model.errors.map((msg: string, key: number) => (
    • {msg}
    • ))} + {model.errors.map((msg: string, key: number) => ( +
    • {msg}
    • + ))}
    ) : null} - {description ? render('description', description, { - className: cx(`Form-description`, descriptionClassName) - }) : null} + {description + ? render('description', description, { + className: cx(`Form-description`, descriptionClassName) + }) + : null}
    -
    ); } @@ -423,72 +462,85 @@ export class FormItemWrap extends React.Component +
    {label && renderLabel !== false ? ( ) : null} - + {this.renderControl()} - {caption ? render('caption', caption, { - className: cx(`Form-caption`, captionClassName) - }) : null} + {caption + ? render('caption', caption, { + className: cx(`Form-caption`, captionClassName) + }) + : null} - {remark ? render('remark', { - type: 'remark', - className: cx(`Form-remark`), - tooltip: remark, - container: env && env.getModalContainer ? env.getModalContainer() : undefined - }) : null} + {remark + ? render('remark', { + type: 'remark', + className: cx(`Form-remark`), + tooltip: remark, + container: env && env.getModalContainer ? env.getModalContainer() : undefined + }) + : null}
    - {hint && this.state.isFocused ? (render('hint', hint, { - className: cx(`Form-hint`) - })) : null} + {hint && this.state.isFocused + ? render('hint', hint, { + className: cx(`Form-hint`) + }) + : null} {model && !model.valid ? (
      - {model.errors.map((msg: string, key: number) => (
    • {msg}
    • ))} + {model.errors.map((msg: string, key: number) => ( +
    • {msg}
    • + ))}
    ) : null} - {description ? render('description', description, { - className: cx(`Form-description`, descriptionClassName) - }) : null} + {description + ? render('description', description, { + className: cx(`Form-description`, descriptionClassName) + }) + : null}
    ); } render() { - const { - formMode, - inputOnly, - wrap - } = this.props; + const {formMode, inputOnly, wrap} = this.props; if (wrap === false || inputOnly) { return this.renderControl(); } return formMode === 'inline' - ? this.renderInline() : formMode === 'horizontal' - ? this.renderHorizontal() : formMode === 'row' - ? this.renderRow() : this.renderNormal(); + ? this.renderInline() + : formMode === 'horizontal' + ? this.renderHorizontal() + : formMode === 'row' + ? this.renderRow() + : this.renderNormal(); } } @@ -498,7 +550,7 @@ export function registerFormItem(config: FormItemConfig): RendererConfig { // 兼容老的 FormItem 用法。 if (config.validate && !Control.prototype.validate) { const fn = config.validate; - Control.prototype.validate = function () { + Control.prototype.validate = function() { // console.warn('推荐直接在类中定义,而不是 FormItem HOC 的参数中传入。'); const host = { input: this @@ -507,7 +559,9 @@ export function registerFormItem(config: FormItemConfig): RendererConfig { return fn.apply(host, arguments); }; } else if (config.validate) { - console.error('FormItem配置中的 validate 将不起作用,因为类的成员函数中已经定义了 validate 方法,将优先使用类里面的实现。'); + console.error( + 'FormItem配置中的 validate 将不起作用,因为类的成员函数中已经定义了 validate 方法,将优先使用类里面的实现。' + ); } if (config.storeType) { @@ -548,11 +602,8 @@ export function registerFormItem(config: FormItemConfig): RendererConfig { } componentWillMount() { - const { - validations, - formItem: model - } = this.props; - + const {validations, formItem: model} = this.props; + // 组件注册的时候可能默认指定验证器类型 if (model && !validations && config.validations) { model.config({ @@ -567,68 +618,74 @@ export function registerFormItem(config: FormItemConfig): RendererConfig { if (nextProps.strictMode === false) { return true; } - + // 把可能会影响视图的白名单弄出来,减少重新渲染次数。 - if (anyChanged([ - 'formPristine', - 'addable', - 'addButtonClassName', - 'addButtonText', - 'addOn', - 'btnClassName', - 'btnLabel', - 'btnDisabled', - 'className', - 'clearable', - 'columns', - 'columnsCount', - 'controls', - 'desc', - 'description', - 'disabled', - 'draggable', - 'editable', - 'editButtonClassName', - 'formHorizontal', - 'formMode', - 'hideRoot', - 'horizontal', - 'icon', - 'inline', - 'inputClassName', - 'label', - 'labelClassName', - 'labelField', - 'language', - 'level', - 'max', - 'maxRows', - 'min', - 'minRows', - 'multiLine', - 'multiple', - 'option', - 'placeholder', - 'removable', - 'required', - 'remark', - 'hint', - 'rows', - 'searchable', - 'showCompressOptions', - 'size', - 'step', - 'showInput', - 'unit', - 'value', - 'diffValue' - ], this.props, nextProps)) { + if ( + anyChanged( + [ + 'formPristine', + 'addable', + 'addButtonClassName', + 'addButtonText', + 'addOn', + 'btnClassName', + 'btnLabel', + 'btnDisabled', + 'className', + 'clearable', + 'columns', + 'columnsCount', + 'controls', + 'desc', + 'description', + 'disabled', + 'draggable', + 'editable', + 'editButtonClassName', + 'formHorizontal', + 'formMode', + 'hideRoot', + 'horizontal', + 'icon', + 'inline', + 'inputClassName', + 'label', + 'labelClassName', + 'labelField', + 'language', + 'level', + 'max', + 'maxRows', + 'min', + 'minRows', + 'multiLine', + 'multiple', + 'option', + 'placeholder', + 'removable', + 'required', + 'remark', + 'hint', + 'rows', + 'searchable', + 'showCompressOptions', + 'size', + 'step', + 'showInput', + 'unit', + 'value', + 'diffValue' + ], + this.props, + nextProps + ) + ) { return true; } - + return false; } - + getWrappedInstance() { return this.ref; } @@ -650,7 +707,7 @@ export function registerFormItem(config: FormItemConfig): RendererConfig { } = this.props; const controlSize = size || defaultSize; - + return ( ); } @@ -687,14 +749,14 @@ export function registerFormItem(config: FormItemConfig): RendererConfig { } export function FormItem(config: FormItemBasicConfig) { - return function (component: FormControlComponent): any { + return function(component: FormControlComponent): any { const renderer = registerFormItem({ ...config, component }); return renderer.component as any; - } + }; } export default FormItem; diff --git a/src/renderers/Form/List.tsx b/src/renderers/Form/List.tsx index 3b834454d..cc1dcd94d 100644 --- a/src/renderers/Form/List.tsx +++ b/src/renderers/Form/List.tsx @@ -1,49 +1,36 @@ import React from 'react'; -import { - OptionsControl, - OptionsControlProps, - Option -} from './Options'; -import { Schema } from '../../types'; -import { createObject, isEmpty } from '../../utils/helper'; +import {OptionsControl, OptionsControlProps, Option} from './Options'; +import {Schema} from '../../types'; +import {createObject, isEmpty} from '../../utils/helper'; import {dataMapping} from '../../utils/tpl-builtin'; export interface ListProps extends OptionsControlProps { imageClassName: string; submitOnDBClick?: boolean; itemSchema?: Schema; -}; +} export default class ListControl extends React.Component { - static propsList = [ - 'itemSchema', - 'value', - 'renderFormItems' - ]; + static propsList = ['itemSchema', 'value', 'renderFormItems']; static defaultProps = { clearable: false, imageClassName: '', submitOnDBClick: false - } + }; - handleDBClick(option:Option, e:React.MouseEvent) { + handleDBClick(option: Option, e: React.MouseEvent) { this.props.onToggle(option); this.props.onAction(e, { type: 'submit' }); } - handleClick(option:Option, e:React.MouseEvent) { + handleClick(option: Option, e: React.MouseEvent) { if (e.target && (e.target as HTMLElement).closest('a,button')) { return; } - const { - onToggle, - multiple, - autoFill, - onBulkChange - } = this.props; + const {onToggle, multiple, autoFill, onBulkChange} = this.props; const sendTo = !multiple && autoFill && !isEmpty(autoFill) && dataMapping(autoFill, option as Option); sendTo && onBulkChange(sendTo); @@ -72,11 +59,11 @@ export default class ListControl extends React.Component { data } = this.props; - let body:JSX.Element | null = null; + let body: JSX.Element | null = null; if (options && options.length) { body = ( -
    +
    {options.map((option, key) => (
    { onClick={this.handleClick.bind(this, option)} onDoubleClick={submitOnDBClick ? this.handleDBClick.bind(this, option) : undefined} > - {itemSchema ? render(`${key}/body`, itemSchema, { - data: createObject(data, option) - }) : option.body ? render(`${key}/body`, option.body) : [ - option.image ? (
    {option.label}
    ) : null, - option.label ? (
    {option.label}
    ) : null, - // {/* {option.tip ? (
    {option.tip}
    ) : null} */} - ]} + {itemSchema + ? render(`${key}/body`, itemSchema, { + data: createObject(data, option) + }) + : option.body + ? render(`${key}/body`, option.body) + : [ + option.image ? ( +
    + {option.label} +
    + ) : null, + option.label ? ( +
    + {option.label} +
    + ) : null + // {/* {option.tip ? (
    {option.tip}
    ) : null} */} + ]}
    ))}
    @@ -112,5 +111,4 @@ export default class ListControl extends React.Component { type: 'list', sizeMutable: false }) -export class ListControlRenderer extends ListControl {}; - +export class ListControlRenderer extends ListControl {} diff --git a/src/renderers/Form/Matrix.tsx b/src/renderers/Form/Matrix.tsx index d5e83926c..da03d6f04 100644 --- a/src/renderers/Form/Matrix.tsx +++ b/src/renderers/Form/Matrix.tsx @@ -1,22 +1,22 @@ /** -* @file filter -* @author fex -*/ + * @file filter + * @author fex + */ import React from 'react'; import cx from 'classnames'; -import { FormControlProps, FormItem } from './Item'; -import { buildApi, isValidApi, isEffectiveApi } from '../../utils/api'; -import { Checkbox } from '../../components'; +import {FormControlProps, FormItem} from './Item'; +import {buildApi, isValidApi, isEffectiveApi} from '../../utils/api'; +import {Checkbox} from '../../components'; export interface Column { label: string; - [propName:string]: any; + [propName: string]: any; } export interface Row { label: string; - [propName:string]: any; + [propName: string]: any; } export interface ValueItem extends Column, Row { @@ -24,31 +24,30 @@ export interface ValueItem extends Column, Row { } export interface MatrixProps extends FormControlProps { - columns: Array; + columns: Array; rows: Array; multiple: boolean; -}; +} export interface MatrixState { - columns: Array; + columns: Array; rows: Array; loading: boolean; error?: string; singleSelectMode?: 'cell' | 'row' | 'column'; -}; +} export default class MatrixCheckbox extends React.Component { - - static defaultProps:Partial = { + static defaultProps: Partial = { columns: [], rows: [], multiple: true, singleSelectMode: 'column' // multiple 为 false 时有效。 }; - state:MatrixState; - sourceInvalid:boolean = false; - constructor(props:MatrixProps) { + state: MatrixState; + sourceInvalid: boolean = false; + constructor(props: MatrixProps) { super(props); this.state = { @@ -62,15 +61,12 @@ export default class MatrixCheckbox extends React.Component { - env.fetcher(source, data) - .then(ret => { - if (!ret.ok) { - throw new Error(ret.msg || '数据请求错误'); - } - this.setState({ - loading: false, - rows: (ret.data as any).rows || [], - columns: (ret.data as any).columns || [], - }, () => { - let value = (ret.data as any).value; - if (value) { - value = mergeValue(value, this.state.columns, this.state.rows); - onChange(value); + this.setState( + { + loading: true + }, + () => { + env.fetcher(source, data) + .then(ret => { + if (!ret.ok) { + throw new Error(ret.msg || '数据请求错误'); } - }); - }) - .catch(reason => this.setState({ - error: reason, - loading: false - })); - }) + this.setState( + { + loading: false, + rows: (ret.data as any).rows || [], + columns: (ret.data as any).columns || [] + }, + () => { + let value = (ret.data as any).value; + if (value) { + value = mergeValue(value, this.state.columns, this.state.rows); + onChange(value); + } + } + ); + }) + .catch(reason => + this.setState({ + error: reason, + loading: false + }) + ); + } + ); } - toggleItem(checked:boolean, x:number, y:number) { - const { - columns, - rows, - } = this.state; - const { - multiple, - singleSelectMode - } = this.props; + toggleItem(checked: boolean, x: number, y: number) { + const {columns, rows} = this.state; + const {multiple, singleSelectMode} = this.props; const value = this.props.value || buildDefaultValue(columns, rows); - + if (multiple) { value[x][y] = { ...value[x][y], @@ -164,14 +157,15 @@ export default class MatrixCheckbox extends React.Component -
    - +
    +
    +
    {columns.map((column, x) => ( - + ))} - {rows.map((row, y) => ( - - - {columns.map((column, x) => ( - + - ))} - - ))} + {columns.map((column, x) => ( + + ))} + + ))}
    {rowLabel}{column.label} + {column.label} +
    - {row.label}{row.description || row.desc ? ( - {row.description || row.desc} - ) : null} - - this.toggleItem(checked, x, y)} - /> + {rows.map((row, y) => ( +
    + {row.label} + {row.description || row.desc ? ( + + {row.description || row.desc} + + ) : null}
    + this.toggleItem(checked, x, y)} + /> +
    @@ -238,30 +229,25 @@ export default class MatrixCheckbox extends React.Component {error ? ( -
    - {String(error)} -
    - ) : this.renderInput()} +
    {String(error)}
    + ) : ( + this.renderInput() + )} - {loading ? render('loading', { - type: 'spinner', - overlay: true, - size: 'lg', - }):null} + {loading + ? render('loading', { + type: 'spinner', + overlay: true, + size: 'lg' + }) + : null}
    ); } @@ -276,19 +262,23 @@ function buildDefaultValue(columns: Array, rows: Array): Array rows.map(row => ({ - ...row, - ...column, - checked: false - }))); + return columns.map(column => + rows.map(row => ({ + ...row, + ...column, + checked: false + })) + ); } -function mergeValue(value:Array>, columns: Array, rows: Array):Array> { - return value.map((column, x) => column.map((item, y) => ({ - ...columns[x], - ...rows[y], - ...item - }))); +function mergeValue(value: Array>, columns: Array, rows: Array): Array> { + return value.map((column, x) => + column.map((item, y) => ({ + ...columns[x], + ...rows[y], + ...item + })) + ); } @FormItem({ @@ -296,4 +286,4 @@ function mergeValue(value:Array>, columns: Array, rows: strictMode: false, sizeMutable: false }) -export class MatrixRenderer extends MatrixCheckbox {}; +export class MatrixRenderer extends MatrixCheckbox {} diff --git a/src/renderers/Form/NestedSelect.tsx b/src/renderers/Form/NestedSelect.tsx index c62ccf456..73288bbc8 100644 --- a/src/renderers/Form/NestedSelect.tsx +++ b/src/renderers/Form/NestedSelect.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import xorBy = require('lodash/xorBy') -import unionBy = require('lodash/unionBy') +import xorBy = require('lodash/xorBy'); +import unionBy = require('lodash/unionBy'); import Overlay from '../../components/Overlay'; import Checkbox from '../../components/Checkbox'; import PopOver from '../../components/PopOver'; @@ -9,11 +9,7 @@ import {Icon} from '../../components/icons'; import {autobind, flattenTree, isEmpty} from '../../utils/helper'; import {dataMapping} from '../../utils/tpl-builtin'; -import { - OptionsControl, - OptionsControlProps, - Option -} from '../Form/Options' +import {OptionsControl, OptionsControlProps, Option} from '../Form/Options'; export interface NestedSelectProps extends OptionsControlProps { cascade?: boolean; @@ -24,16 +20,16 @@ export interface NestedSelectState { isOpened?: boolean; } -export default class NestedSelectControl extends React.Component{ +export default class NestedSelectControl extends React.Component { static defaultProps: Partial = { cascade: false, withChildren: false - } + }; target: any; alteredOptions: any; state = { isOpened: false - } + }; @autobind domRef(ref: any) { @@ -57,12 +53,7 @@ export default class NestedSelectControl extends React.Component @@ -76,37 +67,24 @@ export default class NestedSelectControl extends React.Component) : null; + return clearable && !disabled && (Array.isArray(value) ? value.length : value) ? ( + + + + ) : null; } @autobind clearValue() { - const { - onChange, - resetValue - } = this.props; + const {onChange, resetValue} = this.props; onChange(typeof resetValue === 'undefined' ? '' : resetValue); } handleOptionClick(option: Option, e: React.MouseEvent) { - const { - multiple, - onChange, - joinValues, - extractValue, - valueField, - autoFill, - onBulkChange - } = this.props; + const {multiple, onChange, joinValues, extractValue, valueField, autoFill, onBulkChange} = this.props; e.stopPropagation(); @@ -188,15 +166,7 @@ export default class NestedSelectControl extends React.Component, isChildren: boolean, uncheckable: boolean): any { - const { - multiple, - selectedOptions, - classnames: cx, - value, - options, - disabled, - cascade - } = this.props; + const {multiple, selectedOptions, classnames: cx, value, options, disabled, cascade} = this.props; if (multiple) { let partialChecked = this.partialChecked(options); @@ -230,10 +200,20 @@ export default class NestedSelectControl extends React.Component {option.label} - {option.children ? (
    ) : null} - {option.children && option.children.length ? this.renderOptions(option.children, true, cascade ? false : uncheckable || multiple && checked) : null} + {option.children ? ( +
    + +
    + ) : null} + {option.children && option.children.length + ? this.renderOptions( + option.children, + true, + cascade ? false : uncheckable || (multiple && checked) + ) + : null}
    - ) + ); })}
    ); @@ -250,28 +230,26 @@ export default class NestedSelectControl extends React.Component {option.label} - {option.children ? (
    ) : null} - {option.children && option.children.length ? this.renderOptions(option.children, true, false) : null} + {option.children ? ( +
    + +
    + ) : null} + {option.children && option.children.length + ? this.renderOptions(option.children, true, false) + : null}
    - ))}
    ); } renderOuter() { - const { - popOverContainer, - options, - classnames: cx - } = this.props; + const {popOverContainer, options, classnames: cx} = this.props; let body = ( - -
    + +
    {this.renderOptions(options, false, false)}
    @@ -285,7 +263,7 @@ export default class NestedSelectControl extends React.Component this.target} show > - + {body} @@ -295,20 +273,19 @@ export default class NestedSelectControl extends React.Component -
    +
    @@ -319,7 +296,7 @@ export default class NestedSelectControl extends React.Component +
    {this.state.isOpened ? this.renderOuter() : null} @@ -331,4 +308,4 @@ export default class NestedSelectControl extends React.Component { static defaultProps: Partial = { @@ -28,13 +25,9 @@ export default class NumberControl extends React.Component { } handleChange(inputValue: any) { - const { - classPrefix: ns, - onChange, - resetValue - } = this.props; + const {classPrefix: ns, onChange, resetValue} = this.props; - onChange(typeof inputValue === 'undefined' ? (resetValue || '') : inputValue); + onChange(typeof inputValue === 'undefined' ? resetValue || '' : inputValue); } filterNum(value: number | string | undefined) { @@ -46,17 +39,7 @@ export default class NumberControl extends React.Component { } render(): JSX.Element { - const { - className, - classPrefix: ns, - value, - step, - precision, - max, - min, - disabled, - placeholder - } = this.props; + const {className, classPrefix: ns, value, step, precision, max, min, disabled, placeholder} = this.props; let precisionProps: any = {}; @@ -88,5 +71,5 @@ export default class NumberControl extends React.Component { export class NumberControlRenderer extends NumberControl { static defaultProps: Partial = { validations: 'isNumeric' - } -}; + }; +} diff --git a/src/renderers/Form/Options.tsx b/src/renderers/Form/Options.tsx index 249f284cc..0af7b917a 100644 --- a/src/renderers/Form/Options.tsx +++ b/src/renderers/Form/Options.tsx @@ -1,44 +1,34 @@ import {Api} from '../../types'; import {buildApi, isEffectiveApi, isValidApi, isApiOutdated} from '../../utils/api'; -import { - anyChanged -} from '../../utils/helper'; +import {anyChanged} from '../../utils/helper'; import {reaction} from 'mobx'; -import { - FormControlProps, - registerFormItem, - FormItemBasicConfig -} from './Item'; -import { - IFormItemStore -} from '../../store/formItem'; +import {FormControlProps, registerFormItem, FormItemBasicConfig} from './Item'; +import {IFormItemStore} from '../../store/formItem'; export type OptionsControlComponent = React.ComponentType; import React from 'react'; -import { resolveVariableAndFilter } from '../../utils/tpl-builtin'; -import { evalExpression } from '../../utils/tpl'; -import { Option, OptionProps, normalizeOptions } from '../../components/Select'; +import {resolveVariableAndFilter} from '../../utils/tpl-builtin'; +import {evalExpression} from '../../utils/tpl'; +import {Option, OptionProps, normalizeOptions} from '../../components/Select'; -export { - Option -}; +export {Option}; export interface OptionsBasicConfig extends FormItemBasicConfig { autoLoadOptionsFromSource?: boolean; } export interface OptionsConfig extends OptionsBasicConfig { - component: React.ComponentType + component: React.ComponentType; } export interface OptionsControlProps extends FormControlProps, OptionProps { source?: Api; name?: string; - onToggle: (option:Option, submitOnChange?: boolean) => void; + onToggle: (option: Option, submitOnChange?: boolean) => void; onToggleAll: () => void; selectedOptions: Array