diff --git a/video-gen-admin/.env b/video-gen-admin/.env index ea3cda13..40b79d76 100644 --- a/video-gen-admin/.env +++ b/video-gen-admin/.env @@ -2,4 +2,4 @@ VITE_API_BASE=http://ceshi.apiforeign.minzhong.cn VITE_USE_MOCK=false # Encryption disabled for dev — enable in production -VITE_ENCRYPTION_KEY= +VITE_ENCRYPTION_KEY= \ No newline at end of file diff --git a/video-gen-admin/.gitignore b/video-gen-admin/.gitignore index 1d620eb5..69abf10e 100644 --- a/video-gen-admin/.gitignore +++ b/video-gen-admin/.gitignore @@ -47,6 +47,7 @@ lerna-debug.log* .env.development.local .env.test.local .env.production.local +.env.production # 如果你有示例环境变量文件,可以提交 !.env.example diff --git a/video-gen-admin/dist/assets/index-ApLUbX7J.js b/video-gen-admin/dist/assets/index-ApLUbX7J.js new file mode 100644 index 00000000..e88814e9 --- /dev/null +++ b/video-gen-admin/dist/assets/index-ApLUbX7J.js @@ -0,0 +1,405 @@ +var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),s=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;li[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},c=(n,r,a)=>(a=n==null?{}:e(i(n)),s(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var l=o((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m)if(n(c)!==null)m=!0,S||(S=!0,O());else{var t=n(l);t!==null&&j(x,t.startTime-e)}}var S=!1,C=-1,w=5,T=-1;function E(){return g?!0:!(e.unstable_now()-Tt&&E());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&j(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?O():S=!1}}}var O;if(typeof y==`function`)O=function(){y(D)};else if(typeof MessageChannel<`u`){var k=new MessageChannel,A=k.port2;k.port1.onmessage=D,O=function(){A.postMessage(null)}}else O=function(){_(D,0)};function j(t,n){C=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(C),C=-1):h=!0,j(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,S||(S=!0,O()))),r},e.unstable_shouldYield=E,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),u=o(((e,t)=>{t.exports=l()})),d=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var S=Array.isArray;function C(){}var w={H:null,A:null,T:null,S:null},T=Object.prototype.hasOwnProperty;function E(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function D(e,t){return E(e.type,t,e.props)}function O(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function k(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var A=/\/+/g;function j(e,t){return typeof e==`object`&&e&&e.key!=null?k(``+e.key):t.toString(36)}function M(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(C,C):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function N(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,N(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+j(e,0):a,S(o)?(i=``,c!=null&&(i=c.replace(A,`$&/`)+`/`),N(o,r,i,``,function(e){return e})):o!=null&&(O(o)&&(o=D(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(A,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(S(e))for(var u=0;u{t.exports=d()})),p=o((e=>{var t=f();function n(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=p()})),h=o((e=>{var t=u(),n=f(),r=m();function i(e){var t=`https://react.dev/errors/`+e;if(1B||(e.current=z[B],z[B]=null,B--)}function U(e,t){B++,z[B]=e.current,e.current=t}var W=V(null),ee=V(null),te=V(null),G=V(null);function ne(e,t){switch(U(te,t),U(ee,e),U(W,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Wd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Wd(t),e=Gd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}H(W),U(W,e)}function K(){H(W),H(ee),H(te)}function re(e){e.memoizedState!==null&&U(G,e);var t=W.current,n=Gd(t,e.type);t!==n&&(U(ee,e),U(W,n))}function ie(e){ee.current===e&&(H(W),H(ee)),G.current===e&&(H(G),tp._currentValue=R)}var ae,q;function oe(e){if(ae===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);ae=t&&t[1]||``,q=-1)`:-1i||c[r]!==l[i]){var u=` +`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{se=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?oe(n):``}function le(e,t){switch(e.tag){case 26:case 27:case 5:return oe(e.type);case 16:return oe(`Lazy`);case 13:return e.child!==t&&t!==null?oe(`Suspense Fallback`):oe(`Suspense`);case 19:return oe(`SuspenseList`);case 0:case 15:return ce(e.type,!1);case 11:return ce(e.type.render,!1);case 1:return ce(e.type,!0);case 31:return oe(`Activity`);default:return``}}function ue(e){try{var t=``,n=null;do t+=le(e,n),n=e,e=e.return;while(e);return t}catch(e){return` +Error generating stack: `+e.message+` +`+e.stack}}var de=Object.prototype.hasOwnProperty,fe=t.unstable_scheduleCallback,pe=t.unstable_cancelCallback,me=t.unstable_shouldYield,he=t.unstable_requestPaint,ge=t.unstable_now,_e=t.unstable_getCurrentPriorityLevel,ve=t.unstable_ImmediatePriority,ye=t.unstable_UserBlockingPriority,be=t.unstable_NormalPriority,xe=t.unstable_LowPriority,Se=t.unstable_IdlePriority,Ce=t.log,we=t.unstable_setDisableYieldValue,Te=null,Ee=null;function De(e){if(typeof Ce==`function`&&we(e),Ee&&typeof Ee.setStrictMode==`function`)try{Ee.setStrictMode(Te,e)}catch{}}var Oe=Math.clz32?Math.clz32:je,ke=Math.log,Ae=Math.LN2;function je(e){return e>>>=0,e===0?32:31-(ke(e)/Ae|0)|0}var Me=256,Ne=262144,Pe=4194304;function Fe(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function Ie(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=Fe(n))):i=Fe(o):i=Fe(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=Fe(n))):i=Fe(o)):i=Fe(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function Le(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function Re(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function ze(){var e=Pe;return Pe<<=1,!(Pe&62914560)&&(Pe=4194304),e}function Be(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function Ve(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function He(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0`u`||window.document===void 0||window.document.createElement===void 0),en=!1;if($t)try{var tn={};Object.defineProperty(tn,`passive`,{get:function(){en=!0}}),window.addEventListener(`test`,tn,tn),window.removeEventListener(`test`,tn,tn)}catch{en=!1}var nn=null,rn=null,an=null;function on(){if(an)return an;var e,t=rn,n=t.length,r,i=`value`in nn?nn.value:nn.textContent,a=i.length;for(e=0;e=Rn),Vn=` `,Hn=!1;function Un(e,t){switch(e){case`keyup`:return In.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function Wn(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var Gn=!1;function Kn(e,t){switch(e){case`compositionend`:return Wn(t);case`keypress`:return t.which===32?(Hn=!0,Vn):null;case`textInput`:return e=t.data,e===Vn&&Hn?null:e;default:return null}}function qn(e,t){if(Gn)return e===`compositionend`||!Ln&&Un(e,t)?(e=on(),an=rn=nn=null,Gn=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=hr(n)}}function _r(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?_r(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function vr(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Dt(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=Dt(e.document)}return t}function yr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var br=$t&&`documentMode`in document&&11>=document.documentMode,xr=null,Sr=null,Cr=null,wr=!1;function Tr(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;wr||xr==null||xr!==Dt(r)||(r=xr,`selectionStart`in r&&yr(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),Cr&&mr(Cr,r)||(Cr=r,r=Od(Sr,`onSelect`),0>=o,i-=o,gi=1<<32-Oe(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),a=o(_,a,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),Ti&&vi(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(a,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(a,h),s=o(y,s,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(a,h),Ti&&vi(a,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(a,v.value,l),v!==null&&(s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return Ti&&vi(a,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,a,g,v.value,l),v!==null&&(e&&v.alternate!==null&&h.delete(v.key===null?g:v.key),s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(a,e)}),Ti&&vi(a,g),u}function b(e,r,o,c){if(typeof o==`object`&&o&&o.type===y&&o.key===null&&(o=o.props.children),typeof o==`object`&&o){switch(o.$$typeof){case _:a:{for(var l=o.key;r!==null;){if(r.key===l){if(l=o.type,l===y){if(r.tag===7){n(e,r.sibling),c=a(r,o.props.children),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===O&&va(l)===r.type){n(e,r.sibling),c=a(r,o.props),Ta(c,o),c.return=e,e=c;break a}n(e,r);break}else t(e,r);r=r.sibling}o.type===y?(c=ri(o.props.children,e.mode,c,o.key),c.return=e,e=c):(c=ni(o.type,o.key,o.props,null,e.mode,c),Ta(c,o),c.return=e,e=c)}return s(e);case v:a:{for(l=o.key;r!==null;){if(r.key===l)if(r.tag===4&&r.stateNode.containerInfo===o.containerInfo&&r.stateNode.implementation===o.implementation){n(e,r.sibling),c=a(r,o.children||[]),c.return=e,e=c;break a}else{n(e,r);break}else t(e,r);r=r.sibling}c=oi(o,e.mode,c),c.return=e,e=c}return s(e);case O:return o=va(o),b(e,r,o,c)}if(F(o))return h(e,r,o,c);if(M(o)){if(l=M(o),typeof l!=`function`)throw Error(i(150));return o=l.call(o),g(e,r,o,c)}if(typeof o.then==`function`)return b(e,r,wa(o),c);if(o.$$typeof===C)return b(e,r,Y(e,o),c);Ea(e,o)}return typeof o==`string`&&o!==``||typeof o==`number`||typeof o==`bigint`?(o=``+o,r!==null&&r.tag===6?(n(e,r.sibling),c=a(r,o),c.return=e,e=c):(n(e,r),c=ii(o,e.mode,c),c.return=e,e=c),s(e)):n(e,r)}return function(e,t,n,r){try{Ca=0;var i=b(e,t,n,r);return Sa=null,i}catch(t){if(t===fa||t===ma)throw t;var a=Qr(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var Oa=Da(!0),ka=Da(!1),Aa=!1;function ja(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Ma(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Na(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Pa(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,Pl&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=Yr(e),Jr(e,null,n),t}return Gr(e,r,t,n),Yr(e)}function Fa(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,We(e,n)}}function Ia(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var La=!1;function Ra(){if(La){var e=ra;if(e!==null)throw e}}function za(e,t,n,r){La=!1;var i=e.updateQueue;Aa=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var f=s.lane&-536870913,p=f!==s.lane;if(p?(Ll&f)===f:(r&f)===f){f!==0&&f===na&&(La=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var m=e,g=s;f=t;var _=n;switch(g.tag){case 1:if(m=g.payload,typeof m==`function`){d=m.call(_,d,f);break a}d=m;break a;case 3:m.flags=m.flags&-65537|128;case 0:if(m=g.payload,f=typeof m==`function`?m.call(_,d,f):m,f==null)break a;d=h({},d,f);break a;case 2:Aa=!0}}f=s.callback,f!==null&&(e.flags|=64,p&&(e.flags|=8192),p=i.callbacks,p===null?i.callbacks=[f]:p.push(f))}else p={lane:f,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=p,c=d):u=u.next=p,o|=f;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;p=s,s=p.next,p.next=null,i.lastBaseUpdate=p,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),Gl|=o,e.lanes=o,e.memoizedState=d}}function Ba(e,t){if(typeof e!=`function`)throw Error(i(191,e));e.call(t)}function Va(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=I.T,s={};I.T=s,Os(e,!1,t,n);try{var c=i(),l=I.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?Ds(e,t,oa(c,r),pu(e)):Ds(e,t,r,pu(e))}catch(n){Ds(e,t,{then:function(){},status:`rejected`,reason:n},pu())}finally{L.p=a,o!==null&&s.types!==null&&(o.types=s.types),I.T=o}}function _s(){}function vs(e,t,n,r){if(e.tag!==5)throw Error(i(476));var a=ys(e).queue;gs(e,a,t,R,n===null?_s:function(){return bs(e),n(r)})}function ys(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:R,baseState:R,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ko,lastRenderedState:R},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ko,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function bs(e){var t=ys(e);t.next===null&&(t=e.alternate.memoizedState),Ds(e,t.next.queue,{},pu())}function xs(){return Ki(tp)}function Ss(){return wo().memoizedState}function Cs(){return wo().memoizedState}function ws(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=pu();e=Na(n);var r=Pa(t,e,n);r!==null&&(hu(r,t,n),Fa(r,t,n)),t={cache:Qi()},e.payload=t;return}t=t.return}}function Ts(e,t,n){var r=pu();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},ks(e)?As(t,n):(n=Kr(e,t,n,r),n!==null&&(hu(n,e,r),js(n,t,r)))}function Es(e,t,n){Ds(e,t,n,pu())}function Ds(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(ks(e))As(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,pr(s,o))return Gr(e,t,i,0),Fl===null&&J(),!1}catch{}if(n=Kr(e,t,i,r),n!==null)return hu(n,e,r),js(n,t,r),!0}return!1}function Os(e,t,n,r){if(r={lane:2,revertLane:fd(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},ks(e)){if(t)throw Error(i(479))}else t=Kr(e,n,r,2),t!==null&&hu(t,e,2)}function ks(e){var t=e.alternate;return e===ro||t!==null&&t===ro}function As(e,t){so=oo=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function js(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,We(e,n)}}var Ms={readContext:Ki,use:Do,useCallback:mo,useContext:mo,useEffect:mo,useImperativeHandle:mo,useLayoutEffect:mo,useInsertionEffect:mo,useMemo:mo,useReducer:mo,useRef:mo,useState:mo,useDebugValue:mo,useDeferredValue:mo,useTransition:mo,useSyncExternalStore:mo,useId:mo,useHostTransitionStatus:mo,useFormState:mo,useActionState:mo,useOptimistic:mo,useMemoCache:mo,useCacheRefresh:mo};Ms.useEffectEvent=mo;var Ns={readContext:Ki,use:Do,useCallback:function(e,t){return Co().memoizedState=[e,t===void 0?null:t],e},useContext:Ki,useEffect:rs,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),ts(4194308,4,ls.bind(null,t,e),n)},useLayoutEffect:function(e,t){return ts(4194308,4,e,t)},useInsertionEffect:function(e,t){ts(4,2,e,t)},useMemo:function(e,t){var n=Co();t=t===void 0?null:t;var r=e();if(co){De(!0);try{e()}finally{De(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=Co();if(n!==void 0){var i=n(t);if(co){De(!0);try{n(t)}finally{De(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=Ts.bind(null,ro,e),[r.memoizedState,e]},useRef:function(e){var t=Co();return e={current:e},t.memoizedState=e},useState:function(e){e=zo(e);var t=e.queue,n=Es.bind(null,ro,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:ds,useDeferredValue:function(e,t){return ms(Co(),e,t)},useTransition:function(){var e=zo(!1);return e=gs.bind(null,ro,e.queue,!0,!1),Co().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=ro,a=Co();if(Ti){if(n===void 0)throw Error(i(407));n=n()}else{if(n=t(),Fl===null)throw Error(i(349));Ll&127||Po(r,t,n)}a.memoizedState=n;var o={value:n,getSnapshot:t};return a.queue=o,rs(Io.bind(null,r,o,e),[e]),r.flags|=2048,$o(9,{destroy:void 0},Fo.bind(null,r,o,n,t),null),n},useId:function(){var e=Co(),t=Fl.identifierPrefix;if(Ti){var n=_i,r=gi;n=(r&~(1<<32-Oe(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=lo++,0<\/script>`,o=o.removeChild(o.firstChild);break;case`select`:o=typeof r.is==`string`?s.createElement(`select`,{is:r.is}):s.createElement(`select`),r.multiple?o.multiple=!0:r.size&&(o.size=r.size);break;default:o=typeof r.is==`string`?s.createElement(a,{is:r.is}):s.createElement(a)}}o[Ze]=t,o[Qe]=r;a:for(s=t.child;s!==null;){if(s.tag===5||s.tag===6)o.appendChild(s.stateNode);else if(s.tag!==4&&s.tag!==27&&s.child!==null){s.child.return=s,s=s.child;continue}if(s===t)break a;for(;s.sibling===null;){if(s.return===null||s.return===t)break a;s=s.return}s.sibling.return=s.return,s=s.sibling}t.stateNode=o;a:switch(Ld(o,a,r),a){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&Dc(t)}}return Mc(t),Oc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&Dc(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(i(166));if(e=te.current,Mi(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,a=Ci,a!==null)switch(a.tag){case 27:case 5:r=a.memoizedProps}e[Ze]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||Pd(e.nodeValue,n)),e||ki(t,!0)}else e=Ud(e).createTextNode(r),e[Ze]=t,t.stateNode=e}return Mc(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=Mi(t),n!==null){if(e===null){if(!r)throw Error(i(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(i(557));e[Ze]=t}else Ni(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;Mc(t),e=!1}else n=Pi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?($a(t),t):($a(t),null);if(t.flags&128)throw Error(i(558))}return Mc(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(a=Mi(t),r!==null&&r.dehydrated!==null){if(e===null){if(!a)throw Error(i(318));if(a=t.memoizedState,a=a===null?null:a.dehydrated,!a)throw Error(i(317));a[Ze]=t}else Ni(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;Mc(t),a=!1}else a=Pi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=a),a=!0;if(!a)return t.flags&256?($a(t),t):($a(t),null)}return $a(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,a=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(a=r.alternate.memoizedState.cachePool.pool),o=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(o=r.memoizedState.cachePool.pool),o!==a&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),Ac(t,t.updateQueue),Mc(t),null);case 4:return K(),e===null&&wd(t.stateNode.containerInfo),Mc(t),null;case 10:return Bi(t.type),Mc(t),null;case 19:if(H(eo),r=t.memoizedState,r===null)return Mc(t),null;if(a=(t.flags&128)!=0,o=r.rendering,o===null)if(a)jc(r,!1);else{if(Wl!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(o=to(e),o!==null){for(t.flags|=128,jc(r,!1),e=o.updateQueue,t.updateQueue=e,Ac(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)ti(n,e),n=n.sibling;return U(eo,eo.current&1|2),Ti&&vi(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&ge()>tu&&(t.flags|=128,a=!0,jc(r,!1),t.lanes=4194304)}else{if(!a)if(e=to(o),e!==null){if(t.flags|=128,a=!0,e=e.updateQueue,t.updateQueue=e,Ac(t,e),jc(r,!0),r.tail===null&&r.tailMode===`hidden`&&!o.alternate&&!Ti)return Mc(t),null}else 2*ge()-r.renderingStartTime>tu&&n!==536870912&&(t.flags|=128,a=!0,jc(r,!1),t.lanes=4194304);r.isBackwards?(o.sibling=t.child,t.child=o):(e=r.last,e===null?t.child=o:e.sibling=o,r.last=o)}return r.tail===null?(Mc(t),null):(e=r.tail,r.rendering=e,r.tail=e.sibling,r.renderingStartTime=ge(),e.sibling=null,n=eo.current,U(eo,a?n&1|2:n&1),Ti&&vi(t,r.treeForkCount),e);case 22:case 23:return $a(t),Ka(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(Mc(t),t.subtreeFlags&6&&(t.flags|=8192)):Mc(t),n=t.updateQueue,n!==null&&Ac(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&H(ca),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),Bi(Zi),Mc(t),null;case 25:return null;case 30:return null}throw Error(i(156,t.tag))}function Pc(e,t){switch(xi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Bi(Zi),K(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return ie(t),null;case 31:if(t.memoizedState!==null){if($a(t),t.alternate===null)throw Error(i(340));Ni()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if($a(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(i(340));Ni()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return H(eo),null;case 4:return K(),null;case 10:return Bi(t.type),null;case 22:case 23:return $a(t),Ka(),e!==null&&H(ca),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return Bi(Zi),null;case 25:return null;default:return null}}function Fc(e,t){switch(xi(t),t.tag){case 3:Bi(Zi),K();break;case 26:case 27:case 5:ie(t);break;case 4:K();break;case 31:t.memoizedState!==null&&$a(t);break;case 13:$a(t);break;case 19:H(eo);break;case 10:Bi(t.type);break;case 22:case 23:$a(t),Ka(),e!==null&&H(ca);break;case 24:Bi(Zi)}}function Ic(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){Gu(t,t.return,e)}}function Lc(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){Gu(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){Gu(t,t.return,e)}}function Rc(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{Va(t,n)}catch(t){Gu(e,e.return,t)}}}function zc(e,t,n){n.props=Bs(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){Gu(e,t,n)}}function Bc(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){Gu(e,t,n)}}function Vc(e,t){var n=e.ref,r=e.refCleanup;if(n!==null)if(typeof r==`function`)try{r()}catch(n){Gu(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){Gu(e,t,n)}else n.current=null}function Hc(e){var t=e.type,n=e.memoizedProps,r=e.stateNode;try{a:switch(t){case`button`:case`input`:case`select`:case`textarea`:n.autoFocus&&r.focus();break a;case`img`:n.src?r.src=n.src:n.srcSet&&(r.srcset=n.srcSet)}}catch(t){Gu(e,e.return,t)}}function Uc(e,t,n){try{var r=e.stateNode;Rd(r,e.type,n,t),r[Qe]=t}catch(t){Gu(e,e.return,t)}}function Wc(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&ef(e.type)||e.tag===4}function Gc(e){a:for(;;){for(;e.sibling===null;){if(e.return===null||Wc(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&ef(e.type)||e.flags&2||e.child===null||e.tag===4)continue a;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Kc(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?(n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n).insertBefore(e,t):(t=n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n,t.appendChild(e),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=Wt));else if(r!==4&&(r===27&&ef(e.type)&&(n=e.stateNode,t=null),e=e.child,e!==null))for(Kc(e,t,n),e=e.sibling;e!==null;)Kc(e,t,n),e=e.sibling}function qc(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(r===27&&ef(e.type)&&(n=e.stateNode),e=e.child,e!==null))for(qc(e,t,n),e=e.sibling;e!==null;)qc(e,t,n),e=e.sibling}function Jc(e){var t=e.stateNode,n=e.memoizedProps;try{for(var r=e.type,i=t.attributes;i.length;)t.removeAttributeNode(i[0]);Ld(t,r,n),t[Ze]=e,t[Qe]=n}catch(t){Gu(e,e.return,t)}}var Yc=!1,Xc=!1,Zc=!1,Qc=typeof WeakSet==`function`?WeakSet:Set,$c=null;function el(e,t){if(e=e.containerInfo,Vd=up,e=vr(e),yr(e)){if(`selectionStart`in e)var n={start:e.selectionStart,end:e.selectionEnd};else a:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var a=r.anchorOffset,o=r.focusNode;r=r.focusOffset;try{n.nodeType,o.nodeType}catch{n=null;break a}var s=0,c=-1,l=-1,u=0,d=0,f=e,p=null;b:for(;;){for(var m;f!==n||a!==0&&f.nodeType!==3||(c=s+a),f!==o||r!==0&&f.nodeType!==3||(l=s+r),f.nodeType===3&&(s+=f.nodeValue.length),(m=f.firstChild)!==null;)p=f,f=m;for(;;){if(f===e)break b;if(p===n&&++u===a&&(c=s),p===o&&++d===r&&(l=s),(m=f.nextSibling)!==null)break;f=p,p=f.parentNode}f=m}n=c===-1||l===-1?null:{start:c,end:l}}else n=null}n||={start:0,end:0}}else n=null;for(Hd={focusedElem:e,selectionRange:n},up=!1,$c=t;$c!==null;)if(t=$c,e=t.child,t.subtreeFlags&1028&&e!==null)e.return=t,$c=e;else for(;$c!==null;){switch(t=$c,o=t.alternate,e=t.flags,t.tag){case 0:if(e&4&&(e=t.updateQueue,e=e===null?null:e.events,e!==null))for(n=0;n title`))),Ld(o,r,n),o[Ze]=e,ut(o),r=o;break a;case`link`:var s=Wf(`link`,`href`,a).get(r+(n.href||``));if(s){for(var c=0;cg&&(o=g,g=h,h=o);var _=gr(s,h),v=gr(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,I.T=null,n=lu,lu=null;var o=au,s=su;if(iu=0,ou=au=null,su=0,Pl&6)throw Error(i(331));var c=Pl;if(Pl|=4,kl(o.current),Sl(o,o.current,s,n),Pl=c,ad(0,!1),Ee&&typeof Ee.onPostCommitFiberRoot==`function`)try{Ee.onPostCommitFiberRoot(Te,o)}catch{}return!0}finally{L.p=a,I.T=r,Vu(e,t)}}function Wu(e,t,n){t=ci(n,t),t=Ks(e.stateNode,t,2),e=Pa(e,t,2),e!==null&&(Ve(e,2),id(e))}function Gu(e,t,n){if(e.tag===3)Wu(e,e,n);else for(;t!==null;){if(t.tag===3){Wu(t,e,n);break}else if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(ru===null||!ru.has(r))){e=ci(n,e),n=qs(2),r=Pa(t,n,2),r!==null&&(Js(n,r,t,e),Ve(r,2),id(r));break}}t=t.return}}function Ku(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new Nl;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(Hl=!0,i.add(n),e=qu.bind(null,e,t,n),t.then(e,e))}function qu(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,Fl===e&&(Ll&n)===n&&(Wl===4||Wl===3&&(Ll&62914560)===Ll&&300>ge()-$l?!(Pl&2)&&Su(e,0):ql|=n,Yl===Ll&&(Yl=0)),id(e)}function Ju(e,t){t===0&&(t=ze()),e=qr(e,t),e!==null&&(Ve(e,t),id(e))}function Yu(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),Ju(e,n)}function Xu(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,a=e.memoizedState;a!==null&&(n=a.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(i(314))}r!==null&&r.delete(t),Ju(e,n)}function Zu(e,t){return fe(e,t)}var Qu=null,$u=null,ed=!1,td=!1,nd=!1,rd=0;function id(e){e!==$u&&e.next===null&&($u===null?Qu=$u=e:$u=$u.next=e),td=!0,ed||(ed=!0,dd())}function ad(e,t){if(!nd&&td){nd=!0;do for(var n=!1,r=Qu;r!==null;){if(!t)if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-Oe(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,ud(r,a))}else a=Ll,a=Ie(r,r===Fl?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||Le(r,a)||(n=!0,ud(r,a));r=r.next}while(n);nd=!1}}function od(){sd()}function sd(){td=ed=!1;var e=0;rd!==0&&Jd()&&(e=rd);for(var t=ge(),n=null,r=Qu;r!==null;){var i=r.next,a=cd(r,t);a===0?(r.next=null,n===null?Qu=i:n.next=i,i===null&&($u=n)):(n=r,(e!==0||a&3)&&(td=!0)),r=i}iu!==0&&iu!==5||ad(e,!1),rd!==0&&(rd=0)}function cd(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&zd(d)&&(c=c.responseEnd,o+=u*(c`u`?null:document;function wf(e,t,n){var r=Cf;if(r&&typeof t==`string`&&t){var i=kt(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),vf.has(i)||(vf.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),Ld(t,`link`,e),ut(t),r.head.appendChild(t)))}}function Tf(e){bf.D(e),wf(`dns-prefetch`,e,null)}function Ef(e,t){bf.C(e,t),wf(`preconnect`,e,t)}function Df(e,t,n){bf.L(e,t,n);var r=Cf;if(r&&e&&t){var i=`link[rel="preload"][as="`+kt(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+kt(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+kt(n.imageSizes)+`"]`)):i+=`[href="`+kt(e)+`"]`;var a=i;switch(t){case`style`:a=Nf(e);break;case`script`:a=Lf(e)}_f.has(a)||(e=h({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),_f.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(Pf(a))||t===`script`&&r.querySelector(Rf(a))||(t=r.createElement(`link`),Ld(t,`link`,e),ut(t),r.head.appendChild(t)))}}function Of(e,t){bf.m(e,t);var n=Cf;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+kt(r)+`"][href="`+kt(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Lf(e)}if(!_f.has(a)&&(e=h({rel:`modulepreload`,href:e},t),_f.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(Rf(a)))return}r=n.createElement(`link`),Ld(r,`link`,e),ut(r),n.head.appendChild(r)}}}function kf(e,t,n){bf.S(e,t,n);var r=Cf;if(r&&e){var i=lt(r).hoistableStyles,a=Nf(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(Pf(a)))s.loading=5;else{e=h({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=_f.get(a))&&Vf(e,n);var c=o=r.createElement(`link`);ut(c),Ld(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,Bf(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function Af(e,t){bf.X(e,t);var n=Cf;if(n&&e){var r=lt(n).hoistableScripts,i=Lf(e),a=r.get(i);a||(a=n.querySelector(Rf(i)),a||(e=h({src:e,async:!0},t),(t=_f.get(i))&&Hf(e,t),a=n.createElement(`script`),ut(a),Ld(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function jf(e,t){bf.M(e,t);var n=Cf;if(n&&e){var r=lt(n).hoistableScripts,i=Lf(e),a=r.get(i);a||(a=n.querySelector(Rf(i)),a||(e=h({src:e,async:!0,type:`module`},t),(t=_f.get(i))&&Hf(e,t),a=n.createElement(`script`),ut(a),Ld(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Mf(e,t,n,r){var a=(a=te.current)?yf(a):null;if(!a)throw Error(i(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(t=Nf(n.href),n=lt(a).hoistableStyles,r=n.get(t),r||(r={type:`style`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=Nf(n.href);var o=lt(a).hoistableStyles,s=o.get(e);if(s||(a=a.ownerDocument||a,s={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},o.set(e,s),(o=a.querySelector(Pf(e)))&&!o._p&&(s.instance=o,s.state.loading=5),_f.has(e)||(n={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},_f.set(e,n),o||If(a,e,n,s.state))),t&&r===null)throw Error(i(528,``));return s}if(t&&r!==null)throw Error(i(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(t=Lf(n),n=lt(a).hoistableScripts,r=n.get(t),r||(r={type:`script`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(i(444,e))}}function Nf(e){return`href="`+kt(e)+`"`}function Pf(e){return`link[rel="stylesheet"][`+e+`]`}function Ff(e){return h({},e,{"data-precedence":e.precedence,precedence:null})}function If(e,t,n,r){e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)?r.loading=1:(t=e.createElement(`link`),r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2}),Ld(t,`link`,n),ut(t),e.head.appendChild(t))}function Lf(e){return`[src="`+kt(e)+`"]`}function Rf(e){return`script[async]`+e}function zf(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+kt(n.href)+`"]`);if(r)return t.instance=r,ut(r),r;var a=h({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),ut(r),Ld(r,`style`,a),Bf(r,n.precedence,e),t.instance=r;case`stylesheet`:a=Nf(n.href);var o=e.querySelector(Pf(a));if(o)return t.state.loading|=4,t.instance=o,ut(o),o;r=Ff(n),(a=_f.get(a))&&Vf(r,a),o=(e.ownerDocument||e).createElement(`link`),ut(o);var s=o;return s._p=new Promise(function(e,t){s.onload=e,s.onerror=t}),Ld(o,`link`,r),t.state.loading|=4,Bf(o,n.precedence,e),t.instance=o;case`script`:return o=Lf(n.src),(a=e.querySelector(Rf(o)))?(t.instance=a,ut(a),a):(r=n,(a=_f.get(o))&&(r=h({},n),Hf(r,a)),e=e.ownerDocument||e,a=e.createElement(`script`),ut(a),Ld(a,`link`,r),e.head.appendChild(a),t.instance=a);case`void`:return null;default:throw Error(i(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,Bf(r,n.precedence,e));return t.instance}function Bf(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function Kf(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function qf(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Jf(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=Nf(r.href),a=t.querySelector(Pf(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=Zf.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,ut(a);return}a=t.ownerDocument||t,r=Ff(r),(i=_f.get(i))&&Vf(r,i),a=a.createElement(`link`),ut(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),Ld(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=Zf.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var Yf=0;function Xf(e,t){return e.stylesheets&&e.count===0&&$f(e,e.stylesheets),0Yf?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function Zf(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)$f(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Qf=null;function $f(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Qf=new Map,t.forEach(ep,e),Qf=null,Zf.call(e))}function ep(e,t){if(!(t.state.loading&4)){var n=Qf.get(e);if(n)var r=n.get(null);else{n=new Map,Qf.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=h()}))(),_=`modulepreload`,v=function(e){return`/`+e},y={},b=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}r=o(t.map(t=>{if(t=v(t,n),t in y)return;y[t]=!0;let r=t.endsWith(`.css`),i=r?`[rel="stylesheet"]`:``;if(n)for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}else if(document.querySelector(`link[href="${t}"]${i}`))return;let o=document.createElement(`link`);if(o.rel=r?`stylesheet`:_,r||(o.as=`script`),o.crossOrigin=``,o.href=t,a&&o.setAttribute(`nonce`,a),document.head.appendChild(o),r)return new Promise((e,n)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},x=c(f(),1),S=`popstate`;function C(e){return typeof e==`object`&&!!e&&`pathname`in e&&`search`in e&&`hash`in e&&`state`in e&&`key`in e}function w(e={}){function t(e,t){let n=t.state?.masked,{pathname:r,search:i,hash:a}=n||e.location;return k(``,{pathname:r,search:i,hash:a},t.state&&t.state.usr||null,t.state&&t.state.key||`default`,n?{pathname:e.location.pathname,search:e.location.search,hash:e.location.hash}:void 0)}function n(e,t){return typeof t==`string`?t:A(t)}return M(t,n,null,e)}function T(e,t){if(e===!1||e==null)throw Error(t)}function E(e,t){if(!e){typeof console<`u`&&console.warn(t);try{throw Error(t)}catch{}}}function D(){return Math.random().toString(36).substring(2,10)}function O(e,t){return{usr:e.state,key:e.key,idx:t,masked:e.mask?{pathname:e.pathname,search:e.search,hash:e.hash}:void 0}}function k(e,t,n=null,r,i){return{pathname:typeof e==`string`?e:e.pathname,search:``,hash:``,...typeof t==`string`?j(t):t,state:n,key:t&&t.key||r||D(),mask:i}}function A({pathname:e=`/`,search:t=``,hash:n=``}){return t&&t!==`?`&&(e+=t.charAt(0)===`?`?t:`?`+t),n&&n!==`#`&&(e+=n.charAt(0)===`#`?n:`#`+n),e}function j(e){let t={};if(e){let n=e.indexOf(`#`);n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf(`?`);r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function M(e,t,n,r={}){let{window:i=document.defaultView,v5Compat:a=!1}=r,o=i.history,s=`POP`,c=null,l=u();l??(l=0,o.replaceState({...o.state,idx:l},``));function u(){return(o.state||{idx:null}).idx}function d(){s=`POP`;let e=u(),t=e==null?null:e-l;l=e,c&&c({action:s,location:h.location,delta:t})}function f(e,t){s=`PUSH`;let r=C(e)?e:k(h.location,e,t);n&&n(r,e),l=u()+1;let d=O(r,l),f=h.createHref(r.mask||r);try{o.pushState(d,``,f)}catch(e){if(e instanceof DOMException&&e.name===`DataCloneError`)throw e;i.location.assign(f)}a&&c&&c({action:s,location:h.location,delta:1})}function p(e,t){s=`REPLACE`;let r=C(e)?e:k(h.location,e,t);n&&n(r,e),l=u();let i=O(r,l),d=h.createHref(r.mask||r);o.replaceState(i,``,d),a&&c&&c({action:s,location:h.location,delta:0})}function m(e){return N(e)}let h={get action(){return s},get location(){return e(i,o)},listen(e){if(c)throw Error(`A history only accepts one active listener`);return i.addEventListener(S,d),c=e,()=>{i.removeEventListener(S,d),c=null}},createHref(e){return t(i,e)},createURL:m,encodeLocation(e){let t=m(e);return{pathname:t.pathname,search:t.search,hash:t.hash}},push:f,replace:p,go(e){return o.go(e)}};return h}function N(e,t=!1){let n=`http://localhost`;typeof window<`u`&&(n=window.location.origin===`null`?window.location.href:window.location.origin),T(n,`No window.location.(origin|href) available to create URL`);let r=typeof e==`string`?e:A(e);return r=r.replace(/ $/,`%20`),!t&&r.startsWith(`//`)&&(r=n+r),new URL(r,n)}function P(e,t,n=`/`){return F(e,t,n,!1)}function F(e,t,n,r,i){let a=oe((typeof t==`string`?j(t):t).pathname||`/`,n);if(a==null)return null;let o=i??L(e),s=null,c=q(a);for(let e=0;s==null&&e{let c={relativePath:s===void 0?e.path||``:s,caseSensitive:e.caseSensitive===!0,childrenIndex:a,route:e};if(c.relativePath.startsWith(`/`)){if(!c.relativePath.startsWith(r)&&o)return;T(c.relativePath.startsWith(r),`Absolute route path "${c.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),c.relativePath=c.relativePath.slice(r.length)}let l=he([r,c.relativePath]),u=n.concat(c);e.children&&e.children.length>0&&(T(e.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${l}".`),R(e.children,t,u,l,o)),!(e.path==null&&!e.index)&&t.push({path:l,score:ne(l,e.index),routesMeta:u})};return e.forEach((e,t)=>{if(e.path===``||!e.path?.includes(`?`))a(e,t);else for(let n of z(e.path))a(e,t,!0,n)}),t}function z(e){let t=e.split(`/`);if(t.length===0)return[];let[n,...r]=t,i=n.endsWith(`?`),a=n.replace(/\?$/,``);if(r.length===0)return i?[a,``]:[a];let o=z(r.join(`/`)),s=[];return s.push(...o.map(e=>e===``?a:[a,e].join(`/`))),i&&s.push(...o),s.map(t=>e.startsWith(`/`)&&t===``?`/`:t)}function B(e){e.sort((e,t)=>e.score===t.score?K(e.routesMeta.map(e=>e.childrenIndex),t.routesMeta.map(e=>e.childrenIndex)):t.score-e.score)}var V=/^:[\w-]+$/,H=3,U=2,W=1,ee=10,te=-2,G=e=>e===`*`;function ne(e,t){let n=e.split(`/`),r=n.length;return n.some(G)&&(r+=te),t&&(r+=U),n.filter(e=>!G(e)).reduce((e,t)=>e+(V.test(t)?H:t===``?W:ee),r)}function K(e,t){return e.length===t.length&&e.slice(0,-1).every((e,n)=>e===t[n])?e[e.length-1]-t[t.length-1]:0}function re(e,t,n=!1){let{routesMeta:r}=e,i={},a=`/`,o=[];for(let e=0;e{if(t===`*`){let e=s[r]||``;o=a.slice(0,a.length-e.length).replace(/(.)\/+$/,`$1`)}let i=s[r];return n&&!i?e[t]=void 0:e[t]=(i||``).replace(/%2F/g,`/`),e},{}),pathname:a,pathnameBase:o,pattern:e}}function ae(e,t=!1,n=!0){E(e===`*`||!e.endsWith(`*`)||e.endsWith(`/*`),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,`/*`)}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,`/*`)}".`);let r=[],i=`^`+e.replace(/\/*\*?$/,``).replace(/^\/*/,`/`).replace(/[\\.*+^${}|()[\]]/g,`\\$&`).replace(/\/:([\w-]+)(\?)?/g,(e,t,n,i,a)=>{if(r.push({paramName:t,isOptional:n!=null}),n){let t=a.charAt(i+e.length);return t&&t!==`/`?`/([^\\/]*)`:`(?:/([^\\/]*))?`}return`/([^\\/]+)`}).replace(/\/([\w-]+)\?(\/|$)/g,`(/$1)?$2`);return e.endsWith(`*`)?(r.push({paramName:`*`}),i+=e===`*`||e===`/*`?`(.*)$`:`(?:\\/(.+)|\\/*)$`):n?i+=`\\/*$`:e!==``&&e!==`/`&&(i+=`(?:(?=\\/|$))`),[new RegExp(i,t?void 0:`i`),r]}function q(e){try{return e.split(`/`).map(e=>decodeURIComponent(e).replace(/\//g,`%2F`)).join(`/`)}catch(t){return E(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function oe(e,t){if(t===`/`)return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith(`/`)?t.length-1:t.length,r=e.charAt(n);return r&&r!==`/`?null:e.slice(n)||`/`}var se=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;function ce(e,t=`/`){let{pathname:n,search:r=``,hash:i=``}=typeof e==`string`?j(e):e,a;return n?(n=me(n),a=n.startsWith(`/`)?le(n.substring(1),`/`):le(n,t)):a=t,{pathname:a,search:ve(r),hash:ye(i)}}function le(e,t){let n=ge(t).split(`/`);return e.split(`/`).forEach(e=>{e===`..`?n.length>1&&n.pop():e!==`.`&&n.push(e)}),n.length>1?n.join(`/`):`/`}function ue(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function de(e){return e.filter((e,t)=>t===0||e.route.path&&e.route.path.length>0)}function fe(e){let t=de(e);return t.map((e,n)=>n===t.length-1?e.pathname:e.pathnameBase)}function pe(e,t,n,r=!1){let i;typeof e==`string`?i=j(e):(i={...e},T(!i.pathname||!i.pathname.includes(`?`),ue(`?`,`pathname`,`search`,i)),T(!i.pathname||!i.pathname.includes(`#`),ue(`#`,`pathname`,`hash`,i)),T(!i.search||!i.search.includes(`#`),ue(`#`,`search`,`hash`,i)));let a=e===``||i.pathname===``,o=a?`/`:i.pathname,s;if(o==null)s=n;else{let e=t.length-1;if(!r&&o.startsWith(`..`)){let t=o.split(`/`);for(;t[0]===`..`;)t.shift(),--e;i.pathname=t.join(`/`)}s=e>=0?t[e]:`/`}let c=ce(i,s),l=o&&o!==`/`&&o.endsWith(`/`),u=(a||o===`.`)&&n.endsWith(`/`);return!c.pathname.endsWith(`/`)&&(l||u)&&(c.pathname+=`/`),c}var me=e=>e.replace(/\/\/+/g,`/`),he=e=>me(e.join(`/`)),ge=e=>e.replace(/\/+$/,``),_e=e=>ge(e).replace(/^\/*/,`/`),ve=e=>!e||e===`?`?``:e.startsWith(`?`)?e:`?`+e,ye=e=>!e||e===`#`?``:e.startsWith(`#`)?e:`#`+e,be=class{constructor(e,t,n,r=!1){this.status=e,this.statusText=t||``,this.internal=r,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function xe(e){return e!=null&&typeof e.status==`number`&&typeof e.statusText==`string`&&typeof e.internal==`boolean`&&`data`in e}function Se(e){return he(e.map(e=>e.route.path).filter(Boolean))||`/`}var Ce=typeof window<`u`&&window.document!==void 0&&window.document.createElement!==void 0;function we(e,t){let n=e;if(typeof n!=`string`||!se.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let r=n,i=!1;if(Ce)try{let e=new URL(window.location.href),r=n.startsWith(`//`)?new URL(e.protocol+n):new URL(n),a=oe(r.pathname,t);r.origin===e.origin&&a!=null?n=a+r.search+r.hash:i=!0}catch{E(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:r,isExternal:i,to:n}}Object.getOwnPropertyNames(Object.prototype).sort().join(`\0`);var Te=[`POST`,`PUT`,`PATCH`,`DELETE`];new Set(Te);var Ee=[`GET`,...Te];new Set(Ee);var De=x.createContext(null);De.displayName=`DataRouter`;var Oe=x.createContext(null);Oe.displayName=`DataRouterState`;var ke=x.createContext(!1);function Ae(){return x.useContext(ke)}var je=x.createContext({isTransitioning:!1});je.displayName=`ViewTransition`;var Me=x.createContext(new Map);Me.displayName=`Fetchers`;var Ne=x.createContext(null);Ne.displayName=`Await`;var Pe=x.createContext(null);Pe.displayName=`Navigation`;var Fe=x.createContext(null);Fe.displayName=`Location`;var Ie=x.createContext({outlet:null,matches:[],isDataRoute:!1});Ie.displayName=`Route`;var Le=x.createContext(null);Le.displayName=`RouteError`;var Re=`REACT_ROUTER_ERROR`,ze=`REDIRECT`,Be=`ROUTE_ERROR_RESPONSE`;function Ve(e){if(e.startsWith(`${Re}:${ze}:{`))try{let t=JSON.parse(e.slice(28));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`&&typeof t.location==`string`&&typeof t.reloadDocument==`boolean`&&typeof t.replace==`boolean`)return t}catch{}}function He(e){if(e.startsWith(`${Re}:${Be}:{`))try{let t=JSON.parse(e.slice(40));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`)return new be(t.status,t.statusText,t.data)}catch{}}function Ue(e,{relative:t}={}){T(We(),`useHref() may be used only in the context of a component.`);let{basename:n,navigator:r}=x.useContext(Pe),{hash:i,pathname:a,search:o}=$e(e,{relative:t}),s=a;return n!==`/`&&(s=a===`/`?n:he([n,a])),r.createHref({pathname:s,search:o,hash:i})}function We(){return x.useContext(Fe)!=null}function Ge(){return T(We(),`useLocation() may be used only in the context of a component.`),x.useContext(Fe).location}var Ke=`You should call navigate() in a React.useEffect(), not when your component is first rendered.`;function qe(e){x.useContext(Pe).static||x.useLayoutEffect(e)}function Je(){let{isDataRoute:e}=x.useContext(Ie);return e?vt():Ye()}function Ye(){T(We(),`useNavigate() may be used only in the context of a component.`);let e=x.useContext(De),{basename:t,navigator:n}=x.useContext(Pe),{matches:r}=x.useContext(Ie),{pathname:i}=Ge(),a=JSON.stringify(fe(r)),o=x.useRef(!1);return qe(()=>{o.current=!0}),x.useCallback((r,s={})=>{if(E(o.current,Ke),!o.current)return;if(typeof r==`number`){n.go(r);return}let c=pe(r,JSON.parse(a),i,s.relative===`path`);e==null&&t!==`/`&&(c.pathname=c.pathname===`/`?t:he([t,c.pathname])),(s.replace?n.replace:n.push)(c,s.state,s)},[t,n,a,i,e])}var Xe=x.createContext(null);function Ze(e){let t=x.useContext(Ie).outlet;return x.useMemo(()=>t&&x.createElement(Xe.Provider,{value:e},t),[t,e])}function Qe(){let{matches:e}=x.useContext(Ie);return e[e.length-1]?.params??{}}function $e(e,{relative:t}={}){let{matches:n}=x.useContext(Ie),{pathname:r}=Ge(),i=JSON.stringify(fe(n));return x.useMemo(()=>pe(e,JSON.parse(i),r,t===`path`),[e,i,r,t])}function et(e,t){return tt(e,t)}function tt(e,t,n){T(We(),`useRoutes() may be used only in the context of a component.`);let{navigator:r}=x.useContext(Pe),{matches:i}=x.useContext(Ie),a=i[i.length-1],o=a?a.params:{},s=a?a.pathname:`/`,c=a?a.pathnameBase:`/`,l=a&&a.route;{let e=l&&l.path||``;bt(s,!l||e.endsWith(`*`)||e.endsWith(`*?`),`You rendered descendant (or called \`useRoutes()\`) at "${s}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. + +Please change the parent to .`)}let u=Ge(),d;if(t){let e=typeof t==`string`?j(t):t;T(c===`/`||e.pathname?.startsWith(c),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${c}" but pathname "${e.pathname}" was given in the \`location\` prop.`),d=e}else d=u;let f=d.pathname||`/`,p=f;if(c!==`/`){let e=c.replace(/^\//,``).split(`/`);p=`/`+f.replace(/^\//,``).split(`/`).slice(e.length).join(`/`)}let m=n&&n.state.matches.length?n.state.matches.map(e=>Object.assign(e,{route:n.manifest[e.route.id]||e.route})):P(e,{pathname:p});E(l||m!=null,`No routes matched location "${d.pathname}${d.search}${d.hash}" `),E(m==null||m[m.length-1].route.element!==void 0||m[m.length-1].route.Component!==void 0||m[m.length-1].route.lazy!==void 0,`Matched leaf route at location "${d.pathname}${d.search}${d.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let h=ct(m&&m.map(e=>Object.assign({},e,{params:Object.assign({},o,e.params),pathname:he([c,r.encodeLocation?r.encodeLocation(e.pathname.replace(/%/g,`%25`).replace(/\?/g,`%3F`).replace(/#/g,`%23`)).pathname:e.pathname]),pathnameBase:e.pathnameBase===`/`?c:he([c,r.encodeLocation?r.encodeLocation(e.pathnameBase.replace(/%/g,`%25`).replace(/\?/g,`%3F`).replace(/#/g,`%23`)).pathname:e.pathnameBase])})),i,n);return t&&h?x.createElement(Fe.Provider,{value:{location:{pathname:`/`,search:``,hash:``,state:null,key:`default`,mask:void 0,...d},navigationType:`POP`}},h):h}function nt(){let e=_t(),t=xe(e)?`${e.status} ${e.statusText}`:e instanceof Error?e.message:JSON.stringify(e),n=e instanceof Error?e.stack:null,r=`rgba(200,200,200, 0.5)`,i={padding:`0.5rem`,backgroundColor:r},a={padding:`2px 4px`,backgroundColor:r},o=null;return console.error(`Error handled by React Router default ErrorBoundary:`,e),o=x.createElement(x.Fragment,null,x.createElement(`p`,null,`💿 Hey developer 👋`),x.createElement(`p`,null,`You can provide a way better UX than this when your app throws errors by providing your own `,x.createElement(`code`,{style:a},`ErrorBoundary`),` or`,` `,x.createElement(`code`,{style:a},`errorElement`),` prop on your route.`)),x.createElement(x.Fragment,null,x.createElement(`h2`,null,`Unexpected Application Error!`),x.createElement(`h3`,{style:{fontStyle:`italic`}},t),n?x.createElement(`pre`,{style:i},n):null,o)}var rt=x.createElement(nt,null),it=class extends x.Component{constructor(e){super(e),this.state={location:e.location,revalidation:e.revalidation,error:e.error}}static getDerivedStateFromError(e){return{error:e}}static getDerivedStateFromProps(e,t){return t.location!==e.location||t.revalidation!==`idle`&&e.revalidation===`idle`?{error:e.error,location:e.location,revalidation:e.revalidation}:{error:e.error===void 0?t.error:e.error,location:t.location,revalidation:e.revalidation||t.revalidation}}componentDidCatch(e,t){this.props.onError?this.props.onError(e,t):console.error(`React Router caught the following error during render`,e)}render(){let e=this.state.error;if(this.context&&typeof e==`object`&&e&&`digest`in e&&typeof e.digest==`string`){let t=He(e.digest);t&&(e=t)}let t=e===void 0?this.props.children:x.createElement(Ie.Provider,{value:this.props.routeContext},x.createElement(Le.Provider,{value:e,children:this.props.component}));return this.context?x.createElement(ot,{error:e},t):t}};it.contextType=ke;var at=new WeakMap;function ot({children:e,error:t}){let{basename:n}=x.useContext(Pe);if(typeof t==`object`&&t&&`digest`in t&&typeof t.digest==`string`){let e=Ve(t.digest);if(e){let r=at.get(t);if(r)throw r;let i=we(e.location,n);if(Ce&&!at.get(t))if(i.isExternal||e.reloadDocument)window.location.href=i.absoluteURL||i.to;else{let n=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(i.to,{replace:e.replace}));throw at.set(t,n),n}return x.createElement(`meta`,{httpEquiv:`refresh`,content:`0;url=${i.absoluteURL||i.to}`})}}return e}function st({routeContext:e,match:t,children:n}){let r=x.useContext(De);return r&&r.static&&r.staticContext&&(t.route.errorElement||t.route.ErrorBoundary)&&(r.staticContext._deepestRenderedBoundaryId=t.route.id),x.createElement(Ie.Provider,{value:e},n)}function ct(e,t=[],n){let r=n?.state;if(e==null){if(!r)return null;if(r.errors)e=r.matches;else if(t.length===0&&!r.initialized&&r.matches.length>0)e=r.matches;else return null}let i=e,a=r?.errors;if(a!=null){let e=i.findIndex(e=>e.route.id&&a?.[e.route.id]!==void 0);T(e>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(a).join(`,`)}`),i=i.slice(0,Math.min(i.length,e+1))}let o=!1,s=-1;if(n&&r){o=r.renderFallback;for(let e=0;e=0?i.slice(0,s+1):[i[0]];break}}}}let c=n?.onError,l=r&&c?(e,t)=>{c(e,{location:r.location,params:r.matches?.[0]?.params??{},pattern:Se(r.matches),errorInfo:t})}:void 0;return i.reduceRight((e,n,c)=>{let u,d=!1,f=null,p=null;r&&(u=a&&n.route.id?a[n.route.id]:void 0,f=n.route.errorElement||rt,o&&(s<0&&c===0?(bt(`route-fallback`,!1,"No `HydrateFallback` element provided to render during initial hydration"),d=!0,p=null):s===c&&(d=!0,p=n.route.hydrateFallbackElement||null)));let m=t.concat(i.slice(0,c+1)),h=()=>{let t;return t=u?f:d?p:n.route.Component?x.createElement(n.route.Component,null):n.route.element?n.route.element:e,x.createElement(st,{match:n,routeContext:{outlet:e,matches:m,isDataRoute:r!=null},children:t})};return r&&(n.route.ErrorBoundary||n.route.errorElement||c===0)?x.createElement(it,{location:r.location,revalidation:r.revalidation,component:f,error:u,children:h(),routeContext:{outlet:null,matches:m,isDataRoute:!0},onError:l}):h()},null)}function lt(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function ut(e){let t=x.useContext(De);return T(t,lt(e)),t}function dt(e){let t=x.useContext(Oe);return T(t,lt(e)),t}function ft(e){let t=x.useContext(Ie);return T(t,lt(e)),t}function pt(e){let t=ft(e),n=t.matches[t.matches.length-1];return T(n.route.id,`${e} can only be used on routes that contain a unique "id"`),n.route.id}function mt(){return pt(`useRouteId`)}function ht(){return dt(`useNavigation`).navigation}function gt(){let{matches:e,loaderData:t}=dt(`useMatches`);return x.useMemo(()=>e.map(e=>I(e,t)),[e,t])}function _t(){let e=x.useContext(Le),t=dt(`useRouteError`),n=pt(`useRouteError`);return e===void 0?t.errors?.[n]:e}function vt(){let{router:e}=ut(`useNavigate`),t=pt(`useNavigate`),n=x.useRef(!1);return qe(()=>{n.current=!0}),x.useCallback(async(r,i={})=>{E(n.current,Ke),n.current&&(typeof r==`number`?await e.navigate(r):await e.navigate(r,{fromRouteId:t,...i}))},[e,t])}var yt={};function bt(e,t,n){!t&&!yt[e]&&(yt[e]=!0,E(!1,n))}x.memo(xt);function xt({routes:e,manifest:t,future:n,state:r,isStatic:i,onError:a}){return tt(e,void 0,{manifest:t,state:r,isStatic:i,onError:a,future:n})}function St({to:e,replace:t,state:n,relative:r}){T(We(),` may be used only in the context of a component.`);let{static:i}=x.useContext(Pe);E(!i,` must not be used on the initial render in a . This is a no-op, but you should modify your code so the is only ever rendered in response to some user interaction or state change.`);let{matches:a}=x.useContext(Ie),{pathname:o}=Ge(),s=Je(),c=pe(e,fe(a),o,r===`path`),l=JSON.stringify(c);return x.useEffect(()=>{s(JSON.parse(l),{replace:t,state:n,relative:r})},[s,l,r,t,n]),null}function Ct(e){return Ze(e.context)}function wt(e){T(!1,`A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .`)}function Tt({basename:e=`/`,children:t=null,location:n,navigationType:r=`POP`,navigator:i,static:a=!1,useTransitions:o}){T(!We(),`You cannot render a inside another . You should never have more than one in your app.`);let s=e.replace(/^\/*/,`/`),c=x.useMemo(()=>({basename:s,navigator:i,static:a,useTransitions:o,future:{}}),[s,i,a,o]);typeof n==`string`&&(n=j(n));let{pathname:l=`/`,search:u=``,hash:d=``,state:f=null,key:p=`default`,mask:m}=n,h=x.useMemo(()=>{let e=oe(l,s);return e==null?null:{location:{pathname:e,search:u,hash:d,state:f,key:p,mask:m},navigationType:r}},[s,l,u,d,f,p,r,m]);return E(h!=null,` is not able to match the URL "${l}${u}${d}" because it does not start with the basename, so the won't render anything.`),h==null?null:x.createElement(Pe.Provider,{value:c},x.createElement(Fe.Provider,{children:t,value:h}))}function Et({children:e,location:t}){return et(Dt(e),t)}x.Component;function Dt(e,t=[]){let n=[];return x.Children.forEach(e,(e,r)=>{if(!x.isValidElement(e))return;let i=[...t,r];if(e.type===x.Fragment){n.push.apply(n,Dt(e.props.children,i));return}T(e.type===wt,`[${typeof e.type==`string`?e.type:e.type.name}] is not a component. All component children of must be a or `),T(!e.props.index||!e.props.children,`An index route cannot have child routes.`);let a={id:e.props.id||i.join(`-`),caseSensitive:e.props.caseSensitive,element:e.props.element,Component:e.props.Component,index:e.props.index,path:e.props.path,middleware:e.props.middleware,loader:e.props.loader,action:e.props.action,hydrateFallbackElement:e.props.hydrateFallbackElement,HydrateFallback:e.props.HydrateFallback,errorElement:e.props.errorElement,ErrorBoundary:e.props.ErrorBoundary,hasErrorBoundary:e.props.hasErrorBoundary===!0||e.props.ErrorBoundary!=null||e.props.errorElement!=null,shouldRevalidate:e.props.shouldRevalidate,handle:e.props.handle,lazy:e.props.lazy};e.props.children&&(a.children=Dt(e.props.children,i)),n.push(a)}),n}var Ot=`get`,kt=`application/x-www-form-urlencoded`;function At(e){return typeof HTMLElement<`u`&&e instanceof HTMLElement}function jt(e){return At(e)&&e.tagName.toLowerCase()===`button`}function Mt(e){return At(e)&&e.tagName.toLowerCase()===`form`}function Nt(e){return At(e)&&e.tagName.toLowerCase()===`input`}function Pt(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function Ft(e,t){return e.button===0&&(!t||t===`_self`)&&!Pt(e)}var It=null;function Lt(){if(It===null)try{new FormData(document.createElement(`form`),0),It=!1}catch{It=!0}return It}var Rt=new Set([`application/x-www-form-urlencoded`,`multipart/form-data`,`text/plain`]);function zt(e){return e!=null&&!Rt.has(e)?(E(!1,`"${e}" is not a valid \`encType\` for \`
\`/\`\` and will default to "${kt}"`),null):e}function Bt(e,t){let n,r,i,a,o;if(Mt(e)){let o=e.getAttribute(`action`);r=o?oe(o,t):null,n=e.getAttribute(`method`)||Ot,i=zt(e.getAttribute(`enctype`))||kt,a=new FormData(e)}else if(jt(e)||Nt(e)&&(e.type===`submit`||e.type===`image`)){let o=e.form;if(o==null)throw Error(`Cannot submit a + + + + } + placeholder="关键词:标题/项目名/核心点" + style={{ width: 260 }} + value={inputKeyword} + onChange={e => setInputKeyword(e.target.value)} + onPressEnter={doSearch} + /> + setInputUserId(e.target.value)} + onPressEnter={doSearch} + /> + setInputUserName(e.target.value)} + onPressEnter={doSearch} + /> + + + + + + `共 ${value} 条`, + onChange: setPage, + }} + scroll={{ x: 1380 }} + columns={[ + { + title: '项目ID', + dataIndex: 'id', + width: 150, + render: (value: string) => {shortId(value)}, + }, + { + title: '用户', + width: 180, + render: (_, record) => ( + + {record.userName || '-'} + {shortId(record.userId)} + + ), + }, + { + title: '项目信息', + width: 260, + render: (_, record) => ( + + {record.title || record.targetProjectName || '-'} + 素材:{record.sourceProjectName || '-'} + 核心:{record.coreContentPoint || '-'} + + ), + }, + { title: '状态', dataIndex: 'status', width: 130, render: (v: string) => }, + { title: '当前步骤', dataIndex: 'currentStepCode', width: 140, render: (v: string) => STEP_MAP[v] || v || '-' }, + { title: '图片结果', dataIndex: 'finalImageUrl', width: 90, render: (v: string) => v ? : }, + { title: '视频结果', dataIndex: 'finalVideoUrl', width: 90, render: (v: string) => v ? : }, + { title: '错误信息', dataIndex: 'errorMessage', width: 220, ellipsis: true, render: (v: string) => v || '-' }, + { title: '创建时间', dataIndex: 'createdAt', width: 170, render: safeDate }, + { title: '更新时间', dataIndex: 'updatedAt', width: 170, render: safeDate }, + { + title: '操作', + fixed: 'right', + width: 110, + render: (_, record) => ( + + ), + }, + ]} + /> + + + + ); +}; + +export default AdminHotOpeningReplications; diff --git a/video-gen-admin/src/pages/AdminImageEngines.tsx.tmp.30304.1779097765352 b/video-gen-admin/src/pages/AdminImageEngines.tsx.tmp.30304.1779097765352 deleted file mode 100644 index 0a1dad8b..00000000 --- a/video-gen-admin/src/pages/AdminImageEngines.tsx.tmp.30304.1779097765352 +++ /dev/null @@ -1,250 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { - Button, Card, Form, Input, message, Modal, Popconfirm, Select, Space, Switch, Table, Tag, Typography, -} from 'antd'; -import { - PictureOutlined, PlusOutlined, EditOutlined, DeleteOutlined, -} from '@ant-design/icons'; -import { getImageEngines, saveImageEngine, deleteImageEngine } from '../api'; - -interface ImageEngine { - id: string; - name: string; - provider: string; - apiBase: string; - apiKey: string; - modelName: string; - supportedSizes: string[]; - supportedStyles: string[]; - generateUrl: string; - isActive: boolean; - priority: number; -} - -function parseJsonArray(val: unknown): any[] { - if (Array.isArray(val)) return val; - if (typeof val === 'string') { - try { return JSON.parse(val); } catch { return []; } - } - return []; -} - -const AdminImageEngines: React.FC = () => { - const [engines, setEngines] = useState([]); - const [loading, setLoading] = useState(false); - const [modal, setModal] = useState<{ open: boolean; engine: ImageEngine | null }>({ open: false, engine: null }); - const [form] = Form.useForm(); - - const load = async () => { - setLoading(true); - try { - const data = await getImageEngines(); - setEngines(data.map((e: any) => ({ - ...e, - supportedSizes: parseJsonArray(e.supportedSizes), - supportedStyles: parseJsonArray(e.supportedStyles), - }))); - } catch { - message.error('加载图片引擎失败'); - } finally { - setLoading(false); - } - }; - - useEffect(() => { load(); }, []); - - const handleSave = async () => { - try { - const values = await form.validateFields(); - const payload = { - name: values.name, - provider: values.provider, - api_base: values.apiBase, - api_key: values.apiKey, - model_name: values.modelName, - supported_sizes: JSON.stringify(values.supportedSizes || []), - supported_styles: JSON.stringify(values.supportedStyles || []), - generate_url: values.generateUrl || '', - is_active: values.isActive ?? true, - priority: values.priority ?? 0, - }; - if (modal.engine) { - await saveImageEngine({ id: modal.engine.id, ...payload }); - message.success('已更新'); - } else { - await saveImageEngine(payload); - message.success('已添加'); - } - setModal({ open: false, engine: null }); - form.resetFields(); - load(); - } catch (e: any) { - if (e?.errorFields) return; - message.error(e?.message || '保存失败'); - } - }; - - const handleDelete = async (id: string) => { - try { - await deleteImageEngine(id); - message.success('已删除'); - load(); - } catch { - message.error('删除失败'); - } - }; - - const openEdit = (engine?: ImageEngine) => { - setModal({ open: true, engine: engine || null }); - if (engine) { - form.setFieldsValue(engine); - } else { - form.resetFields(); - form.setFieldsValue({ - isActive: true, priority: 0, - supportedSizes: ['1024x1024', '1024x1792', '1792x1024'], - supportedStyles: ['realistic', 'anime', 'oil_painting'], - }); - } - }; - - const columns = [ - { - title: '引擎名称', key: 'name', width: 180, - render: (_: any, r: ImageEngine) => ( -
-
-
- {r.name} -
{r.provider}
-
-
- ), - }, - { - title: '支持尺寸', dataIndex: 'supportedSizes', width: 280, - render: (sizes: string[]) => {sizes.map(s => {s})}, - }, - { - title: '支持风格', dataIndex: 'supportedStyles', width: 280, - render: (styles: string[]) => {styles.map(s => {s})}, - }, - { - title: '状态', dataIndex: 'isActive', width: 80, - render: (v: boolean) => {v ? '启用' : '停用'}, - }, - { - title: '操作', key: 'action', width: 150, fixed: 'right' as const, - render: (_: any, r: ImageEngine) => ( - - - handleDelete(r.id)}> - - - - ), - }, - ]; - - return ( -
- -
- - - 图片引擎配置 - {engines.length} 个引擎 - - -
- -
- - - {modal.engine ? '编辑引擎' : '添加引擎'}} - open={modal.open} - onOk={handleSave} - onCancel={() => { setModal({ open: false, engine: null }); form.resetFields(); }} - okText="保存" cancelText="取消" width={620} - > - -
- - - - - - - - - - - - - - - - - - -
- -
- - - {modal.engine ? '编辑引擎' : '添加引擎'}} - open={modal.open} - onOk={handleSave} - onCancel={() => { setModal({ open: false, engine: null }); form.resetFields(); }} - okText="保存" cancelText="取消" width={680} - > - -
- - - - - - - - - - - - - - - - - - -
- -
- - - {modal.item ? '编辑行业' : '添加行业'}} - open={modal.open} - onOk={handleSave} - onCancel={() => { setModal({ open: false, item: null }); form.resetFields(); }} - okText="保存" cancelText="取消" width={640} - confirmLoading={saving} - > - -
- - - - - - -
- - - - - - - - - - - {/* Option Groups */} -
- 行业选项配置 - - 添加选项组,每组包含名称和多个选项,前台将显示为下拉选择 - -
- - {(fields, { add, remove }) => ( -
- {fields.map(({ key, name, ...restField }) => ( -
-
- - - - - - -
- - -
- ); -}; - -export default AdminIndustries; diff --git a/video-gen-admin/src/pages/AdminIndustries.tsx.tmp.30304.1779097121934 b/video-gen-admin/src/pages/AdminIndustries.tsx.tmp.30304.1779097121934 deleted file mode 100644 index b9d0181e..00000000 --- a/video-gen-admin/src/pages/AdminIndustries.tsx.tmp.30304.1779097121934 +++ /dev/null @@ -1,490 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { - Button, Card, Form, Input, message, Modal, Popconfirm, Space, Switch, Table, Tag, Typography, Dropdown, Select, -} from 'antd'; -import { - AppstoreOutlined, PlusOutlined, EditOutlined, DeleteOutlined, DownOutlined, MinusCircleOutlined, - ShoppingCartOutlined, BookOutlined, HomeOutlined, FireOutlined, RocketOutlined, SkinOutlined, - CompassOutlined, HeartOutlined, CarOutlined, CameraOutlined, CloudOutlined, StarOutlined, - TrophyOutlined, ThunderboltOutlined, BulbOutlined, CoffeeOutlined, CrownOutlined, DashboardOutlined, - FlagOutlined, GlobalOutlined, GiftOutlined, LaptopOutlined, MobileOutlined, MonitorOutlined, - PayCircleOutlined, PictureOutlined, PlayCircleOutlined, SafetyOutlined, - ShoppingOutlined, SmileOutlined, SoundOutlined, TagOutlined, TeamOutlined, - ToolOutlined, TruckOutlined, VideoCameraOutlined, WalletOutlined, BankOutlined, - BuildOutlined, ExperimentOutlined, HighlightOutlined, IdcardOutlined, - MedicineBoxOutlined, ReadOutlined, RestOutlined, SketchOutlined, SolutionOutlined, -} from '@ant-design/icons'; -import { getIndustryConfigs, saveIndustryConfig, deleteIndustryConfig } from '../api'; - -interface OptionGroup { - name: string; - options: string[]; -} - -interface IndustryItem { - id: string; - key: string; - label: string; - icon: string; - description: string; - skills: string; - optionGroups: OptionGroup[]; - isActive: boolean; - sortOrder: number; -} - -// Icon library for industries -const ICON_OPTIONS: { name: string; label: string; component: React.ReactNode }[] = [ - { name: 'ShoppingCartOutlined', label: '购物', component: }, - { name: 'BookOutlined', label: '书籍', component: }, - { name: 'HomeOutlined', label: '房产', component: }, - { name: 'FireOutlined', label: '火', component: }, - { name: 'RocketOutlined', label: '科技', component: }, - { name: 'SkinOutlined', label: '时尚', component: }, - { name: 'CompassOutlined', label: '指南', component: }, - { name: 'HeartOutlined', label: '健康', component: }, - { name: 'CarOutlined', label: '汽车', component: }, - { name: 'CameraOutlined', label: '相机', component: }, - { name: 'CloudOutlined', label: '云', component: }, - { name: 'StarOutlined', label: '星', component: }, - { name: 'TrophyOutlined', label: '奖杯', component: }, - { name: 'ThunderboltOutlined', label: '闪电', component: }, - { name: 'BulbOutlined', label: '灯泡', component: }, - { name: 'CoffeeOutlined', label: '咖啡', component: }, - { name: 'CrownOutlined', label: '皇冠', component: }, - { name: 'DashboardOutlined', label: '仪表', component: }, - { name: 'FlagOutlined', label: '旗帜', component: }, - { name: 'GlobalOutlined', label: '全球', component: }, - { name: 'GiftOutlined', label: '礼物', component: }, - { name: 'LaptopOutlined', label: '笔记本', component: }, - { name: 'MobileOutlined', label: '手机', component: }, - { name: 'MonitorOutlined', label: '显示器', component: }, - { name: 'PayCircleOutlined', label: '支付', component: }, - { name: 'PictureOutlined', label: '图片', component: }, - { name: 'PlayCircleOutlined', label: '播放', component: }, - { name: 'SafetyOutlined', label: '安全', component: }, - { name: 'ShoppingOutlined', label: '商店', component: }, - { name: 'SmileOutlined', label: '笑脸', component: }, - { name: 'SoundOutlined', label: '声音', component: }, - { name: 'TagOutlined', label: '标签', component: }, - { name: 'TeamOutlined', label: '团队', component: }, - { name: 'ToolOutlined', label: '工具', component: }, - { name: 'TruckOutlined', label: '物流', component: }, - { name: 'VideoCameraOutlined', label: '视频', component: }, - { name: 'WalletOutlined', label: '钱包', component: }, - { name: 'BankOutlined', label: '银行', component: }, - { name: 'BuildOutlined', label: '建筑', component: }, - { name: 'ExperimentOutlined', label: '实验', component: }, - { name: 'HighlightOutlined', label: '高亮', component: }, - { name: 'IdcardOutlined', label: '名片', component: }, - { name: 'MedicineBoxOutlined', label: '医药', component: }, - { name: 'ReadOutlined', label: '阅读', component: }, - { name: 'RestOutlined', label: '休息', component: }, - { name: 'SketchOutlined', label: '钻石', component: }, - { name: 'SolutionOutlined', label: '方案', component: }, -]; - -const iconMap: Record = Object.fromEntries( - ICON_OPTIONS.map(o => [o.name, o.component]) -); - -function getIconComponent(name: string): React.ReactNode { - return iconMap[name] || ; -} - -// Parse skills JSON into { skillItems, optionGroups } -function parseSkills(raw: string | any[]): { skillItems: { key: string; label: string }[]; optionGroups: OptionGroup[] } { - try { - const arr = typeof raw === 'string' ? JSON.parse(raw) : raw; - if (!Array.isArray(arr)) return { skillItems: [], optionGroups: [] }; - const skillItems: { key: string; label: string }[] = []; - const optionGroups: OptionGroup[] = []; - for (const item of arr) { - if (item && item.type === 'option_group' && item.name && Array.isArray(item.options)) { - optionGroups.push({ name: item.name, options: item.options }); - } else if (item && item.key && item.label) { - skillItems.push({ key: item.key, label: item.label }); - } - } - return { skillItems, optionGroups }; - } catch { - return { skillItems: [], optionGroups: [] }; - } -} - -// Icon Picker Component -const IconPicker: React.FC<{ value?: string; onChange?: (v: string) => void }> = ({ value, onChange }) => { - const selected = ICON_OPTIONS.find(o => o.name === value); - return ( - ( -
-
- {ICON_OPTIONS.map(opt => ( -
{ e.preventDefault(); e.stopPropagation(); onChange?.(opt.name); }} title={opt.label} style={{ - width: 40, height: 40, borderRadius: 8, display: 'flex', alignItems: 'center', justifyContent: 'center', - cursor: 'pointer', fontSize: 18, transition: 'all 0.15s', - background: value === opt.name ? '#6366f1' : 'transparent', - color: value === opt.name ? '#fff' : '#64748b', - border: value === opt.name ? 'none' : '1px solid transparent', - }} - onMouseEnter={e => { if (value !== opt.name) e.currentTarget.style.background = '#f1f5f9'; }} - onMouseLeave={e => { if (value !== opt.name) e.currentTarget.style.background = 'transparent'; }} - > - {opt.component} -
- ))} -
-
- )} - > -
- {value ? ( - <> - {getIconComponent(value)} - {selected?.label || value} - - ) : ( - 选择图标 - )} - -
-
- ); -}; - -const AdminIndustries: React.FC = () => { - const [industries, setIndustries] = useState([]); - const [loading, setLoading] = useState(false); - const [saving, setSaving] = useState(false); - const [modal, setModal] = useState<{ open: boolean; item: IndustryItem | null }>({ open: false, item: null }); - const [form] = Form.useForm(); - - const load = async () => { - setLoading(true); - try { - const data = await getIndustryConfigs(); - setIndustries(data.map((item: any) => { - const { skillItems, optionGroups } = parseSkills(item.skills); - return { - id: item.id, - key: item.key, - label: item.label, - icon: item.icon || '', - description: item.description || '', - skills: JSON.stringify(skillItems), - optionGroups, - isActive: item.is_active ?? item.isActive ?? true, - sortOrder: item.sort_order ?? item.sortOrder ?? 0, - }; - })); - } catch { - message.error('加载行业配置失败'); - } finally { - setLoading(false); - } - }; - - useEffect(() => { load(); }, []); - - const handleSave = async () => { - try { - const values = await form.validateFields(); - setSaving(true); - - // Build skills array: skill items + option groups - const skillsArr: any[] = []; - if (values.skills_wentutujie?.trim()) { - skillsArr.push({ type: 'skill', key: '文图理解', label: values.skills_wentutujie.trim() }); - } - // Add option groups - const groups: OptionGroup[] = (values.optionGroups || []) - .filter((g: any) => g?.name?.trim()) - .map((g: any) => ({ - name: g.name.trim(), - options: (g.options || []).filter((o: string) => o?.trim()), - })) - .filter((g: OptionGroup) => g.options.length > 0); - for (const g of groups) { - skillsArr.push({ type: 'option_group', name: g.name, options: g.options }); - } - - const payload: any = { - key: values.key, - label: values.label, - icon: values.icon || '', - description: values.description || '', - skills: skillsArr, - is_active: values.is_active ?? true, - sort_order: values.sort_order ?? 0, - }; - if (modal.item?.id) { - await saveIndustryConfig({ id: modal.item.id, ...payload }); - message.success('已更新'); - } else { - await saveIndustryConfig(payload); - message.success('已添加'); - } - setModal({ open: false, item: null }); - form.resetFields(); - load(); - } catch (e: any) { - if (e?.errorFields) return; - message.error(e?.message || '保存失败'); - } finally { - setSaving(false); - } - }; - - const handleDelete = async (id: string) => { - try { - await deleteIndustryConfig(id); - message.success('已删除'); - load(); - } catch (e: any) { - message.error(e?.message || '删除失败'); - } - }; - - const openEdit = (item?: IndustryItem) => { - setModal({ open: true, item: item || null }); - let wentutujie = ''; - let wentutujieImage = ''; - let optionGroups: OptionGroup[] = []; - if (item) { - // Parse skills for 文图理解 video and image prompts - try { - const arr = JSON.parse(item.skills); - if (Array.isArray(arr)) { - for (const s of arr) { - if (s.key === '文图理解生成视频提示词' || s.key === '文图理解') { wentutujie = s.label || ''; } - if (s.key === '文图理解生成图片提示词') { wentutujieImage = s.label || ''; } - } - } - } catch { /* ignore */ } - optionGroups = item.optionGroups.length > 0 ? item.optionGroups : [{ name: '', options: [] }]; - } - if (item) { - form.setFieldsValue({ - key: item.key, - label: item.label, - icon: item.icon || '', - description: item.description, - skills_wentutujie: wentutujie, - skills_wentutujie_image: wentutujieImage, - optionGroups, - is_active: item.isActive, - sort_order: item.sortOrder, - }); - } else { - form.resetFields(); - form.setFieldsValue({ is_active: true, sort_order: 0, optionGroups: [{ name: '', options: [] }] }); - } - }; - - const columns = [ - { - title: '行业', key: 'industry', width: 180, - render: (_: any, r: IndustryItem) => ( -
-
- {getIconComponent(r.icon)} -
-
- {r.label} -
{r.key}
-
-
- ), - }, - { title: '描述', dataIndex: 'description', ellipsis: true }, - { - title: '选项配置', key: 'optionGroups', width: 260, - render: (_: any, r: IndustryItem) => { - if (!r.optionGroups || r.optionGroups.length === 0) { - return 未配置; - } - return ( -
- {r.optionGroups.map((g, i) => ( -
- {g.name} - - {g.options.slice(0, 3).join('、')}{g.options.length > 3 ? `...${g.options.length}项` : ''} - -
- ))} -
- ); - }, - }, - { - title: '文图理解生成视频提示词', dataIndex: 'skills', ellipsis: true, - render: (v: string) => { - try { - const arr = JSON.parse(v); - if (Array.isArray(arr)) { - const wtj = arr.find((s: any) => s.key === '文图理解生成视频提示词' || s.key === '文图理解'); - if (wtj) return {wtj.label}; - } - } catch { /* ignore */ } - return -; - }, - }, - { - title: '文图理解生成图片提示词', dataIndex: 'skills', ellipsis: true, - render: (v: string) => { - try { - const arr = JSON.parse(v); - if (Array.isArray(arr)) { - const wtj = arr.find((s: any) => s.key === '文图理解生成图片提示词'); - if (wtj) return {wtj.label}; - } - } catch { /* ignore */ } - return -; - }, - }, - { - title: '状态', dataIndex: 'isActive', width: 80, - render: (v: boolean) => {v ? '启用' : '停用'}, - }, - { - title: '操作', key: 'action', width: 150, fixed: 'right' as const, - render: (_: any, r: IndustryItem) => ( - - - handleDelete(r.id)}> - - - - ), - }, - ]; - - return ( -
- -
- - - 行业与技能配置 - {industries.length} 个行业 - - -
- -
- - - {modal.item ? '编辑行业' : '添加行业'}} - open={modal.open} - onOk={handleSave} - onCancel={() => { setModal({ open: false, item: null }); form.resetFields(); }} - okText="保存" cancelText="取消" width={640} - confirmLoading={saving} - > -
-
- - - - - - -
- - - - - - - - - - - {/* Option Groups */} -
- 行业选项配置 - - 添加选项组,每组包含名称和多个选项,前台将显示为下拉选择 - -
- - {(fields, { add, remove }) => ( -
- {fields.map(({ key, name, ...restField }) => ( -
-
- - - - - - -
- - -
- ); -}; - -export default AdminIndustries; diff --git a/video-gen-admin/src/pages/AdminLayout.tsx b/video-gen-admin/src/pages/AdminLayout.tsx index 785efdf1..8be68ef0 100644 --- a/video-gen-admin/src/pages/AdminLayout.tsx +++ b/video-gen-admin/src/pages/AdminLayout.tsx @@ -261,23 +261,25 @@ const AdminLayout: React.FC = () => {
{/* Menu */} - { - if (key.startsWith('group-')) return; - navigate(key); - }} - theme="light" - /> +
+ { + if (key.startsWith('group-')) return; + navigate(key); + }} + theme="light" + /> +
diff --git a/video-gen-admin/src/pages/AdminLayout.tsx.tmp.30304.1779098260634 b/video-gen-admin/src/pages/AdminLayout.tsx.tmp.30304.1779098260634 deleted file mode 100644 index 04e55c68..00000000 --- a/video-gen-admin/src/pages/AdminLayout.tsx.tmp.30304.1779098260634 +++ /dev/null @@ -1,318 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { Layout, Menu, Avatar, Typography, Dropdown, Spin, Modal, Form, Input, Space, message } from 'antd'; -import { - DashboardOutlined, - UserOutlined, - RobotOutlined, - SettingOutlined, - BellOutlined, - ThunderboltOutlined, - LogoutOutlined, - LockOutlined, - WalletOutlined, - CalculatorOutlined, - DollarOutlined, - AppstoreOutlined, - PlayCircleOutlined, - GiftOutlined, - HomeOutlined, - StarOutlined, - HeartOutlined, - CameraOutlined, - FileTextOutlined, - HistoryOutlined, - VideoCameraOutlined, - PictureOutlined, -} from '@ant-design/icons'; -import { Outlet, useNavigate, useLocation, Navigate } from 'react-router-dom'; -import { useAdminStore } from '../store'; -import { getMenuConfigs, adminChangePassword } from '../api'; - -const { Sider, Content } = Layout; - -const iconMap: Record = { - DashboardOutlined: , - UserOutlined: , - RobotOutlined: , - SettingOutlined: , - BellOutlined: , - LogoutOutlined: , - WalletOutlined: , - CalculatorOutlined: , - DollarOutlined: , - AppstoreOutlined: , - PlayCircleOutlined: , - GiftOutlined: , - HomeOutlined: , - StarOutlined: , - HeartOutlined: , - CameraOutlined: , - FileTextOutlined: , - HistoryOutlined: , - VideoCameraOutlined: , -}; - -const AdminLayout: React.FC = () => { - const navigate = useNavigate(); - const location = useLocation(); - const { user, loading, logout } = useAdminStore(); - const [collapsed, setCollapsed] = useState(false); - const [menuItems, setMenuItems] = useState([]); - const [pwdModal, setPwdModal] = useState(false); - const [pwdForm] = Form.useForm(); - - useEffect(() => { - getMenuConfigs().then(data => { - let menus = data.filter((m: any) => { - const target = m.menu_target ?? m.menuTarget ?? 'admin'; - const active = m.is_active ?? m.isActive ?? true; - return active && (target === 'admin' || target === 'both'); - }); - // Non-admin backend users: filter by allowedMenus - const isAdminUser = !!(user?.isAdmin ?? (user as any)?.is_admin); - if (user && !isAdminUser) { - const allowed = user.allowedMenus ?? (user as any)?.allowed_menus; - if (allowed && Array.isArray(allowed) && allowed.length > 0) { - const allowedSet = new Set(allowed); - menus = menus.filter((m: any) => { - const menuType = m.menu_type ?? m.menuType; - if (menuType === 'group') { - return menus.some((c: any) => { - const pid = c.parent_id ?? c.parentId; - return pid === m.id && allowedSet.has(c.path); - }); - } - return allowedSet.has(m.path); - }); - } else { - // No allowed menus set and not admin = show nothing - menus = []; - } - } - setMenuItems(menus); - }).catch(() => {}); - }, [user]); - - if (loading) { - return ( -
- -
- ); - } - - if (!user) { - return ; - } - - // Build menu items for Ant Design Menu — single sorted list interleaving groups and pages - const childMap: Record = {}; - menuItems.filter(m => (m.menu_type ?? m.menuType) !== 'group' && (m.parent_id ?? m.parentId)).forEach(m => { - const pid = m.parent_id ?? m.parentId; - if (!childMap[pid]) childMap[pid] = []; - childMap[pid].push(m); - }); - - // Sort all menu items by sortOrder, then build ant menu items - const sorted = [...menuItems].sort((a, b) => (a.sort_order ?? a.sortOrder ?? 0) - (b.sort_order ?? b.sortOrder ?? 0)); - const antMenuItems: any[] = []; - - sorted.forEach(m => { - const menuType = m.menu_type ?? m.menuType; - const parentId = m.parent_id ?? m.parentId; - if (menuType === 'group') { - const children = (childMap[m.id] || []) - .sort((a, b) => (a.sort_order ?? a.sortOrder ?? 0) - (b.sort_order ?? b.sortOrder ?? 0)) - .map(c => ({ - key: c.path, - icon: iconMap[c.icon] || undefined, - label: c.label, - })); - if (children.length > 0) { - antMenuItems.push({ - key: `group-${m.id}`, - icon: iconMap[m.icon] || undefined, - label: m.label, - children, - }); - } - } else if (!parentId) { - antMenuItems.push({ - key: m.path, - icon: iconMap[m.icon] || undefined, - label: m.label, - }); - } - }); - - // Fallback only for admin users — non-admin users with no permissions see nothing - const isAdminUser = !!(user?.isAdmin ?? (user as any)?.is_admin); - if (antMenuItems.length === 0 && isAdminUser) { - antMenuItems.push( - { key: '/', icon: , label: '数据概览' }, - { key: '/users', icon: , label: '用户管理' }, - ); - } - - const selectedKey = location.pathname; - - // Find the leaf menu key that matches (for sub-menus, need to find the right key) - let activeKey = selectedKey; - const allLeafKeys: string[] = []; - antMenuItems.forEach(item => { - if (item.children) { - item.children.forEach((c: any) => allLeafKeys.push(c.key)); - } else { - allLeafKeys.push(item.key); - } - }); - // Exact match or prefix match - if (!allLeafKeys.includes(activeKey)) { - activeKey = allLeafKeys.find(k => activeKey.startsWith(k)) || '/'; - } - - // Find open keys for sub-menus - const openKeys: string[] = []; - antMenuItems.forEach(item => { - if (item.children) { - if (item.children.some((c: any) => c.key === activeKey)) { - openKeys.push(item.key); - } - } - }); - - return ( - - - {/* Logo */} -
-
- -
- {!collapsed && ( - - 管理后台 - - )} -
- - {/* Menu */} - { - if (key.startsWith('group-')) return; - navigate(key); - }} - style={{ background: 'transparent', borderRight: 0, marginTop: 8 }} - theme="dark" - /> - - - - - {/* Header */} -
- - {antMenuItems.find(m => m.key === activeKey)?.label - || antMenuItems.flatMap(m => m.children || []).find((c: any) => c.key === activeKey)?.label - || '管理后台'} - - , label: user?.username, disabled: true }, - { type: 'divider' as const }, - { key: 'changePwd', icon: , label: '修改密码' }, - { key: 'logout', icon: , label: '退出登录', danger: true }, - ], - onClick: ({ key }) => { - if (key === 'logout') { logout(); navigate('/login'); } - if (key === 'changePwd') { setPwdModal(true); pwdForm.resetFields(); } - }, - }} placement="bottomRight" arrow> -
- } - style={{ background: 'linear-gradient(135deg, #6366f1, #8b5cf6)' }} /> - - {user?.username} - -
-
-
- - {/* Content */} - - {antMenuItems.length === 0 && !isAdminUser ? ( -
- -
暂无任何权限
-
请联系管理员配置菜单权限
-
- ) : ( - - )} -
-
- - 修改密码} - open={pwdModal} - onOk={async () => { - try { - const values = await pwdForm.validateFields(); - if (values.newPassword !== values.confirmPassword) { - message.error('两次输入的密码不一致'); - return; - } - await adminChangePassword(values.oldPassword, values.newPassword); - message.success('密码修改成功'); - setPwdModal(false); - pwdForm.resetFields(); - } catch (e: any) { - if (e?.errorFields) return; - message.error(e?.message || '修改失败'); - } - }} - onCancel={() => { setPwdModal(false); pwdForm.resetFields(); }} - okText="确认修改" cancelText="取消" width={420} - > -
- - - - - - - - - - -
- - ); -}; - -export default AdminLayout; diff --git a/video-gen-admin/src/pages/AdminLayout.tsx.tmp.30304.1779098268240 b/video-gen-admin/src/pages/AdminLayout.tsx.tmp.30304.1779098268240 deleted file mode 100644 index b22f3cd1..00000000 --- a/video-gen-admin/src/pages/AdminLayout.tsx.tmp.30304.1779098268240 +++ /dev/null @@ -1,319 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { Layout, Menu, Avatar, Typography, Dropdown, Spin, Modal, Form, Input, Space, message } from 'antd'; -import { - DashboardOutlined, - UserOutlined, - RobotOutlined, - SettingOutlined, - BellOutlined, - ThunderboltOutlined, - LogoutOutlined, - LockOutlined, - WalletOutlined, - CalculatorOutlined, - DollarOutlined, - AppstoreOutlined, - PlayCircleOutlined, - GiftOutlined, - HomeOutlined, - StarOutlined, - HeartOutlined, - CameraOutlined, - FileTextOutlined, - HistoryOutlined, - VideoCameraOutlined, - PictureOutlined, -} from '@ant-design/icons'; -import { Outlet, useNavigate, useLocation, Navigate } from 'react-router-dom'; -import { useAdminStore } from '../store'; -import { getMenuConfigs, adminChangePassword } from '../api'; - -const { Sider, Content } = Layout; - -const iconMap: Record = { - DashboardOutlined: , - UserOutlined: , - RobotOutlined: , - SettingOutlined: , - BellOutlined: , - LogoutOutlined: , - WalletOutlined: , - CalculatorOutlined: , - DollarOutlined: , - AppstoreOutlined: , - PlayCircleOutlined: , - GiftOutlined: , - HomeOutlined: , - StarOutlined: , - HeartOutlined: , - CameraOutlined: , - FileTextOutlined: , - HistoryOutlined: , - VideoCameraOutlined: , - PictureOutlined: , -}; - -const AdminLayout: React.FC = () => { - const navigate = useNavigate(); - const location = useLocation(); - const { user, loading, logout } = useAdminStore(); - const [collapsed, setCollapsed] = useState(false); - const [menuItems, setMenuItems] = useState([]); - const [pwdModal, setPwdModal] = useState(false); - const [pwdForm] = Form.useForm(); - - useEffect(() => { - getMenuConfigs().then(data => { - let menus = data.filter((m: any) => { - const target = m.menu_target ?? m.menuTarget ?? 'admin'; - const active = m.is_active ?? m.isActive ?? true; - return active && (target === 'admin' || target === 'both'); - }); - // Non-admin backend users: filter by allowedMenus - const isAdminUser = !!(user?.isAdmin ?? (user as any)?.is_admin); - if (user && !isAdminUser) { - const allowed = user.allowedMenus ?? (user as any)?.allowed_menus; - if (allowed && Array.isArray(allowed) && allowed.length > 0) { - const allowedSet = new Set(allowed); - menus = menus.filter((m: any) => { - const menuType = m.menu_type ?? m.menuType; - if (menuType === 'group') { - return menus.some((c: any) => { - const pid = c.parent_id ?? c.parentId; - return pid === m.id && allowedSet.has(c.path); - }); - } - return allowedSet.has(m.path); - }); - } else { - // No allowed menus set and not admin = show nothing - menus = []; - } - } - setMenuItems(menus); - }).catch(() => {}); - }, [user]); - - if (loading) { - return ( -
- -
- ); - } - - if (!user) { - return ; - } - - // Build menu items for Ant Design Menu — single sorted list interleaving groups and pages - const childMap: Record = {}; - menuItems.filter(m => (m.menu_type ?? m.menuType) !== 'group' && (m.parent_id ?? m.parentId)).forEach(m => { - const pid = m.parent_id ?? m.parentId; - if (!childMap[pid]) childMap[pid] = []; - childMap[pid].push(m); - }); - - // Sort all menu items by sortOrder, then build ant menu items - const sorted = [...menuItems].sort((a, b) => (a.sort_order ?? a.sortOrder ?? 0) - (b.sort_order ?? b.sortOrder ?? 0)); - const antMenuItems: any[] = []; - - sorted.forEach(m => { - const menuType = m.menu_type ?? m.menuType; - const parentId = m.parent_id ?? m.parentId; - if (menuType === 'group') { - const children = (childMap[m.id] || []) - .sort((a, b) => (a.sort_order ?? a.sortOrder ?? 0) - (b.sort_order ?? b.sortOrder ?? 0)) - .map(c => ({ - key: c.path, - icon: iconMap[c.icon] || undefined, - label: c.label, - })); - if (children.length > 0) { - antMenuItems.push({ - key: `group-${m.id}`, - icon: iconMap[m.icon] || undefined, - label: m.label, - children, - }); - } - } else if (!parentId) { - antMenuItems.push({ - key: m.path, - icon: iconMap[m.icon] || undefined, - label: m.label, - }); - } - }); - - // Fallback only for admin users — non-admin users with no permissions see nothing - const isAdminUser = !!(user?.isAdmin ?? (user as any)?.is_admin); - if (antMenuItems.length === 0 && isAdminUser) { - antMenuItems.push( - { key: '/', icon: , label: '数据概览' }, - { key: '/users', icon: , label: '用户管理' }, - ); - } - - const selectedKey = location.pathname; - - // Find the leaf menu key that matches (for sub-menus, need to find the right key) - let activeKey = selectedKey; - const allLeafKeys: string[] = []; - antMenuItems.forEach(item => { - if (item.children) { - item.children.forEach((c: any) => allLeafKeys.push(c.key)); - } else { - allLeafKeys.push(item.key); - } - }); - // Exact match or prefix match - if (!allLeafKeys.includes(activeKey)) { - activeKey = allLeafKeys.find(k => activeKey.startsWith(k)) || '/'; - } - - // Find open keys for sub-menus - const openKeys: string[] = []; - antMenuItems.forEach(item => { - if (item.children) { - if (item.children.some((c: any) => c.key === activeKey)) { - openKeys.push(item.key); - } - } - }); - - return ( - - - {/* Logo */} -
-
- -
- {!collapsed && ( - - 管理后台 - - )} -
- - {/* Menu */} - { - if (key.startsWith('group-')) return; - navigate(key); - }} - style={{ background: 'transparent', borderRight: 0, marginTop: 8 }} - theme="dark" - /> - - - - - {/* Header */} -
- - {antMenuItems.find(m => m.key === activeKey)?.label - || antMenuItems.flatMap(m => m.children || []).find((c: any) => c.key === activeKey)?.label - || '管理后台'} - - , label: user?.username, disabled: true }, - { type: 'divider' as const }, - { key: 'changePwd', icon: , label: '修改密码' }, - { key: 'logout', icon: , label: '退出登录', danger: true }, - ], - onClick: ({ key }) => { - if (key === 'logout') { logout(); navigate('/login'); } - if (key === 'changePwd') { setPwdModal(true); pwdForm.resetFields(); } - }, - }} placement="bottomRight" arrow> -
- } - style={{ background: 'linear-gradient(135deg, #6366f1, #8b5cf6)' }} /> - - {user?.username} - -
-
-
- - {/* Content */} - - {antMenuItems.length === 0 && !isAdminUser ? ( -
- -
暂无任何权限
-
请联系管理员配置菜单权限
-
- ) : ( - - )} -
-
- - 修改密码} - open={pwdModal} - onOk={async () => { - try { - const values = await pwdForm.validateFields(); - if (values.newPassword !== values.confirmPassword) { - message.error('两次输入的密码不一致'); - return; - } - await adminChangePassword(values.oldPassword, values.newPassword); - message.success('密码修改成功'); - setPwdModal(false); - pwdForm.resetFields(); - } catch (e: any) { - if (e?.errorFields) return; - message.error(e?.message || '修改失败'); - } - }} - onCancel={() => { setPwdModal(false); pwdForm.resetFields(); }} - okText="确认修改" cancelText="取消" width={420} - > -
- - - - - - - - - - -
- - ); -}; - -export default AdminLayout; diff --git a/video-gen-admin/src/pages/AdminReplicationProjectDetail.tsx b/video-gen-admin/src/pages/AdminReplicationProjectDetail.tsx new file mode 100644 index 00000000..9627d07d --- /dev/null +++ b/video-gen-admin/src/pages/AdminReplicationProjectDetail.tsx @@ -0,0 +1,384 @@ +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { + Alert, + Button, + Card, + Collapse, + Descriptions, + Empty, + Space, + Spin, + Steps, + Table, + Tag, + Tooltip, + Typography, + message, +} from 'antd'; +import { + ArrowLeftOutlined, + FileImageOutlined, + PlayCircleOutlined, + VideoCameraOutlined, +} from '@ant-design/icons'; +import { useNavigate, useParams } from 'react-router-dom'; +import { getAdminHotOpeningTaskDetail, getAdminShotProjectDetail } from '../api'; +import type { ReplicationProjectDetailOut, ReplicationStepOut } from '../types'; +import { formatDate } from '../utils/formatDate'; +import JsonCollapse, { JsonBlock } from './adminReplication/components/JsonCollapse'; +import MediaPreview from './adminReplication/components/MediaPreview'; +import StatusTag, { getModuleLabel, getStatusLabel, getStepCodeLabel } from './adminReplication/components/StatusTag'; +import VideoPromptSchemaViewer from './adminReplication/components/VideoPromptSchemaViewer'; + +type ReplicationModuleType = 'hot_opening_replicate' | 'shot_replicate'; + +interface AdminReplicationProjectDetailProps { + moduleType?: ReplicationModuleType; +} + +const STEP_ORDER = [ + 'material_input', + 'image_prompt_optimize', + 'image_generate', + 'video_prompt_optimize', + 'video_generate', +]; + +const STEP_DESCRIPTIONS: Record = { + material_input: '参考素材、项目名称和核心内容点', + image_prompt_optimize: '图片 AI 提词优化结果', + image_generate: '图片引擎、生成参数和结果图', + video_prompt_optimize: '视频 JSON schema、动作流程和最终提词', + video_generate: '视频引擎、生成参数、封面和结果视频', +}; + +const safeDate = (value?: string | null): string => (value ? formatDate(value) : '-'); + +const shortId = (value?: string | null): string => { + if (!value) return '-'; + return value.length > 18 ? `${value.slice(0, 10)}...${value.slice(-4)}` : value; +}; + +const EmptyText: React.FC<{ text?: string }> = ({ text = '-' }) => ( + {text} +); + +const StepRawJson: React.FC<{ step?: ReplicationStepOut | null }> = ({ step }) => { + if (!step) return null; + return ; +}; + +const StepHeader: React.FC<{ index: number; stepCode: string; step?: ReplicationStepOut | null; current?: boolean }> = ({ index, stepCode, step, current }) => ( + + {`第${index}步:${getStepCodeLabel(stepCode)}`} + + {current ? 当前步骤 : null} + {STEP_DESCRIPTIONS[stepCode] || stepCode} + {step?.updatedAt ? 更新时间:{safeDate(step.updatedAt)} : null} + {step?.chatTaskId ? Chat:{shortId(step.chatTaskId)} : null} + +); + +const buildDefaultActiveKeys = (detail: ReplicationProjectDetailOut | null, stepsByCode: Record): string[] => { + if (!detail) return []; + const keys = new Set(); + keys.add('material_input'); + if (detail.currentStepCode) keys.add(detail.currentStepCode); + Object.values(stepsByCode).forEach(step => { + if (step.status === 'failed' || step.errorMessage) keys.add(step.stepCode); + }); + if (detail.errorMessage) keys.add(detail.currentStepCode || 'material_input'); + return Array.from(keys); +}; + +const renderErrorAlert = (messageText?: string | null, title = '错误信息') => { + if (!messageText) return null; + return ; +}; + +const renderPromptText = (value?: string | null, empty = '暂无提词') => { + if (!value) return ; + return {value}; +}; + +const AdminReplicationProjectDetail: React.FC = ({ moduleType = 'shot_replicate' }) => { + const { projectId } = useParams<{ projectId: string }>(); + const navigate = useNavigate(); + const [detail, setDetail] = useState(null); + const [loading, setLoading] = useState(false); + + const load = useCallback(async () => { + if (!projectId) return; + setLoading(true); + try { + const res = moduleType === 'hot_opening_replicate' + ? await getAdminHotOpeningTaskDetail(projectId) + : await getAdminShotProjectDetail(projectId); + setDetail(res); + } catch (e: any) { + message.error(e?.message || '加载复刻项目详情失败'); + } finally { + setLoading(false); + } + }, [moduleType, projectId]); + + useEffect(() => { + load(); + }, [load]); + + const stepsByCode = useMemo(() => { + const map: Record = {}; + (detail?.steps || []).forEach(step => { map[step.stepCode] = step; }); + return map; + }, [detail]); + + const moduleValue = detail?.module || moduleType; + const moduleName = getModuleLabel(moduleValue); + + const stepItems = useMemo(() => STEP_ORDER.map(code => { + const step = stepsByCode[code]; + let status: 'wait' | 'process' | 'finish' | 'error' = 'wait'; + if (step?.status === 'completed') status = 'finish'; + else if (step?.status === 'processing') status = 'process'; + else if (step?.status === 'failed') status = 'error'; + return { + title: getStepCodeLabel(code), + description: step ? : '未创建', + status, + }; + }), [stepsByCode]); + + const defaultActiveKeys = useMemo(() => buildDefaultActiveKeys(detail, stepsByCode), [detail, stepsByCode]); + + if (loading && !detail) { + return
; + } + + if (!detail) { + return ( + + + + ); + } + + const materialStep = stepsByCode.material_input; + const imagePromptStep = stepsByCode.image_prompt_optimize; + const imageGenerateStep = stepsByCode.image_generate; + const videoPromptStep = stepsByCode.video_prompt_optimize; + const videoGenerateStep = stepsByCode.video_generate; + + const imageResultUrl = detail.imageGeneration?.resultImageUrl || detail.finalImageUrl; + const videoCoverUrl = detail.videoGeneration?.resultVideoCoverUrl || detail.finalVideoCoverUrl; + const videoResultUrl = detail.videoGeneration?.resultVideoUrl || detail.finalVideoUrl; + + const collapseItems = [ + { + key: 'material_input', + label: , + children: ( + + + + {detail.material?.materialStepId || '-'} + {detail.material?.sourceProjectName || '-'} + {detail.material?.targetProjectName || '-'} + {detail.material?.coreContentPoint || '-'} + +
+ 素材视频}> + + + 素材图片}> + + +
+ {renderErrorAlert(materialStep?.errorMessage)} + +
+ ), + }, + { + key: 'image_prompt_optimize', + label: , + children: ( + + + {detail.imageGeneration?.promptStepId || '-'} + + {renderPromptText(detail.imageGeneration?.prompt, '暂无图片提示词')} + + {renderErrorAlert(imagePromptStep?.errorMessage || detail.imageGeneration?.errorMessage)} + + + ), + }, + { + key: 'image_generate', + label: , + children: ( + + + {detail.imageGeneration?.generateStepId || '-'} + {detail.imageGeneration?.chatTaskId || '-'} + + {detail.imageGeneration?.engineId || '-'} + {detail.imageGeneration?.engineName || '-'} + + + {renderErrorAlert(detail.imageGeneration?.errorMessage || imageGenerateStep?.errorMessage)} + 图片结果}> + + + + + ), + }, + { + key: 'video_prompt_optimize', + label: , + children: ( + + + {detail.videoGeneration?.promptStepId || '-'} + + + + {renderErrorAlert(videoPromptStep?.errorMessage || detail.videoGeneration?.errorMessage)} + + + + ), + }, + { + key: 'video_generate', + label: , + children: ( + + + {detail.videoGeneration?.generateStepId || '-'} + {detail.videoGeneration?.chatTaskId || '-'} + + {detail.videoGeneration?.engineId || '-'} + {detail.videoGeneration?.engineName || '-'} + + + {renderErrorAlert(detail.videoGeneration?.errorMessage || videoGenerateStep?.errorMessage)} +
+ 视频封面}> + + + 最终视频}> + + +
+ +
+ ), + }, + ]; + + return ( +
+ + + + + {moduleName}项目详情 + + {detail.module && detail.module !== moduleType ? 接口模块:{getModuleLabel(detail.module)} : null} + + + + + + + {detail.id} + + {detail.userId || '-'} + {detail.userName || '-'} + {detail.title || '-'} + {getStepCodeLabel(detail.currentStepCode)} + + {safeDate(detail.createdAt)} + {safeDate(detail.updatedAt)} + {safeDate(detail.completedAt)} + {detail.errorMessage ? : null} + + + + + + + + +
+ + + + + + + + + +
+
+ + + + {getStepCodeLabel(v)} }, + { title: '状态', dataIndex: 'status', width: 120, render: (v: string) => }, + { title: '版本', dataIndex: 'version', width: 70 }, + { title: '当前有效', dataIndex: 'isCurrent', width: 90, render: (v: boolean) => v ? : }, + { title: 'Chat任务', dataIndex: 'chatTaskId', width: 160, render: (v: string) => {shortId(v)} }, + { title: '创建时间', dataIndex: 'createdAt', width: 170, render: safeDate }, + { title: '完成时间', dataIndex: 'completedAt', width: 170, render: safeDate }, + { title: '错误', dataIndex: 'errorMessage', ellipsis: true, render: (v: string) => v || '-' }, + ]} + /> + ), + }, + { + key: 'raw-detail', + label: '完整详情原始 JSON', + children: , + }, + ]} + /> +
+
+ ); +}; + +export default AdminReplicationProjectDetail; diff --git a/video-gen-admin/src/pages/AdminShotReplications.tsx b/video-gen-admin/src/pages/AdminShotReplications.tsx new file mode 100644 index 00000000..74c8e2e6 --- /dev/null +++ b/video-gen-admin/src/pages/AdminShotReplications.tsx @@ -0,0 +1,220 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import { Button, Card, DatePicker, Input, Progress, Select, Space, Table, Tag, Tooltip, Typography, message } from 'antd'; +import { EyeOutlined, ReloadOutlined, SearchOutlined } from '@ant-design/icons'; +import { useNavigate } from 'react-router-dom'; +import { getAdminShotTaskSets } from '../api'; +import type { ShotTaskSetOut } from '../types'; +import { formatDate } from '../utils/formatDate'; + +const PAGE_SIZE = 20; + +const TASK_STATUS_OPTIONS = [ + { value: 'pending_analysis', label: '等待分析' }, + { value: 'analyzing', label: '分析中' }, + { value: 'analysis_completed', label: '分析完成' }, + { value: 'analysis_failed', label: '分析失败' }, + { value: 'splitting', label: '拆镜中' }, + { value: 'split_completed', label: '拆镜完成' }, + { value: 'partial_failed', label: '部分失败' }, + { value: 'failed', label: '失败' }, +]; + +const ANALYSIS_STATUS_OPTIONS = [ + { value: 'pending', label: '待分析' }, + { value: 'processing', label: '分析中' }, + { value: 'completed', label: '分析完成' }, + { value: 'failed', label: '分析失败' }, +]; + +const SPLIT_STATUS_OPTIONS = [ + { value: 'none', label: '未拆镜' }, + { value: 'pending', label: '待拆镜' }, + { value: 'processing', label: '拆镜中' }, + { value: 'completed', label: '拆镜完成' }, + { value: 'failed', label: '拆镜失败' }, + { value: 'retry_waiting', label: '等待重试' }, +]; + +const STATUS_MAP: Record = { + pending_analysis: { color: 'default', text: '等待分析' }, + analyzing: { color: 'processing', text: '分析中' }, + analysis_completed: { color: 'success', text: '分析完成' }, + analysis_failed: { color: 'error', text: '分析失败' }, + splitting: { color: 'warning', text: '拆镜中' }, + split_completed: { color: 'success', text: '拆镜完成' }, + partial_failed: { color: 'orange', text: '部分失败' }, + failed: { color: 'error', text: '失败' }, + none: { color: 'default', text: '未拆镜' }, + pending: { color: 'default', text: '待处理' }, + processing: { color: 'warning', text: '处理中' }, + completed: { color: 'success', text: '完成' }, + retry_waiting: { color: 'orange', text: '等待重试' }, +}; + +const safeDate = (value?: string | null): string => (value ? formatDate(value) : '-'); +const shortId = (value?: string | null): string => (!value ? '-' : value.length > 16 ? `${value.slice(0, 10)}...` : value); + +const StatusTag: React.FC<{ status?: string | null }> = ({ status }) => { + if (!status) return -; + const meta = STATUS_MAP[status] || { color: 'blue', text: status }; + return {meta.text}; +}; + +const AdminShotReplications: React.FC = () => { + const navigate = useNavigate(); + const [items, setItems] = useState([]); + const [total, setTotal] = useState(0); + const [loading, setLoading] = useState(false); + const [page, setPage] = useState(1); + + const [status, setStatus] = useState(''); + const [analysisStatus, setAnalysisStatus] = useState(''); + const [splitStatus, setSplitStatus] = useState(''); + const [inputKeyword, setInputKeyword] = useState(''); + const [inputUserId, setInputUserId] = useState(''); + const [inputUserName, setInputUserName] = useState(''); + const [createdRange, setCreatedRange] = useState(null); + + const [queryKeyword, setQueryKeyword] = useState(''); + const [queryUserId, setQueryUserId] = useState(''); + const [queryUserName, setQueryUserName] = useState(''); + const [queryCreatedRange, setQueryCreatedRange] = useState(null); + const [reloadKey, setReloadKey] = useState(0); + + const load = useCallback(async () => { + setLoading(true); + try { + const res = await getAdminShotTaskSets({ + status: status || undefined, + analysisStatus: analysisStatus || undefined, + splitStatus: splitStatus || undefined, + keyword: queryKeyword || undefined, + userId: queryUserId || undefined, + userName: queryUserName || undefined, + createdStart: queryCreatedRange?.[0]?.toISOString?.(), + createdEnd: queryCreatedRange?.[1]?.toISOString?.(), + page, + pageSize: PAGE_SIZE, + }); + setItems(res.items || []); + setTotal(res.total || 0); + } catch (e: any) { + message.error(e?.message || '加载拆镜复刻任务失败'); + } finally { + setLoading(false); + } + }, [analysisStatus, page, queryCreatedRange, queryKeyword, queryUserId, queryUserName, splitStatus, status]); + + useEffect(() => { + load(); + }, [load, reloadKey]); + + const doSearch = () => { + setQueryKeyword(inputKeyword.trim()); + setQueryUserId(inputUserId.trim()); + setQueryUserName(inputUserName.trim()); + setQueryCreatedRange(createdRange); + setPage(1); + }; + + const resetSearch = () => { + setStatus(''); + setAnalysisStatus(''); + setSplitStatus(''); + setInputKeyword(''); + setInputUserId(''); + setInputUserName(''); + setCreatedRange(null); + setQueryKeyword(''); + setQueryUserId(''); + setQueryUserName(''); + setQueryCreatedRange(null); + setPage(1); + setReloadKey(v => v + 1); + }; + + return ( +
+ + + +
+ 拆镜复刻 + 只读排查页面:查看拆镜总任务、AI 分析结果、切片列表和关联复刻项目。 +
+ +
+ + + { setAnalysisStatus(v || ''); setPage(1); }} options={ANALYSIS_STATUS_OPTIONS} /> + } placeholder="关键词:标题/内容/分类/受众" style={{ width: 260 }} value={inputKeyword} onChange={e => setInputKeyword(e.target.value)} onPressEnter={doSearch} /> + setInputUserId(e.target.value)} onPressEnter={doSearch} /> + setInputUserName(e.target.value)} onPressEnter={doSearch} /> + + + + + +
`共 ${value} 条`, onChange: setPage }} + scroll={{ x: 1500 }} + columns={[ + { title: '任务集ID', dataIndex: 'id', width: 150, render: (v: string) => {shortId(v)} }, + { + title: '用户', + width: 180, + render: (_, record) => ( + + {record.userName || '-'} + {shortId(record.userId)} + + ), + }, + { + title: '任务信息', + width: 300, + render: (_, record) => ( + + {record.title || '-'} + 分类:{record.originalVideoCategory || '-'} + 受众:{record.originalVideoAudience || '-'} + + ), + }, + { title: '总状态', dataIndex: 'status', width: 120, render: (v: string) => }, + { title: '分析状态', dataIndex: 'analysisStatus', width: 110, render: (v: string) => }, + { title: '拆镜状态', dataIndex: 'splitStatus', width: 110, render: (v: string) => }, + { + title: '切片进度', + width: 180, + render: (_, record) => { + const totalSegments = record.segmentCount || 0; + const done = record.completedSegmentCount || 0; + const percent = totalSegments ? Math.round((done / totalSegments) * 100) : 0; + return `${done}/${totalSegments}`} />; + }, + }, + { title: '失败片段', dataIndex: 'failedSegmentCount', width: 90, render: (v: number) => v ? {v} : 0 }, + { title: '视频时长', dataIndex: 'videoDurationSeconds', width: 100, render: (v: number) => `${Number(v || 0).toFixed(1)}s` }, + { title: '创建时间', dataIndex: 'createdAt', width: 170, render: safeDate }, + { title: '更新时间', dataIndex: 'updatedAt', width: 170, render: safeDate }, + { + title: '操作', + fixed: 'right', + width: 120, + render: (_, record) => , + }, + ]} + /> + + + + ); +}; + +export default AdminShotReplications; diff --git a/video-gen-admin/src/pages/AdminShotTaskSetDetail.tsx b/video-gen-admin/src/pages/AdminShotTaskSetDetail.tsx new file mode 100644 index 00000000..8abf82d8 --- /dev/null +++ b/video-gen-admin/src/pages/AdminShotTaskSetDetail.tsx @@ -0,0 +1,340 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import { + Alert, + Button, + Card, + Collapse, + Descriptions, + Drawer, + Empty, + Input, + Select, + Space, + Spin, + Table, + Tag, + Tooltip, + Typography, + message, +} from 'antd'; +import { ArrowLeftOutlined, EyeOutlined, PlayCircleOutlined, ReloadOutlined, SearchOutlined } from '@ant-design/icons'; +import { useNavigate, useParams } from 'react-router-dom'; +import { getAdminShotSegmentDetail, getAdminShotSegments, getAdminShotTaskSetDetail } from '../api'; +import type { ShotAiSuggestionOut, ShotSegmentDetailOut, ShotSegmentOut, ShotTaskSetDetailOut } from '../types'; +import { formatDate } from '../utils/formatDate'; +import { getStepCodeLabel } from './adminReplication/components/StatusTag'; + +const RAW_API_BASE = import.meta.env.VITE_API_BASE || 'http://localhost:8000'; +const RESOURCE_BASE = RAW_API_BASE.replace(/\/api\/?$/i, '').replace(/\/$/, ''); +const PAGE_SIZE = 20; + +const SOURCE_OPTIONS = [ + { value: 'ai_suggestion', label: 'AI 建议' }, + { value: 'custom', label: '自定义' }, +]; +const SPLIT_STATUS_OPTIONS = [ + { value: 'none', label: '未拆镜' }, + { value: 'pending', label: '待拆镜' }, + { value: 'processing', label: '拆镜中' }, + { value: 'completed', label: '拆镜完成' }, + { value: 'failed', label: '拆镜失败' }, + { value: 'retry_waiting', label: '等待重试' }, +]; +const ANALYSIS_STATUS_OPTIONS = [ + { value: 'not_required', label: '无需分析' }, + { value: 'pending', label: '待分析' }, + { value: 'processing', label: '分析中' }, + { value: 'completed', label: '分析完成' }, + { value: 'failed', label: '分析失败' }, +]; +const REPLICATE_STATUS_OPTIONS = [ + { value: 'not_started', label: '未复刻' }, + { value: 'project_created', label: '已创建项目' }, + { value: 'processing', label: '复刻中' }, + { value: 'completed', label: '复刻完成' }, + { value: 'failed', label: '复刻失败' }, +]; + +const STATUS_MAP: Record = { + pending_analysis: { color: 'default', text: '等待分析' }, + analyzing: { color: 'processing', text: '分析中' }, + analysis_completed: { color: 'success', text: '分析完成' }, + analysis_failed: { color: 'error', text: '分析失败' }, + splitting: { color: 'warning', text: '拆镜中' }, + split_completed: { color: 'success', text: '拆镜完成' }, + partial_failed: { color: 'orange', text: '部分失败' }, + failed: { color: 'error', text: '失败' }, + none: { color: 'default', text: '未拆镜' }, + pending: { color: 'default', text: '待处理' }, + processing: { color: 'warning', text: '处理中' }, + completed: { color: 'success', text: '完成' }, + retry_waiting: { color: 'orange', text: '等待重试' }, + not_required: { color: 'default', text: '无需分析' }, + not_started: { color: 'default', text: '未复刻' }, + project_created: { color: 'processing', text: '已创建项目' }, +}; + +const apiUrl = (url?: string | null): string => { + if (!url) return ''; + const value = String(url).trim(); + if (!value) return ''; + if (/^(https?:)?\/\//i.test(value) || /^(blob|data):/i.test(value)) return value; + return `${RESOURCE_BASE}${value.startsWith('/') ? value : `/${value}`}`; +}; + +const safeDate = (value?: string | null): string => (value ? formatDate(value) : '-'); +const shortId = (value?: string | null): string => (!value ? '-' : value.length > 16 ? `${value.slice(0, 10)}...` : value); + +const StatusTag: React.FC<{ status?: string | null }> = ({ status }) => { + if (!status) return -; + const meta = STATUS_MAP[status] || { color: 'blue', text: status }; + return {meta.text}; +}; + +const JsonBlock: React.FC<{ value: unknown; maxHeight?: number }> = ({ value, maxHeight = 420 }) => ( +
+    {JSON.stringify(value ?? {}, null, 2)}
+  
+); + +const VideoPreview: React.FC<{ url?: string | null; height?: number }> = ({ url, height = 280 }) => { + if (!url) return ; + return
`${Number(v || 0).toFixed(2)}s` }, + { title: '结束', dataIndex: 'endSecond', width: 80, render: (v: number) => `${Number(v || 0).toFixed(2)}s` }, + { title: '内容', dataIndex: 'content', ellipsis: true }, + { title: '分类', dataIndex: 'category', width: 140 }, + { title: '受众', dataIndex: 'audience', ellipsis: true }, + ]} + /> +); + +const AdminShotTaskSetDetail: React.FC = () => { + const { taskSetId } = useParams<{ taskSetId: string }>(); + const navigate = useNavigate(); + + const [detail, setDetail] = useState(null); + const [segments, setSegments] = useState([]); + const [total, setTotal] = useState(0); + const [page, setPage] = useState(1); + const [loading, setLoading] = useState(false); + const [segmentLoading, setSegmentLoading] = useState(false); + const [reloadKey, setReloadKey] = useState(0); + + const [sourceMode, setSourceMode] = useState(''); + const [splitStatus, setSplitStatus] = useState(''); + const [analysisStatus, setAnalysisStatus] = useState(''); + const [replicateStatus, setReplicateStatus] = useState(''); + const [drawerOpen, setDrawerOpen] = useState(false); + const [segmentDetail, setSegmentDetail] = useState(null); + + const loadDetail = useCallback(async () => { + if (!taskSetId) return; + setLoading(true); + try { + const res = await getAdminShotTaskSetDetail(taskSetId); + setDetail(res); + } catch (e: any) { + message.error(e?.message || '加载拆镜任务详情失败'); + } finally { + setLoading(false); + } + }, [taskSetId]); + + const loadSegments = useCallback(async () => { + if (!taskSetId) return; + setSegmentLoading(true); + try { + const res = await getAdminShotSegments(taskSetId, { + sourceMode: sourceMode || undefined, + splitStatus: splitStatus || undefined, + analysisStatus: analysisStatus || undefined, + replicateStatus: replicateStatus || undefined, + page, + pageSize: PAGE_SIZE, + }); + setSegments(res.items || []); + setTotal(res.total || 0); + } catch (e: any) { + message.error(e?.message || '加载拆镜片段失败'); + } finally { + setSegmentLoading(false); + } + }, [analysisStatus, page, replicateStatus, sourceMode, splitStatus, taskSetId]); + + useEffect(() => { loadDetail(); }, [loadDetail, reloadKey]); + useEffect(() => { loadSegments(); }, [loadSegments, reloadKey]); + + const openSegmentDetail = async (segmentId: string) => { + setDrawerOpen(true); + setSegmentDetail(null); + try { + const res = await getAdminShotSegmentDetail(segmentId); + setSegmentDetail(res); + } catch (e: any) { + message.error(e?.message || '加载片段详情失败'); + } + }; + + const resetFilters = () => { + setSourceMode(''); + setSplitStatus(''); + setAnalysisStatus(''); + setReplicateStatus(''); + setPage(1); + setReloadKey(v => v + 1); + }; + + if (loading && !detail) { + return
; + } + + if (!detail) { + return ; + } + + return ( +
+ + + + + 拆镜任务详情 + + + + + + + + {detail.id} + {detail.userId || '-'} + {detail.userName || '-'} + {detail.title || '-'} + {Number(detail.videoDurationSeconds || 0).toFixed(2)}s + + + + {detail.completedSegmentCount}/{detail.segmentCount},失败 {detail.failedSegmentCount} + {detail.originalVideoCategory || '-'} + {safeDate(detail.createdAt)} + {safeDate(detail.updatedAt)} + {detail.originalVideoContent || '-'} + {detail.originalVideoAudience || '-'} + {detail.analysisErrorMessage ? : null} + {detail.splitErrorMessage ? : null} + + + + 原视频预览}> + + + + + {detail.aiSuggestions?.length ? : } + }]} + /> + + + + + { setSplitStatus(v || ''); setPage(1); }} /> + { setReplicateStatus(v || ''); setPage(1); }} /> + + + + +
`共 ${value} 条`, onChange: setPage }} + scroll={{ x: 1550 }} + columns={[ + { title: '片段ID', dataIndex: 'id', width: 150, render: (v: string) => {shortId(v)} }, + { title: '序号', dataIndex: 'segmentIndex', width: 70 }, + { title: '来源', dataIndex: 'sourceMode', width: 100, render: (v: string) => v === 'ai_suggestion' ? AI建议 : 自定义 }, + { title: '时间节点', dataIndex: 'timeNode', width: 130 }, + { title: '时长', dataIndex: 'durationSeconds', width: 90, render: (v: number) => `${Number(v || 0).toFixed(2)}s` }, + { title: '切割', dataIndex: 'splitStatus', width: 100, render: (v: string) => }, + { title: '分析', dataIndex: 'analysisStatus', width: 100, render: (v: string) => }, + { title: '复刻', dataIndex: 'replicateStatus', width: 110, render: (v: string) => }, + { title: '片段内容', dataIndex: 'segmentContent', width: 260, ellipsis: true, render: (v: string) => v || '-' }, + { title: '分类', dataIndex: 'segmentCategory', width: 120, render: (v: string) => v || '-' }, + { + title: '关联项目', + width: 220, + render: (_, record) => record.moduleProjectId ? ( + + + {record.moduleProjectTitle || getStepCodeLabel(record.moduleProjectCurrentStepCode)} + + + ) : 未创建, + }, + { title: '错误', dataIndex: 'splitLastError', width: 220, ellipsis: true, render: (v: string, record) => v || record.analysisErrorMessage || '-' }, + { title: '创建时间', dataIndex: 'createdAt', width: 170, render: safeDate }, + { + title: '操作', + fixed: 'right', + width: 100, + render: (_, record) => , + }, + ]} + /> + + + + setDrawerOpen(false)} destroyOnClose> + {!segmentDetail ? : ( + + + {segmentDetail.id} + {segmentDetail.timeNode} + {Number(segmentDetail.durationSeconds || 0).toFixed(2)}s + + + + {segmentDetail.moduleProjectId ? : '-'} + {segmentDetail.segmentContent || '-'} + {segmentDetail.segmentCategory || '-'} + {segmentDetail.segmentAudience || '-'} + + + + + {segmentDetail.splitLastError ? : null} + {segmentDetail.analysisErrorMessage ? : null} + }, + { key: 'suggestion', label: 'AI 建议原始 JSON', children: }, + ]} + /> + + )} + + + ); +}; + +export default AdminShotTaskSetDetail; diff --git a/video-gen-admin/src/pages/adminReplication/components/JsonCollapse.tsx b/video-gen-admin/src/pages/adminReplication/components/JsonCollapse.tsx new file mode 100644 index 00000000..18f139fa --- /dev/null +++ b/video-gen-admin/src/pages/adminReplication/components/JsonCollapse.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import { Collapse, Empty } from 'antd'; + +interface JsonBlockProps { + value: unknown; + maxHeight?: number; +} + +export const JsonBlock: React.FC = ({ value, maxHeight = 420 }) => { + if (value === undefined || value === null || value === '') { + return ; + } + + return ( +
+      {JSON.stringify(value, null, 2)}
+    
+ ); +}; + +interface JsonCollapseProps { + input?: unknown; + output?: unknown; + raw?: unknown; + inputLabel?: string; + outputLabel?: string; + rawLabel?: string; +} + +const JsonCollapse: React.FC = ({ + input, + output, + raw, + inputLabel = '查看 input_json', + outputLabel = '查看 output_json', + rawLabel = '查看原始 JSON', +}) => { + const items = []; + if (input !== undefined) items.push({ key: 'input', label: inputLabel, children: }); + if (output !== undefined) items.push({ key: 'output', label: outputLabel, children: }); + if (raw !== undefined) items.push({ key: 'raw', label: rawLabel, children: }); + + if (!items.length) return null; + return ; +}; + +export default JsonCollapse; diff --git a/video-gen-admin/src/pages/adminReplication/components/MediaPreview.tsx b/video-gen-admin/src/pages/adminReplication/components/MediaPreview.tsx new file mode 100644 index 00000000..8a9b9b3e --- /dev/null +++ b/video-gen-admin/src/pages/adminReplication/components/MediaPreview.tsx @@ -0,0 +1,126 @@ +import React, { useEffect, useMemo, useState } from 'react'; +import { Alert, Button, Empty, Image, Space, Typography, message } from 'antd'; +import { CopyOutlined, LinkOutlined } from '@ant-design/icons'; + +const RAW_API_BASE = import.meta.env.VITE_API_BASE || 'http://localhost:8000'; +const RESOURCE_BASE = RAW_API_BASE.replace(/\/api\/?$/i, '').replace(/\/$/, ''); + +export function resolveResourceUrl(url?: string | null): string { + if (!url) return ''; + const value = String(url).trim(); + if (!value) return ''; + if (/^(https?:)?\/\//i.test(value) || /^(blob|data):/i.test(value)) return value; + return `${RESOURCE_BASE}${value.startsWith('/') ? value : `/${value}`}`; +} + +interface MediaPreviewProps { + url?: string | null; + type: 'image' | 'video'; + height?: number; + emptyDescription?: string; + errorDescription?: string; +} + +const MediaPreview: React.FC = ({ + url, + type, + height = 260, + emptyDescription = '暂无资源', + errorDescription = '资源加载失败,可能文件不存在、签名过期或访问权限受限。', +}) => { + const resolvedUrl = useMemo(() => resolveResourceUrl(url), [url]); + const [loadFailed, setLoadFailed] = useState(false); + + useEffect(() => { + setLoadFailed(false); + }, [resolvedUrl]); + + const copyUrl = async () => { + if (!resolvedUrl) return; + try { + await navigator.clipboard.writeText(resolvedUrl); + message.success('资源地址已复制'); + } catch { + message.error('复制失败,请手动复制'); + } + }; + + const tools = resolvedUrl ? ( + + + + + {resolvedUrl} + + + ) : null; + + if (!resolvedUrl) { + return ( +
+
+ +
+
+ ); + } + + return ( +
+ {loadFailed ? ( + + ) : null} + + {type === 'image' ? ( + setLoadFailed(true)} + style={{ + width: '100%', + maxHeight: height, + objectFit: 'contain', + borderRadius: 12, + background: '#f8fafc', + border: '1px solid #f1f5f9', + }} + fallback="" + preview={!loadFailed} + /> + ) : ( +
+ ); +}; + +export default MediaPreview; diff --git a/video-gen-admin/src/pages/adminReplication/components/StatusTag.tsx b/video-gen-admin/src/pages/adminReplication/components/StatusTag.tsx new file mode 100644 index 00000000..207347e0 --- /dev/null +++ b/video-gen-admin/src/pages/adminReplication/components/StatusTag.tsx @@ -0,0 +1,105 @@ +import React from 'react'; +import { Tag, Tooltip } from 'antd'; + +interface LabelMeta { + text: string; + color?: string; +} + +const STATUS_LABELS: Record = { + // 通用任务状态 + pending: { text: '待处理', color: 'default' }, + waiting_user: { text: '等待用户操作', color: 'processing' }, + processing: { text: '处理中', color: 'warning' }, + completed: { text: '已完成', color: 'success' }, + failed: { text: '失败', color: 'error' }, + cancelled: { text: '已取消', color: 'default' }, + canceled: { text: '已取消', color: 'default' }, + timeout: { text: '已超时', color: 'error' }, + queued: { text: '已入队', color: 'processing' }, + preparing: { text: '准备中', color: 'processing' }, + + // 生成任务 pipeline / download stage + creating_provider_task: { text: '创建远端任务', color: 'processing' }, + waiting_remote: { text: '等待远端结果', color: 'processing' }, + polling: { text: '轮询远端结果', color: 'processing' }, + result_ready: { text: '结果已就绪', color: 'success' }, + downloading: { text: '下载中', color: 'processing' }, + done: { text: '已完成', color: 'success' }, + download_failed: { text: '下载失败', color: 'error' }, + retry_waiting: { text: '等待重试', color: 'orange' }, + + // 拆镜总任务状态 + pending_analysis: { text: '等待分析', color: 'default' }, + analyzing: { text: '分析中', color: 'processing' }, + analysis_completed: { text: '分析完成', color: 'success' }, + analysis_failed: { text: '分析失败', color: 'error' }, + splitting: { text: '拆镜中', color: 'warning' }, + split_completed: { text: '拆镜完成', color: 'success' }, + partial_failed: { text: '部分失败', color: 'orange' }, + + // 拆镜片段状态 + none: { text: '未拆镜', color: 'default' }, + not_required: { text: '无需处理', color: 'default' }, + not_started: { text: '未开始', color: 'default' }, + project_created: { text: '已创建项目', color: 'processing' }, + + // 布尔/兜底类 + true: { text: '是', color: 'success' }, + false: { text: '否', color: 'default' }, +}; + +const STEP_LABELS: Record = { + material_input: '素材输入', + image_prompt_optimize: '图片 AI 提词', + image_generate: '图片生成', + video_prompt_optimize: '视频 AI 提词', + video_generate: '视频生成', +}; + +const MODULE_LABELS: Record = { + hot_opening_replicate: '爆款开头复刻', + shot_replicate: '拆镜复刻', +}; + +const SOURCE_MODE_LABELS: Record = { + ai_suggestion: { text: 'AI 建议', color: 'purple' }, + custom: { text: '自定义', color: 'cyan' }, + original: { text: '原视频', color: 'blue' }, +}; + +export function getModuleLabel(value?: string | null): string { + if (!value) return '-'; + return MODULE_LABELS[value] || value; +} + +export function getStepCodeLabel(value?: string | null): string { + if (!value) return '-'; + return STEP_LABELS[value] || value; +} + +export function getStatusLabel(value?: string | null): string { + if (!value) return '-'; + return STATUS_LABELS[value]?.text || STEP_LABELS[value] || MODULE_LABELS[value] || SOURCE_MODE_LABELS[value]?.text || value; +} + +export function getStatusColor(value?: string | null): string { + if (!value) return 'default'; + return STATUS_LABELS[value]?.color || SOURCE_MODE_LABELS[value]?.color || 'blue'; +} + +interface StatusTagProps { + status?: string | boolean | null; + tooltipRaw?: boolean; +} + +const StatusTag: React.FC = ({ status, tooltipRaw = true }) => { + if (status === undefined || status === null || status === '') return -; + const raw = String(status); + const label = getStatusLabel(raw); + const tag = {label}; + if (!tooltipRaw || label === raw) return tag; + return {tag}; +}; + +export default StatusTag; diff --git a/video-gen-admin/src/pages/adminReplication/components/VideoPromptSchemaViewer.tsx b/video-gen-admin/src/pages/adminReplication/components/VideoPromptSchemaViewer.tsx new file mode 100644 index 00000000..dc70e791 --- /dev/null +++ b/video-gen-admin/src/pages/adminReplication/components/VideoPromptSchemaViewer.tsx @@ -0,0 +1,314 @@ +import React from 'react'; +import { Card, Collapse, Descriptions, Empty, Space, Table, Typography } from 'antd'; +import type { ColumnsType } from 'antd/es/table'; +import { JsonBlock } from './JsonCollapse'; + +const FIELD_LABELS: Record = { + schema_version: 'Schema 版本', + generation_type: '生成类型', + business_type: '业务类型', + usage: '用途', + product_type: '产品类型', + target_audience: '目标受众', + style: '风格', + aspect_ratio: '画面比例', + resolution: '分辨率', + duration: '时长', + fps: '帧率', + final_prompt: '最终提示词', + prompt: '提示词', + description: '说明', + content: '内容', + time: '时间', + time_range: '时间段', + start_time: '开始时间', + end_time: '结束时间', + stage: '阶段', + scene: '场景', + action: '动作', + camera: '镜头', + shot: '镜头', + lens: '镜头', + subtitle: '字幕', + voiceover: '口播', + audio: '音频', + rhythm: '节奏', + notes: '备注', +}; + +const SECTION_LABELS: Record = { + basic: '基础信息', + basic_info: '基础信息', + material: '素材理解', + material_understanding: '素材理解', + business: '业务属性', + business_info: '业务属性', + visual: '画面与风格', + visual_style: '画面与风格', + time_plan: '时间规划', + timeline: '时间规划', + scene_timeline: '场景时间线', + action_flow: '动作流程', + motion_flow: '动作流程', + character_action_flow: '角色动作流程', + camera_flow: '镜头流程', + shot_flow: '镜头流程', + lens_flow: '镜头流程', + subtitle: '字幕', + subtitles: '字幕', + voiceover: '口播', + audio: '音频', + rhythm: '节奏', + compliance: '合规控制', + final_prompt: '最终提示词', +}; + +const isRecord = (value: unknown): value is Record => !!value && typeof value === 'object' && !Array.isArray(value); + +const labelOf = (key: string): string => SECTION_LABELS[key] || FIELD_LABELS[key] || key; + +const isLongText = (value: unknown): boolean => typeof value === 'string' && value.length > 80; + + +const EMPTY_TEXTS = new Set(['', '无', 'null', 'None', 'none', '未提及', '不适用']); +const PLACEHOLDER_FLOW_TEXTS = new Set([ + '展示主体动作、核心卖点或主要视觉内容', + '展示主要动作、核心卖点或主要视觉内容', + '展示核心卖点或主要视觉内容', + '展示主体动作', + '无', +]); +const ACTION_CONTENT_KEYS = ['动作内容', '动作', '动作说明', '内容', '说明', '主体动作', '动作变化']; +const CAMERA_CONTENT_KEYS = ['镜头内容', '镜头', '镜头说明', '运镜', '运镜说明', '内容', '说明']; + +const toText = (value: unknown): string => { + if (value === null || value === undefined) return ''; + if (typeof value === 'string') return value.trim(); + if (typeof value === 'number' || typeof value === 'boolean') return String(value); + try { + return JSON.stringify(value); + } catch { + return String(value); + } +}; + +const isEmptyText = (value: unknown): boolean => EMPTY_TEXTS.has(toText(value)); + +const isActionFlowSection = (sectionKey: string): boolean => { + const lower = sectionKey.toLowerCase(); + return lower.includes('action') || lower.includes('motion') || lower.includes('动作'); +}; + +const isCameraFlowSection = (sectionKey: string): boolean => { + const lower = sectionKey.toLowerCase(); + return lower.includes('camera') || lower.includes('shot') || lower.includes('lens') || lower.includes('镜头'); +}; + +const isTimePlanSection = (sectionKey: string): boolean => { + const lower = sectionKey.toLowerCase(); + return lower.includes('time') || lower.includes('timeline') || lower.includes('时间规划') || lower.includes('动态时间规划'); +}; + +const pickFirstContent = (item: Record, keys: string[]): string => { + for (const key of keys) { + if (key in item && !isEmptyText(item[key])) return toText(item[key]); + } + return ''; +}; + +const normalizeFlowContent = (baseContent: string, extras: string[]): string => { + const cleanBase = baseContent.trim(); + const uniqueExtras = extras.filter((item, index) => item && extras.indexOf(item) === index); + if (uniqueExtras.length && (!cleanBase || PLACEHOLDER_FLOW_TEXTS.has(cleanBase))) { + return uniqueExtras.join(';'); + } + const parts = cleanBase && !EMPTY_TEXTS.has(cleanBase) ? [cleanBase] : []; + uniqueExtras.forEach((item) => { + if (item && !parts.includes(item)) parts.push(item); + }); + return parts.join(';') || '-'; +}; + +const normalizeFlowItemForDisplay = ( + item: Record, + contentKey: '动作内容' | '镜头内容', + contentKeys: string[], +): Record => { + const allowed = new Set(['时间段', contentKey, ...contentKeys]); + const extras: string[] = []; + Object.entries(item).forEach(([field, value]) => { + if (allowed.has(field)) return; + const fieldText = toText(field); + const valueText = toText(value); + if (fieldText && !EMPTY_TEXTS.has(fieldText)) extras.push(fieldText); + if (valueText && !EMPTY_TEXTS.has(valueText) && valueText !== fieldText) extras.push(valueText); + }); + return { + 时间段: toText(item['时间段']) || '-', + [contentKey]: normalizeFlowContent(pickFirstContent(item, contentKeys), extras), + }; +}; + +const normalizeRecordForSection = (sectionKey: string, item: Record): Record => { + if (isActionFlowSection(sectionKey)) { + return normalizeFlowItemForDisplay(item, '动作内容', ACTION_CONTENT_KEYS); + } + if (isCameraFlowSection(sectionKey)) { + return normalizeFlowItemForDisplay(item, '镜头内容', CAMERA_CONTENT_KEYS); + } + if (isTimePlanSection(sectionKey)) { + return { + 时间段: toText(item['时间段']) || '-', + 阶段: toText(item['阶段']) || '-', + 说明: toText(item['说明']) || '-', + }; + } + return item; +}; + +const renderValue = (value: unknown): React.ReactNode => { + if (value === null || value === undefined || value === '') return -; + if (typeof value === 'boolean') return value ? '是' : '否'; + if (typeof value === 'number') return value; + if (typeof value === 'string') { + return {value}; + } + return ; +}; + +const getArrayMode = (key: string): 'card' | 'table' => { + const lower = key.toLowerCase(); + if ( + lower.includes('action') || + lower.includes('motion') || + lower.includes('camera') || + lower.includes('shot') || + lower.includes('lens') || + lower.includes('flow') || + lower.includes('动作') || + lower.includes('镜头') + ) { + return 'card'; + } + return 'table'; +}; + +const renderCardArray = (sectionKey: string, items: Record[]): React.ReactNode => ( + + {items.map((item, index) => { + const displayItem = normalizeRecordForSection(sectionKey, item); + return ( + + + {Object.entries(displayItem).map(([field, value]) => ( + + {renderValue(value)} + + ))} + + + ); + })} + +); + +const renderTableArray = (sectionKey: string, items: Record[]): React.ReactNode => { + const displayItems = items.map(item => normalizeRecordForSection(sectionKey, item)); + const fields = Array.from(new Set(displayItems.flatMap(item => Object.keys(item)))); + const columns: ColumnsType> = fields.map(field => ({ + title: labelOf(field), + dataIndex: field, + key: field, + width: isLongText(displayItems.find(item => item[field])?.[field]) ? 280 : 160, + render: (value: unknown) => renderValue(value), + })); + + return ( +
`${sectionKey}-${index}`} + columns={columns} + dataSource={displayItems} + pagination={false} + scroll={{ x: Math.max(900, fields.length * 180) }} + tableLayout="fixed" + /> + ); +}; + +const renderArray = (sectionKey: string, value: unknown[]): React.ReactNode => { + if (!value.length) return ; + if (value.every(isRecord)) { + return getArrayMode(sectionKey) === 'card' + ? renderCardArray(sectionKey, value) + : renderTableArray(sectionKey, value); + } + return ; +}; + +const renderRecord = (value: Record): React.ReactNode => ( + + {Object.entries(value).map(([field, fieldValue]) => ( + + {Array.isArray(fieldValue) + ? renderArray(field, fieldValue) + : isRecord(fieldValue) + ? renderRecord(fieldValue) + : renderValue(fieldValue)} + + ))} + +); + +const renderSection = (key: string, value: unknown): React.ReactNode => { + if (Array.isArray(value)) return renderArray(key, value); + if (isRecord(value)) return renderRecord(value); + return renderValue(value); +}; + +interface VideoPromptSchemaViewerProps { + schema?: Record | null; + finalPrompt?: string | null; +} + +const VideoPromptSchemaViewer: React.FC = ({ schema, finalPrompt }) => { + const hasSchema = !!schema && Object.keys(schema).length > 0; + if (!hasSchema && !finalPrompt) { + return ; + } + + const schemaItems = hasSchema + ? Object.entries(schema || {}).map(([key, value]) => ({ + key, + label: labelOf(key), + children: renderSection(key, value), + })) + : []; + + const defaultKeys = finalPrompt ? ['final_prompt'] : []; + + return ( + + {finalPrompt ? ( + + {finalPrompt} + + ) : null} + + {schemaItems.length ? ( + + ) : null} + + ); +}; + +export default VideoPromptSchemaViewer; diff --git a/video-gen-admin/src/types/index.ts b/video-gen-admin/src/types/index.ts index 0f353139..aea94177 100644 --- a/video-gen-admin/src/types/index.ts +++ b/video-gen-admin/src/types/index.ts @@ -342,3 +342,242 @@ export interface GenerationAITaskQueryParams { userName?: string; } + + +// ── Admin Replication Readonly Types ────────────────────────────────────── + +export type ModuleReplicationStatus = + | 'pending' + | 'waiting_user' + | 'processing' + | 'completed' + | 'failed' + | 'cancelled' + | string; + +export interface ReplicationStepOut { + id: string; + projectId: string; + module: string; + stepIndex: number; + stepCode: string; + status: string; + version: number; + isCurrent: boolean; + parentStepId?: string | null; + sourceStepId?: string | null; + chatTaskId?: string | null; + input?: Record | null; + output?: Record | null; + errorMessage?: string | null; + createdAt?: string | null; + updatedAt?: string | null; + completedAt?: string | null; +} + +export interface ReplicationMaterialOut { + materialStepId?: string | null; + materialVideoUrl?: string | null; + materialImageUrl?: string | null; + sourceProjectName?: string | null; + targetProjectName?: string | null; + coreContentPoint?: string | null; +} + +export interface ReplicationImageGenerationOut { + promptStepId?: string | null; + generateStepId?: string | null; + prompt?: string | null; + engineId?: string | null; + engineName?: string | null; + params?: Record | null; + chatTaskId?: string | null; + status?: string | null; + resultImageUrl?: string | null; + errorMessage?: string | null; +} + +export interface ReplicationVideoGenerationOut { + promptStepId?: string | null; + generateStepId?: string | null; + promptSchema?: Record | null; + finalPrompt?: string | null; + promptParams?: Record | null; + engineId?: string | null; + engineName?: string | null; + params?: Record | null; + chatTaskId?: string | null; + status?: string | null; + resultVideoUrl?: string | null; + resultVideoCoverUrl?: string | null; + errorMessage?: string | null; +} + +export interface ReplicationProjectDetailOut { + id: string; + projectId: string; + userId?: string | null; + userName?: string | null; + module: string; + title?: string | null; + status: ModuleReplicationStatus; + currentStepCode?: string | null; + finalImageUrl?: string | null; + finalVideoUrl?: string | null; + finalVideoCoverUrl?: string | null; + errorMessage?: string | null; + material: ReplicationMaterialOut; + imageGeneration: ReplicationImageGenerationOut; + videoGeneration: ReplicationVideoGenerationOut; + steps: ReplicationStepOut[]; + createdAt?: string | null; + updatedAt?: string | null; + completedAt?: string | null; +} + +export interface HotOpeningTaskListItemOut { + id: string; + projectId: string; + userId?: string | null; + userName?: string | null; + module: string; + title?: string | null; + status: ModuleReplicationStatus; + currentStepCode?: string | null; + sourceProjectName?: string | null; + targetProjectName?: string | null; + coreContentPoint?: string | null; + finalImageUrl?: string | null; + finalVideoUrl?: string | null; + finalVideoCoverUrl?: string | null; + errorMessage?: string | null; + createdAt?: string | null; + updatedAt?: string | null; + completedAt?: string | null; +} + +export interface HotOpeningTaskListOut { + total: number; + items: HotOpeningTaskListItemOut[]; +} + +export interface AdminHotOpeningTaskQueryParams { + status?: string; + keyword?: string; + userId?: string; + userName?: string; + createdStart?: string; + createdEnd?: string; + page?: number; + pageSize?: number; +} + +export interface ShotTaskSetOut { + id: string; + userId?: string | null; + userName?: string | null; + title?: string | null; + videoUrl: string; + videoDurationSeconds: number; + status: string; + analysisStatus: string; + splitStatus: string; + originalVideoContent?: string | null; + originalVideoCategory?: string | null; + originalVideoAudience?: string | null; + segmentCount: number; + completedSegmentCount: number; + failedSegmentCount: number; + analysisErrorMessage?: string | null; + splitErrorMessage?: string | null; + createdAt?: string | null; + updatedAt?: string | null; +} + +export interface ShotAiSuggestionOut { + index: number; + startSecond: number; + endSecond: number; + durationSeconds: number; + timeNode: string; + content?: string | null; + category?: string | null; + audience?: string | null; +} + +export interface ShotTaskSetDetailOut extends ShotTaskSetOut { + aiSuggestions: ShotAiSuggestionOut[]; + analysisResultJson?: Record | any[] | null; +} + +export interface ShotTaskSetListOut { + total: number; + page: number; + pageSize: number; + items: ShotTaskSetOut[]; +} + +export interface AdminShotTaskSetQueryParams { + status?: string; + analysisStatus?: string; + splitStatus?: string; + keyword?: string; + userId?: string; + userName?: string; + createdStart?: string; + createdEnd?: string; + page?: number; + pageSize?: number; +} + +export interface ShotSegmentOut { + id: string; + taskSetId: string; + segmentIndex: number; + segmentName?: string | null; + sourceMode: string; + startSecond: number; + endSecond: number; + durationSeconds: number; + timeNode: string; + splitStatus: string; + analysisStatus: string; + replicateStatus: string; + segmentVideoUrl?: string | null; + originalVideoContent?: string | null; + originalVideoCategory?: string | null; + originalVideoAudience?: string | null; + segmentContent?: string | null; + segmentCategory?: string | null; + segmentAudience?: string | null; + splitRetryCount: number; + splitLastError?: string | null; + analysisErrorMessage?: string | null; + moduleProjectId?: string | null; + moduleProjectTitle?: string | null; + moduleProjectStatus?: string | null; + moduleProjectCurrentStepCode?: string | null; + createdAt?: string | null; + updatedAt?: string | null; +} + +export interface ShotSegmentDetailOut extends ShotSegmentOut { + analysisJson?: Record | any[] | null; + aiSuggestionJson?: Record | any[] | null; +} + +export interface ShotSegmentListOut { + total: number; + page: number; + pageSize: number; + items: ShotSegmentOut[]; +} + +export interface AdminShotSegmentQueryParams { + sourceMode?: string; + splitStatus?: string; + analysisStatus?: string; + replicateStatus?: string; + page?: number; + pageSize?: number; +} diff --git a/video-gen-admin/tsconfig.tsbuildinfo b/video-gen-admin/tsconfig.tsbuildinfo index 6698c958..c1f0f8dc 100644 --- a/video-gen-admin/tsconfig.tsbuildinfo +++ b/video-gen-admin/tsconfig.tsbuildinfo @@ -1 +1 @@ -{"root":["./src/app.tsx","./src/env.d.ts","./src/main.tsx","./src/api/client.ts","./src/api/crypto.ts","./src/api/index.ts","./src/pages/admincreditratios.tsx","./src/pages/admincreditrecords.tsx","./src/pages/admindashboard.tsx","./src/pages/admingenerationairecords.tsx","./src/pages/admingenerationrecords.tsx","./src/pages/adminimageengines.tsx","./src/pages/adminindustries.tsx","./src/pages/adminlayout.tsx","./src/pages/adminloginpage.tsx","./src/pages/adminmenuconfig.tsx","./src/pages/adminmodels.tsx","./src/pages/adminnotificationmanager.tsx","./src/pages/adminoauthapplist.tsx","./src/pages/adminoperationlogs.tsx","./src/pages/adminpaymentconfig.tsx","./src/pages/adminpaymentstats.tsx","./src/pages/adminrechargepackages.tsx","./src/pages/adminsettings.tsx","./src/pages/adminusers.tsx","./src/pages/adminvideoengines.tsx","./src/store/index.ts","./src/types/index.ts","./src/utils/formatdate.ts"],"version":"6.0.3"} \ No newline at end of file +{"root":["./src/app.tsx","./src/env.d.ts","./src/main.tsx","./src/api/client.ts","./src/api/crypto.ts","./src/api/index.ts","./src/pages/admincreditratios.tsx","./src/pages/admincreditrecords.tsx","./src/pages/admindashboard.tsx","./src/pages/admingenerationairecords.tsx","./src/pages/admingenerationrecords.tsx","./src/pages/adminhotopeningreplicationdetail.tsx","./src/pages/adminhotopeningreplications.tsx","./src/pages/adminimageengines.tsx","./src/pages/adminindustries.tsx","./src/pages/adminlayout.tsx","./src/pages/adminloginpage.tsx","./src/pages/adminmenuconfig.tsx","./src/pages/adminmodels.tsx","./src/pages/adminnotificationmanager.tsx","./src/pages/adminoauthapplist.tsx","./src/pages/adminoperationlogs.tsx","./src/pages/adminpaymentconfig.tsx","./src/pages/adminpaymentstats.tsx","./src/pages/adminrechargepackages.tsx","./src/pages/adminreplicationprojectdetail.tsx","./src/pages/adminsettings.tsx","./src/pages/adminshotreplications.tsx","./src/pages/adminshottasksetdetail.tsx","./src/pages/adminusers.tsx","./src/pages/adminvideoengines.tsx","./src/pages/adminreplication/components/jsoncollapse.tsx","./src/pages/adminreplication/components/mediapreview.tsx","./src/pages/adminreplication/components/statustag.tsx","./src/pages/adminreplication/components/videopromptschemaviewer.tsx","./src/store/index.ts","./src/types/index.ts","./src/utils/formatdate.ts"],"version":"6.0.3"} \ No newline at end of file diff --git a/video-gen-api/alembic/versions/287c6c064c5d_新增素材前测表pre_test_template和素材表resources_.py b/video-gen-api/alembic/versions/287c6c064c5d_新增素材前测表pre_test_template和素材表resources_.py index 7562bf5e..959cd2b7 100644 --- a/video-gen-api/alembic/versions/287c6c064c5d_新增素材前测表pre_test_template和素材表resources_.py +++ b/video-gen-api/alembic/versions/287c6c064c5d_新增素材前测表pre_test_template和素材表resources_.py @@ -8,122 +8,262 @@ from typing import Sequence, Union from alembic import op import sqlalchemy as sa +from sqlalchemy import inspect # revision identifiers, used by Alembic. -revision: str = '287c6c064c5d' -down_revision: Union[str, None] = '9216bca75ccf' +revision: str = "287c6c064c5d" +down_revision: Union[str, None] = "9216bca75ccf" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None +def _inspector(): + return inspect(op.get_bind()) + + +def _table_exists(table_name: str) -> bool: + return table_name in _inspector().get_table_names(schema="public") + + +def _column_exists(table_name: str, column_name: str) -> bool: + if not _table_exists(table_name): + return False + columns = _inspector().get_columns(table_name, schema="public") + return any(column["name"] == column_name for column in columns) + + +def _index_exists(table_name: str, index_name: str) -> bool: + if not _table_exists(table_name): + return False + indexes = _inspector().get_indexes(table_name, schema="public") + return any(index["name"] == index_name for index in indexes) + + +def _create_pre_test_template_table() -> None: + op.create_table( + "pre_test_template", + sa.Column("id", sa.String(length=32), nullable=False, comment="主键"), + sa.Column("name", sa.String(length=128), nullable=False, comment="模板名称"), + sa.Column("user_id", sa.String(length=32), nullable=False, comment="用户id"), + sa.Column("note", sa.Text(), nullable=True, comment="模板备注"), + sa.Column("platform", sa.String(length=32), nullable=True, comment="投放平台(AD/QIANCHUAN/LOCAL)"), + sa.Column("external_action", sa.String(length=64), nullable=True, comment="转化目标"), + sa.Column("cpa_bid", sa.Float(), nullable=True, comment="目标转化成本:[1, 10000]"), + sa.Column("audience_gender", sa.String(length=16), nullable=True, comment="性别(ALL/MALE/FEMALE)"), + sa.Column("audience_age", sa.Text(), nullable=True, comment="受众年龄,JSON数组, 格式:[ALL,18-23, 24-30, 31-40, 41-49, 50+]"), + sa.Column("audience_region", sa.Text(), nullable=True, comment="受众地区,JSON数组(二级行政区域code)"), + sa.Column("audience_network", sa.Text(), nullable=True, comment="网络类型,JSON数组, 格式:[ALL,5G,4G,3G,2G,WIFI]"), + sa.Column("cus_name", sa.String(length=256), nullable=True, comment="客户主体名称"), + sa.Column("pricing_type", sa.String(length=16), nullable=True, comment="出价类型(OCPC/CPA/OCPM)"), + sa.Column("cost_cap", sa.Boolean(), nullable=True, comment="是否最优成本出价(仅AD支持)"), + sa.Column("target_cost", sa.Boolean(), nullable=True, comment="是否稳定成本出价(仅AD支持)"), + sa.Column("nobid", sa.Boolean(), nullable=True, comment="是否最大转化出价(仅AD支持)"), + sa.Column("cpc_bid", sa.Float(), nullable=True, comment="目标点击成本:[1, 10000]"), + sa.Column("budget", sa.Float(), nullable=True, comment="预算金额:[1, 10000]"), + sa.Column("is_default", sa.Boolean(), nullable=True, comment="是否默认模板"), + sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), + sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), + sa.Column("deleted_at", sa.DateTime(timezone=True), nullable=True), + sa.PrimaryKeyConstraint("id", name="pre_test_template_pkey"), + ) + + if not _index_exists("pre_test_template", "ix_pre_test_template_user_id"): + op.create_index( + "ix_pre_test_template_user_id", + "pre_test_template", + ["user_id"], + unique=False, + ) + + +def _upgrade_existing_pre_test_template_table() -> None: + if not _column_exists("pre_test_template", "note"): + op.add_column( + "pre_test_template", + sa.Column("note", sa.Text(), nullable=True, comment="模板备注"), + ) + + if _column_exists("pre_test_template", "platform"): + op.alter_column( + "pre_test_template", + "platform", + existing_type=sa.VARCHAR(length=32), + nullable=True, + existing_comment="投放平台(AD/QIANCHUAN/LOCAL)", + ) + + if _column_exists("pre_test_template", "external_action"): + op.alter_column( + "pre_test_template", + "external_action", + existing_type=sa.VARCHAR(length=64), + nullable=True, + existing_comment="转化目标", + ) + + if _column_exists("pre_test_template", "audience_gender"): + op.alter_column( + "pre_test_template", + "audience_gender", + existing_type=sa.VARCHAR(length=16), + nullable=True, + existing_comment="性别(ALL/MALE/FEMALE)", + ) + + if _column_exists("pre_test_template", "audience_age"): + op.alter_column( + "pre_test_template", + "audience_age", + existing_type=sa.TEXT(), + comment="受众年龄,JSON数组, 格式:[ALL,18-23, 24-30, 31-40, 41-49, 50+]", + existing_comment="受众年龄,JSON数组", + existing_nullable=True, + ) + + if _column_exists("pre_test_template", "audience_network"): + op.alter_column( + "pre_test_template", + "audience_network", + existing_type=sa.TEXT(), + comment="网络类型,JSON数组, 格式:[ALL,5G,4G,3G,2G,WIFI]", + existing_comment="网络类型,JSON数组", + existing_nullable=True, + ) + + if _column_exists("pre_test_template", "pricing_type"): + op.alter_column( + "pre_test_template", + "pricing_type", + existing_type=sa.VARCHAR(length=16), + nullable=True, + existing_comment="出价类型(OCPC/CPA/OCPM)", + ) + + if _column_exists("pre_test_template", "cost_cap"): + op.alter_column( + "pre_test_template", + "cost_cap", + existing_type=sa.BOOLEAN(), + nullable=True, + existing_comment="是否最优成本出价(仅AD支持)", + ) + + if _column_exists("pre_test_template", "target_cost"): + op.alter_column( + "pre_test_template", + "target_cost", + existing_type=sa.BOOLEAN(), + nullable=True, + existing_comment="是否稳定成本出价(仅AD支持)", + ) + + if _column_exists("pre_test_template", "nobid"): + op.alter_column( + "pre_test_template", + "nobid", + existing_type=sa.BOOLEAN(), + nullable=True, + existing_comment="是否最大转化出价(仅AD支持)", + ) + + if _column_exists("pre_test_template", "is_default"): + op.alter_column( + "pre_test_template", + "is_default", + existing_type=sa.BOOLEAN(), + nullable=True, + existing_comment="是否默认模板", + ) + + if _column_exists("pre_test_template", "status"): + op.drop_column("pre_test_template", "status") + + if _column_exists("pre_test_template", "description"): + op.drop_column("pre_test_template", "description") + + if not _index_exists("pre_test_template", "ix_pre_test_template_user_id"): + op.create_index( + "ix_pre_test_template_user_id", + "pre_test_template", + ["user_id"], + unique=False, + ) + + def upgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - op.add_column('pre_test_template', sa.Column('note', sa.Text(), nullable=True, comment='模板备注')) - op.alter_column('pre_test_template', 'platform', - existing_type=sa.VARCHAR(length=32), - nullable=True, - existing_comment='投放平台(AD/QIANCHUAN/LOCAL)') - op.alter_column('pre_test_template', 'external_action', - existing_type=sa.VARCHAR(length=64), - nullable=True, - existing_comment='转化目标') - op.alter_column('pre_test_template', 'audience_gender', - existing_type=sa.VARCHAR(length=16), - nullable=True, - existing_comment='性别(ALL/MALE/FEMALE)') - op.alter_column('pre_test_template', 'audience_age', - existing_type=sa.TEXT(), - comment='受众年龄,JSON数组, 格式:[ALL,18-23, 24-30, 31-40, 41-49, 50+]', - existing_comment='受众年龄,JSON数组', - existing_nullable=True) - op.alter_column('pre_test_template', 'audience_network', - existing_type=sa.TEXT(), - comment='网络类型,JSON数组, 格式:[ALL,5G,4G,3G,2G,WIFI]', - existing_comment='网络类型,JSON数组', - existing_nullable=True) - op.alter_column('pre_test_template', 'pricing_type', - existing_type=sa.VARCHAR(length=16), - nullable=True, - existing_comment='出价类型(OCPC/CPA/OCPM)') - op.alter_column('pre_test_template', 'cost_cap', - existing_type=sa.BOOLEAN(), - nullable=True, - existing_comment='是否最优成本出价(仅AD支持)') - op.alter_column('pre_test_template', 'target_cost', - existing_type=sa.BOOLEAN(), - nullable=True, - existing_comment='是否稳定成本出价(仅AD支持)') - op.alter_column('pre_test_template', 'nobid', - existing_type=sa.BOOLEAN(), - nullable=True, - existing_comment='是否最大转化出价(仅AD支持)') - op.alter_column('pre_test_template', 'is_default', - existing_type=sa.BOOLEAN(), - nullable=True, - existing_comment='是否默认模板') - op.drop_column('pre_test_template', 'status') - op.drop_column('pre_test_template', 'description') - op.add_column('resources_material', sa.Column('task_id', sa.String(length=32), nullable=True, comment='前测任务id')) - op.add_column('resources_material', sa.Column('note', sa.Text(), nullable=True, comment='前测失败备注或者其他备注')) - op.add_column('resources_material', sa.Column('status', sa.String(length=16), nullable=True, comment='前测状态(FAILED/PENDING/SUCCESS)')) - op.add_column('resources_material', sa.Column('pre_result', sa.Text(), nullable=True, comment='前测结果,JSON数组对象')) - op.add_column('resources_material', sa.Column('pre_test_template_id', sa.String(length=32), nullable=True, comment='前测模板id')) - op.create_index(op.f('ix_resources_material_task_id'), 'resources_material', ['task_id'], unique=False) - # ### end Alembic commands ### + # pre_test_template 是这版迁移缺失的核心表。 + # 如果不存在,直接按当前模型源码创建完整表。 + # 如果已存在,则按原迁移逻辑补 note、调整 nullable/comment、删除旧字段。 + if not _table_exists("pre_test_template"): + _create_pre_test_template_table() + else: + _upgrade_existing_pre_test_template_table() + + # resources_material 追加字段,按源码迁移逻辑保留,同时增加字段存在判断,避免重复执行报错。 + if _table_exists("resources_material"): + if not _column_exists("resources_material", "task_id"): + op.add_column( + "resources_material", + sa.Column("task_id", sa.String(length=32), nullable=True, comment="前测任务id"), + ) + + if not _column_exists("resources_material", "note"): + op.add_column( + "resources_material", + sa.Column("note", sa.Text(), nullable=True, comment="前测失败备注或者其他备注"), + ) + + if not _column_exists("resources_material", "status"): + op.add_column( + "resources_material", + sa.Column("status", sa.String(length=16), nullable=True, comment="前测状态(FAILED/PENDING/SUCCESS)"), + ) + + if not _column_exists("resources_material", "pre_result"): + op.add_column( + "resources_material", + sa.Column("pre_result", sa.Text(), nullable=True, comment="前测结果,JSON数组对象"), + ) + + if not _column_exists("resources_material", "pre_test_template_id"): + op.add_column( + "resources_material", + sa.Column("pre_test_template_id", sa.String(length=32), nullable=True, comment="前测模板id"), + ) + + if not _index_exists("resources_material", "ix_resources_material_task_id"): + op.create_index( + "ix_resources_material_task_id", + "resources_material", + ["task_id"], + unique=False, + ) def downgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - op.drop_index(op.f('ix_resources_material_task_id'), table_name='resources_material') - op.drop_column('resources_material', 'pre_test_template_id') - op.drop_column('resources_material', 'pre_result') - op.drop_column('resources_material', 'status') - op.drop_column('resources_material', 'note') - op.drop_column('resources_material', 'task_id') - op.add_column('pre_test_template', sa.Column('description', sa.TEXT(), autoincrement=False, nullable=True, comment='模板描述')) - op.add_column('pre_test_template', sa.Column('status', sa.INTEGER(), autoincrement=False, nullable=False, comment='状态(0=禁用,1=启用)')) - op.alter_column('pre_test_template', 'is_default', - existing_type=sa.BOOLEAN(), - nullable=False, - existing_comment='是否默认模板') - op.alter_column('pre_test_template', 'nobid', - existing_type=sa.BOOLEAN(), - nullable=False, - existing_comment='是否最大转化出价(仅AD支持)') - op.alter_column('pre_test_template', 'target_cost', - existing_type=sa.BOOLEAN(), - nullable=False, - existing_comment='是否稳定成本出价(仅AD支持)') - op.alter_column('pre_test_template', 'cost_cap', - existing_type=sa.BOOLEAN(), - nullable=False, - existing_comment='是否最优成本出价(仅AD支持)') - op.alter_column('pre_test_template', 'pricing_type', - existing_type=sa.VARCHAR(length=16), - nullable=False, - existing_comment='出价类型(OCPC/CPA/OCPM)') - op.alter_column('pre_test_template', 'audience_network', - existing_type=sa.TEXT(), - comment='网络类型,JSON数组', - existing_comment='网络类型,JSON数组, 格式:[ALL,5G,4G,3G,2G,WIFI]', - existing_nullable=True) - op.alter_column('pre_test_template', 'audience_age', - existing_type=sa.TEXT(), - comment='受众年龄,JSON数组', - existing_comment='受众年龄,JSON数组, 格式:[ALL,18-23, 24-30, 31-40, 41-49, 50+]', - existing_nullable=True) - op.alter_column('pre_test_template', 'audience_gender', - existing_type=sa.VARCHAR(length=16), - nullable=False, - existing_comment='性别(ALL/MALE/FEMALE)') - op.alter_column('pre_test_template', 'external_action', - existing_type=sa.VARCHAR(length=64), - nullable=False, - existing_comment='转化目标') - op.alter_column('pre_test_template', 'platform', - existing_type=sa.VARCHAR(length=32), - nullable=False, - existing_comment='投放平台(AD/QIANCHUAN/LOCAL)') - op.drop_column('pre_test_template', 'note') - # ### end Alembic commands ### + if _table_exists("resources_material"): + if _index_exists("resources_material", "ix_resources_material_task_id"): + op.drop_index("ix_resources_material_task_id", table_name="resources_material") + + if _column_exists("resources_material", "pre_test_template_id"): + op.drop_column("resources_material", "pre_test_template_id") + + if _column_exists("resources_material", "pre_result"): + op.drop_column("resources_material", "pre_result") + + if _column_exists("resources_material", "status"): + op.drop_column("resources_material", "status") + + if _column_exists("resources_material", "note"): + op.drop_column("resources_material", "note") + + if _column_exists("resources_material", "task_id"): + op.drop_column("resources_material", "task_id") + + # 这一版迁移负责新增 pre_test_template 表,所以回滚时删除该表。 + if _table_exists("pre_test_template"): + if _index_exists("pre_test_template", "ix_pre_test_template_user_id"): + op.drop_index("ix_pre_test_template_user_id", table_name="pre_test_template") + + op.drop_table("pre_test_template") \ No newline at end of file diff --git a/video-gen-api/app/api/v1/__init__.py b/video-gen-api/app/api/v1/__init__.py index 6bc09321..7430c445 100644 --- a/video-gen-api/app/api/v1/__init__.py +++ b/video-gen-api/app/api/v1/__init__.py @@ -21,6 +21,7 @@ from app.api.v1.test import router as test_router from app.api.v1.user_oauth import router as user_oauth_router from app.api.v1.user_oauth_app import router as user_oauth_app_router from app.api.v1.upload_material import router as upload_material_router +from app.api.v1.pre_test_template import router as pre_test_template_router api_router = APIRouter() api_router.include_router(auth_router) @@ -44,3 +45,4 @@ api_router.include_router(test_router) api_router.include_router(user_oauth_router) api_router.include_router(user_oauth_app_router) api_router.include_router(upload_material_router) +api_router.include_router(pre_test_template_router) diff --git a/video-gen-api/app/api/v1/admin.py b/video-gen-api/app/api/v1/admin.py index 12961243..eee15906 100644 --- a/video-gen-api/app/api/v1/admin.py +++ b/video-gen-api/app/api/v1/admin.py @@ -1081,8 +1081,8 @@ async def update_system_config( config = result.scalar_one_or_none() if not config: raise HTTPException(status_code=404, detail="配置不存在") - config.value = req.value - await db.flush() + config.value = str(req.value) + await db.commit() return config diff --git a/video-gen-api/app/api/v1/hot_opening_replicate.py b/video-gen-api/app/api/v1/hot_opening_replicate.py index c7c9b493..0550b97b 100644 --- a/video-gen-api/app/api/v1/hot_opening_replicate.py +++ b/video-gen-api/app/api/v1/hot_opening_replicate.py @@ -1,5 +1,6 @@ from __future__ import annotations +from datetime import datetime from types import SimpleNamespace from fastapi import APIRouter, Body, Depends, HTTPException, Path, Query @@ -8,6 +9,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from app.dependencies import get_current_user, get_db from app.models.user import User +from app.enums.common import ModuleProjectStatusEnum from app.enums.hot_opening_replicate import HotOpeningStepCodeEnum, ModuleCodeEnum from app.schemas.hot_opening_replicate import ( HotOpeningActionOut, @@ -195,7 +197,7 @@ async def _mark_dispatch_failed_and_raise( "/spec", response_model=HotOpeningSpecOut, summary="查询爆款开头复刻模块状态枚举和步骤 JSON 结构说明", - description="返回总任务状态、子任务状态、5个固定步骤编码以及每个步骤 input_json/output_json 的统一结构示例,方便前端和排查人员对照。", + description="保留给调试和前端兜底读取。原业务接口已经在 Path、Query、Body 和响应模型字段上直接展示参数说明与枚举值。", ) async def get_spec(): return HotOpeningSpecOut() @@ -239,13 +241,38 @@ async def create_task( description="分页查询爆款开头复刻总任务项目列表。普通用户只能查看自己的项目,管理员可查看全部。", ) async def list_tasks( - status: str | None = Query(None, description="总任务状态筛选,例如 waiting_user、processing、completed、failed;为空不过滤"), + status: ModuleProjectStatusEnum | None = Query(None, description="总任务状态筛选:pending=已创建,waiting_user=等待用户操作,processing=处理中,completed=完成,failed=失败,cancelled=取消;为空不过滤"), + keyword: str | None = Query(None, description="关键词搜索:项目ID、标题、生成项目名称、素材项目名称、核心内容点;普通用户只在自己的数据内搜索"), + user_id: str | None = Query(None, description="管理员专用:按用户ID筛选;普通用户不可使用"), + user_name: str | None = Query(None, description="管理员专用:按用户名模糊筛选;普通用户不可使用"), + created_start: datetime | None = Query(None, description="管理员专用:创建时间开始,ISO datetime;普通用户不可使用"), + created_end: datetime | None = Query(None, description="管理员专用:创建时间结束,ISO datetime;普通用户不可使用"), page: int = Query(1, ge=1, description="分页页码,从1开始"), page_size: int = Query(20, ge=1, le=100, description="每页数量,范围1-100"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): - return await list_hot_opening_projects(db, current_user=current_user, status=status, page=page, page_size=page_size) + admin_only_params = { + "user_id": user_id, + "user_name": user_name, + "created_start": created_start, + "created_end": created_end, + } + if not _safe_user_is_admin(current_user) and any(value is not None and str(value).strip() != "" for value in admin_only_params.values()): + raise HTTPException(status_code=403, detail="当前搜索条件仅管理员可用") + + return await list_hot_opening_projects( + db, + current_user=current_user, + status=status.value if status else None, + keyword=keyword, + user_id=user_id, + user_name=user_name, + created_start=created_start, + created_end=created_end, + page=page, + page_size=page_size, + ) @router.get( diff --git a/video-gen-api/app/api/v1/pre_test_template.py b/video-gen-api/app/api/v1/pre_test_template.py new file mode 100644 index 00000000..d19403bf --- /dev/null +++ b/video-gen-api/app/api/v1/pre_test_template.py @@ -0,0 +1,358 @@ +import json +from typing import Any, Optional, Dict + +from fastapi import APIRouter, Depends, HTTPException, Query, status +from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy import select +from app.models.pre_test_template import PreTestTemplate +from app.utils.douyinApi import DouyinApi +from app.utils.area import parse_district_data, get_area_by_level, get_cached_area_data, fetch_and_cache_area_data + + +from app.dependencies import get_current_user, get_db +from app.models.user import User +from app.schemas.pre_test_template import ( + PreTestTemplateCreate, + PreTestTemplateListResponse, + PreTestTemplateOut, + PreTestTemplateUpdate, +) +from app.services.pre_test_template_service import ( + create_pre_test_template, + delete_pre_test_template, + get_default_template, + get_pre_test_template, + get_pre_test_template_list, + update_pre_test_template, +) + +router = APIRouter(prefix="/pre-test-template", tags=["前测模板"]) + + +def _template_to_dict(template): + return { + "id": template.id, + "name": template.name, + "note": template.note, + "platform": template.platform, + "external_action": template.external_action, + "cpa_bid": template.cpa_bid, + "audience_gender": template.audience_gender, + "audience_age": json.loads(template.audience_age) if template.audience_age else None, + "audience_region": json.loads(template.audience_region) if template.audience_region else None, + "audience_network": json.loads(template.audience_network) if template.audience_network else None, + "cus_name": template.cus_name, + "pricing_type": template.pricing_type, + "cost_cap": template.cost_cap, + "target_cost": template.target_cost, + "nobid": template.nobid, + "cpc_bid": template.cpc_bid, + "budget": template.budget, + "is_default": template.is_default, + "user_id": template.user_id, + "created_at": template.created_at, + "updated_at": template.updated_at, + } + + +@router.post( + "/create", + summary="创建前测模板", + description="创建一个新的前测模板", +) +async def create_template( + req: PreTestTemplateCreate, + current_user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +) -> Any: + try: + #新增一个判断,如果模板名称重复,提示用户修改 + result = await db.execute( + select(PreTestTemplate).where( + PreTestTemplate.name == req.name, + PreTestTemplate.user_id == current_user.id, + PreTestTemplate.deleted_at.is_(None), + ) + ) + existing_template = result.scalar() + if existing_template: + raise ValueError("模板名称已存在") + + template = await create_pre_test_template( + user_id=current_user.id, + db=db, + name=req.name, + note=req.note, + platform=req.platform, + external_action=req.external_action, + cpa_bid=req.cpa_bid, + audience_gender=req.audience_gender, + audience_age=req.audience_age, + audience_region=req.audience_region, + audience_network=req.audience_network, + cus_name=req.cus_name, + pricing_type=req.pricing_type, + cost_cap=req.cost_cap, + target_cost=req.target_cost, + nobid=req.nobid, + cpc_bid=req.cpc_bid, + budget=req.budget, + is_default=req.is_default, + ) + + return { + "code": 0, + "message": "创建成功", + } + except ValueError as e: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=str(e), + ) + except Exception as e: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"创建失败: {str(e)}", + ) + + +@router.get( + "/list", + summary="获取前测模板列表", + description="获取当前用户的前测模板列表,支持按平台筛选和分页", + response_model=PreTestTemplateListResponse, +) +async def list_templates( + platform: Optional[str] = Query(None, description="投放平台筛选(AD/QIANCHUAN/LOCAL)"), + page: int = Query(1, description="页码,默认1"), + page_size: int = Query(10, description="每页数量,默认10,最大100"), + current_user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +) -> Any: + try: + result = await get_pre_test_template_list( + user_id=current_user.id, + db=db, + platform=platform, + page=page, + page_size=page_size, + ) + + return { + "code": 0, + "message": "查询成功", + "data": [_template_to_dict(t) for t in result["data"]], + "pagination": { + "page": result["page"], + "page_size": result["page_size"], + "total": result["total"], + "total_pages": (result["total"] + result["page_size"] - 1) // result["page_size"], + }, + } + except ValueError as e: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=str(e), + ) + except Exception as e: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"查询失败: {str(e)}", + ) + + +@router.get( + "/default", + summary="获取默认前测模板", + description="获取当前用户的默认前测模板", +) +async def get_default( + current_user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +) -> Any: + try: + template = await get_default_template(current_user.id, db) + + if not template: + return { + "code": 0, + "message": "未设置默认模板", + "data": None, + } + + return { + "code": 0, + "message": "查询成功", + "data": _template_to_dict(template), + } + except Exception as e: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"查询失败: {str(e)}", + ) + + +@router.get( + "/select/{template_id}", + summary="获取前测模板详情", + description="根据模板id获取前测模板详情", +) +async def get_template( + template_id: str, + current_user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +) -> Any: + try: + template = await get_pre_test_template(template_id, current_user.id, db) + + if not template: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="模板不存在", + ) + + return { + "code": 0, + "message": "查询成功", + "data": _template_to_dict(template), + } + except HTTPException: + raise + except Exception as e: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"查询失败: {str(e)}", + ) + + +@router.post( + "/update/{template_id}", + summary="更新前测模板", + description="更新指定的前测模板", +) +async def update_template( + template_id: str, + req: PreTestTemplateUpdate, + current_user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +) -> Any: + try: + update_data = req.dict(exclude_none=True) + template = await update_pre_test_template(template_id, current_user.id, db, **update_data) + + if not template: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="模板不存在", + ) + + return { + "code": 0, + "message": "更新成功", + "data": _template_to_dict(template), + } + except HTTPException: + raise + except ValueError as e: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=str(e), + ) + except Exception as e: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"更新失败: {str(e)}", + ) + + +@router.get( + "/delete/{template_id}", + summary="删除前测模板", + description="软删除指定的前测模板", +) +async def delete_template( + template_id: str, + current_user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +) -> Any: + try: + success = await delete_pre_test_template(template_id, current_user.id, db) + + if not success: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="模板不存在", + ) + + return { + "code": 0, + "message": "删除成功", + } + except HTTPException: + raise + except Exception as e: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"删除失败: {str(e)}", + ) + + +@router.get( + "/getArea", + summary="获取行政区域信息", + description="获取指定级别的行政区域信息,支持一级、二级、三级区域,如果需要更新地区,执行:/api/pre-test-template/getArea?oauth_id=0019ecab9b8bc57d964&advertiser_id=1836693172153543", +) +async def get_template_area( + oauth_id: str = Query(None, description="授权ID选填,更新地区必填"), + advertiser_id: str = Query(default="1836693172153543", description="授权ID选填,更新地区必填"), + code: Optional[str] = Query("CN", description="行政区域编码,默认中国CN,选填"), + level: Optional[str] = Query("ONE_LEVEL", description="行政区域层级,可选值:ONE_LEVEL(获取省份)、TWO_LEVEL(市级)、THREE_LEVEL(区级)"), + parent_code: Optional[str] = Query(None, description="父级区域编码,获取二级时传一级编码,获取三级时传二级编码"), +) -> Any: + try: + # 1. 先检查缓存是否存在 + area_list = get_cached_area_data() + + # 2. 如果缓存不存在,调用接口获取数据并保存到缓存 + if not area_list: + area_list = await fetch_and_cache_area_data(oauth_id, advertiser_id, code) + + # 3. 根据 level 参数过滤区域 + if level == "ONE_LEVEL": + result = get_area_by_level(area_list, "ONE_LEVEL") + elif level == "TWO_LEVEL": + result = get_area_by_level(area_list, "TWO_LEVEL", parent_code) + elif level == "THREE_LEVEL": + if not parent_code: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="获取三级区域需要提供二级区域编码(parent_code)", + ) + result = get_area_by_level(area_list, "THREE_LEVEL", parent_code) + else: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=f"不支持的级别: {level}", + ) + + # 4. 转换为字典格式返回 + result_dict = [area.to_dict() for area in result] + + return { + "code": 0, + "message": "成功", + "data": result_dict, + } + + except HTTPException: + raise + except ValueError as e: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=str(e), + ) + except Exception as e: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"获取区域信息失败: {str(e)}", + ) diff --git a/video-gen-api/app/api/v1/shot_replicate.py b/video-gen-api/app/api/v1/shot_replicate.py index d620f104..d1720205 100644 --- a/video-gen-api/app/api/v1/shot_replicate.py +++ b/video-gen-api/app/api/v1/shot_replicate.py @@ -1,5 +1,6 @@ from __future__ import annotations +from datetime import datetime from types import SimpleNamespace from fastapi import APIRouter, Body, Depends, HTTPException, Path, Query @@ -8,7 +9,16 @@ from sqlalchemy.ext.asyncio import AsyncSession from app.dependencies import get_current_user, get_db from app.models.user import User -from app.enums.shot_replicate import ModuleCodeEnum, ShotReplicateStepCodeEnum +from app.enums.shot_replicate import ( + ModuleCodeEnum, + ShotAnalysisStatusEnum, + ShotReplicateStepCodeEnum, + ShotSegmentAnalysisStatusEnum, + ShotSegmentReplicateStatusEnum, + ShotSegmentSourceModeEnum, + ShotSplitStatusEnum, + ShotTaskSetStatusEnum, +) from app.schemas.shot_replicate import ( ShotReplicateActionOut, ShotReplicateDeleteOut, @@ -222,6 +232,7 @@ async def _mark_dispatch_failed_and_raise( "/spec", response_model=ShotReplicateSpecOut, summary="查询拆镜复刻模块状态枚举和步骤 JSON 结构说明", + description="保留给调试和前端兜底读取。原业务接口已经在 Path、Query、Body 和响应模型字段上直接展示参数说明与枚举值。", ) async def get_spec(): return ShotReplicateSpecOut() @@ -231,9 +242,14 @@ async def get_spec(): "/task-sets", response_model=ShotTaskSetDetailOut, summary="创建拆镜总任务集并异步分析原视频", + description=( + "创建拆镜总任务集,保存原视频地址和时长,随后异步投递原视频 AI 分析任务。" + "分析完成后会写入原视频内容、分类、受众和 AI 建议拆镜时间段。" + "状态枚举直接见本接口响应字段:status、analysis_status、split_status。" + ), ) async def create_shot_task_set( - req: ShotTaskSetCreate = Body(...), + req: ShotTaskSetCreate = Body(..., description="创建拆镜总任务集参数:原视频 URL、视频时长、标题和可选幂等键"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): @@ -275,22 +291,39 @@ async def create_shot_task_set( summary="查询拆镜总任务集列表", ) async def list_shot_task_sets( - status: str | None = Query(None, description="总任务状态,见 ShotTaskSetStatusEnum"), - analysis_status: str | None = Query(None, description="分析状态,见 ShotAnalysisStatusEnum"), - split_status: str | None = Query(None, description="拆镜状态,见 ShotSplitStatusEnum"), - keyword: str | None = Query(None, description="标题/内容关键词"), - page: int = Query(1, ge=1), - page_size: int = Query(20, ge=1, le=100), + status: ShotTaskSetStatusEnum | None = Query(None, description="总任务状态筛选:pending_analysis=等待分析,analyzing=分析中,analysis_completed=分析完成,analysis_failed=分析失败,splitting=拆镜中,split_completed=拆镜完成,partial_failed=部分失败,failed=失败,deleted=已软删"), + analysis_status: ShotAnalysisStatusEnum | None = Query(None, description="原视频分析状态筛选:pending=待分析,processing=分析中,completed=分析完成,failed=分析失败"), + split_status: ShotSplitStatusEnum | None = Query(None, description="拆镜状态筛选:none=尚未拆镜,pending=待拆镜,processing=拆镜中,completed=拆镜完成,failed=拆镜失败,retry_waiting=等待恢复重试"), + keyword: str | None = Query(None, description="标题/原视频内容/分类/受众关键词,模糊搜索;普通用户只在自己的数据内搜索"), + user_id: str | None = Query(None, description="管理员专用:按用户ID筛选;普通用户不可使用"), + user_name: str | None = Query(None, description="管理员专用:按用户名模糊筛选;普通用户不可使用"), + created_start: datetime | None = Query(None, description="管理员专用:创建时间开始,ISO datetime;普通用户不可使用"), + created_end: datetime | None = Query(None, description="管理员专用:创建时间结束,ISO datetime;普通用户不可使用"), + page: int = Query(1, ge=1, description="分页页码,从1开始"), + page_size: int = Query(20, ge=1, le=100, description="每页数量,范围1-100"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): + admin_only_params = { + "user_id": user_id, + "user_name": user_name, + "created_start": created_start, + "created_end": created_end, + } + if not _safe_user_is_admin(current_user) and any(value is not None and str(value).strip() != "" for value in admin_only_params.values()): + raise HTTPException(status_code=403, detail="当前搜索条件仅管理员可用") + return await list_task_sets( db, current_user=current_user, - status=status, - analysis_status=analysis_status, - split_status=split_status, + status=status.value if status else None, + analysis_status=analysis_status.value if analysis_status else None, + split_status=split_status.value if split_status else None, keyword=keyword, + user_id=user_id, + user_name=user_name, + created_start=created_start, + created_end=created_end, page=page, page_size=page_size, ) @@ -300,9 +333,10 @@ async def list_shot_task_sets( "/task-sets/{task_set_id}", response_model=ShotTaskSetDetailOut, summary="获取拆镜总任务集详情", + description="根据拆镜总任务集ID查询详情,包含原视频分析结果、AI 建议拆镜列表和当前总任务状态。", ) async def get_shot_task_set( - task_set_id: str = Path(...), + task_set_id: str = Path(..., description="拆镜总任务集ID,即 shot_replicate_task_sets.id"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): @@ -313,10 +347,14 @@ async def get_shot_task_set( "/task-sets/{task_set_id}/split-by-ai", response_model=ShotSplitByAIOut, summary="按 AI 建议方案异步拆镜", + description=( + "基于原视频 AI 分析生成的建议时间段创建拆镜片段,并异步投递 ffmpeg 切割任务。" + "selected_indices 不传时默认按全部 AI 建议拆镜;replace_existing=true 时会软删旧 AI 建议片段后重新创建。" + ), ) async def split_by_ai( - task_set_id: str = Path(...), - req: ShotSplitByAIRequest = Body(default_factory=ShotSplitByAIRequest), + task_set_id: str = Path(..., description="拆镜总任务集ID,即 shot_replicate_task_sets.id"), + req: ShotSplitByAIRequest = Body(default_factory=ShotSplitByAIRequest, description="AI 建议拆镜参数:可选择建议序号,也可选择是否覆盖旧 AI 片段"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): @@ -345,10 +383,11 @@ async def split_by_ai( "/task-sets/{task_set_id}/split-custom", response_model=ShotSplitCustomOut, summary="按用户自定义开始/结束秒异步拆单条片段", + description="按用户传入的 start_second/end_second 创建 custom 来源片段,并异步投递 ffmpeg 切割任务;切割完成后可进入复刻项目。", ) async def split_custom( - task_set_id: str = Path(...), - req: ShotSplitCustomRequest = Body(...), + task_set_id: str = Path(..., description="拆镜总任务集ID,即 shot_replicate_task_sets.id"), + req: ShotSplitCustomRequest = Body(..., description="自定义拆镜时间段参数,end_second 必须大于 start_second"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): @@ -376,15 +415,16 @@ async def split_custom( "/task-sets/{task_set_id}/segments", response_model=ShotSegmentListOut, summary="查询拆镜片段列表", + description="分页查询指定拆镜总任务集下的片段列表,可按来源、切割状态、片段分析状态和复刻状态筛选。", ) async def list_task_set_segments( - task_set_id: str = Path(...), - source_mode: str | None = Query(None, description="ai_suggestion/custom"), - split_status: str | None = Query(None, description="拆镜状态"), - analysis_status: str | None = Query(None, description="片段分析状态"), - replicate_status: str | None = Query(None, description="复刻状态"), - page: int = Query(1, ge=1), - page_size: int = Query(20, ge=1, le=100), + task_set_id: str = Path(..., description="拆镜总任务集ID,即 shot_replicate_task_sets.id"), + source_mode: ShotSegmentSourceModeEnum | None = Query(None, description="片段来源:ai_suggestion=AI 建议拆镜,custom=用户自定义拆镜"), + split_status: ShotSplitStatusEnum | None = Query(None, description="切割状态:none=尚未拆镜,pending=待拆镜,processing=拆镜中,completed=拆镜完成,failed=拆镜失败,retry_waiting=等待恢复重试"), + analysis_status: ShotSegmentAnalysisStatusEnum | None = Query(None, description="片段分析状态:not_required=无需单独分析,pending=等待分析,processing=分析中,completed=分析完成,failed=分析失败"), + replicate_status: ShotSegmentReplicateStatusEnum | None = Query(None, description="片段复刻状态:not_started=未复刻,project_created=已创建复刻项目,processing=复刻处理中,completed=复刻完成,failed=复刻失败"), + page: int = Query(1, ge=1, description="分页页码,从1开始"), + page_size: int = Query(20, ge=1, le=100, description="每页数量,范围1-100"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): @@ -392,10 +432,10 @@ async def list_task_set_segments( db, current_user=current_user, task_set_id=task_set_id, - source_mode=source_mode, - split_status=split_status, - analysis_status=analysis_status, - replicate_status=replicate_status, + source_mode=source_mode.value if source_mode else None, + split_status=split_status.value if split_status else None, + analysis_status=analysis_status.value if analysis_status else None, + replicate_status=replicate_status.value if replicate_status else None, page=page, page_size=page_size, ) @@ -405,9 +445,10 @@ async def list_task_set_segments( "/segments/{segment_id}", response_model=ShotSegmentDetailOut, summary="获取拆镜片段详情", + description="根据拆镜片段ID查询单个片段详情,包含切割结果、片段分析结果、复刻项目ID和状态。", ) async def get_segment( - segment_id: str = Path(...), + segment_id: str = Path(..., description="拆镜片段ID,即 shot_replicate_segments.id"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): @@ -418,10 +459,15 @@ async def get_segment( "/segments/{segment_id}/replication-projects", response_model=ShotReplicateActionOut, summary="将拆镜片段创建为拆镜复刻项目", + description=( + "以拆镜片段作为锁定素材视频创建 ModuleGenerationProject 复刻项目。" + "创建后只同步生成第1步 material_input,后续第2-5步需要调用 /projects/{project_id}/steps/{step_id}/... 系列接口手动推进。" + "素材视频来自片段 segment_video_url,不允许前端传入或后续修改。" + ), ) async def create_replication_project_from_segment( - segment_id: str = Path(...), - req: ShotSegmentReplicationCreateRequest = Body(...), + segment_id: str = Path(..., description="拆镜片段ID,即 shot_replicate_segments.id"), + req: ShotSegmentReplicationCreateRequest = Body(..., description="从拆镜片段创建复刻项目参数:生成项目名称、核心内容点、新产品图片和可选幂等键"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): @@ -450,9 +496,10 @@ async def create_replication_project_from_segment( "/projects/{project_id}", response_model=ShotReplicateTaskDetailOut, summary="获取拆镜复刻项目详情", + description="获取拆镜复刻 ModuleGenerationProject 项目详情,聚合返回素材、图片提词、图片生成、视频提词、视频生成和当前有效步骤列表。", ) async def get_project( - project_id: str = Path(...), + project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): @@ -463,10 +510,15 @@ async def get_project( "/projects/{project_id}/material", response_model=ShotReplicateActionOut, summary="修改拆镜复刻素材信息,素材视频不允许修改", + description=( + "修改拆镜复刻第1步素材输入,并重建第1步 material_input 新版本。" + "素材视频 material_video_url 锁定为拆镜片段视频,不允许修改;可修改新产品图片、参考素材项目名、生成项目名和核心内容点。" + "修改后会软删除第2、3、4、5步当前有效任务,并清空旧图片/视频结果。" + ), ) async def update_material( - project_id: str = Path(...), - req: ShotReplicateMaterialUpdateRequest = Body(...), + project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"), + req: ShotReplicateMaterialUpdateRequest = Body(..., description="第1步素材输入修改参数;不接收 material_video_url,至少传一个允许修改字段"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): @@ -486,12 +538,13 @@ async def update_material( @router.put( "/projects/{project_id}/steps/{step_id}/image-prompt", response_model=ShotReplicateActionOut, - summary="直接修改图片 AI 优化提词", + summary="直接修改第2步图片 AI 优化提词", + description="直接修改第2步 image_prompt_optimize 的图片提示词,不调用 AI、不扣积分;保存后软删除第3、4、5步当前有效任务。", ) async def update_image_prompt( - project_id: str = Path(...), - step_id: str = Path(...), - req: ShotReplicateImagePromptUpdateRequest = Body(...), + project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"), + step_id: str = Path(..., description="第2步图片 AI 提词子任务ID,即 module_generation_steps.id,step_code=image_prompt_optimize"), + req: ShotReplicateImagePromptUpdateRequest = Body(..., description="图片 AI 优化提词修改参数"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): @@ -512,12 +565,16 @@ async def update_image_prompt( @router.put( "/projects/{project_id}/steps/{step_id}/video-prompt-schema", response_model=ShotReplicateActionOut, - summary="修改视频 AI 提词 JSON schema", + summary="修改第4步视频 AI 提词 JSON schema", + description=( + "修改第4步 video_prompt_optimize 的视频提词 JSON schema,不调用 AI、不扣积分。" + "服务端会锁定视频时长、比例、分辨率、帧率、动态时间规划等关键结构;保存后软删除第5步视频生成任务。" + ), ) async def update_video_prompt_schema( - project_id: str = Path(...), - step_id: str = Path(...), - req: ShotReplicateVideoPromptSchemaUpdateRequest = Body(...), + project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"), + step_id: str = Path(..., description="第4步视频 AI 提词子任务ID,即 module_generation_steps.id,step_code=video_prompt_optimize"), + req: ShotReplicateVideoPromptSchemaUpdateRequest = Body(..., description="视频 AI 提词 JSON schema 修改参数"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): @@ -536,19 +593,24 @@ async def update_video_prompt_schema( @router.post( - "/projects/{project_id}/generate-image-prompt", + "/projects/{project_id}/steps/{step_id}/generate-image-prompt", response_model=ShotReplicateActionOut, - summary="生成图片 AI 提词", + summary="基于第1步素材输入生成图片 AI 提词", + description=( + "基于第1步 material_input 子任务手动生成第2步 image_prompt_optimize。" + "如果已存在旧的第2、3、4、5步,会先软删除旧步骤,再创建新的第2步并投递 Celery 文本提词任务。" + ), ) async def generate_image_prompt( - project_id: str = Path(...), - req: ShotReplicateGenerateImagePromptRequest = Body(default_factory=ShotReplicateGenerateImagePromptRequest), + project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"), + step_id: str = Path(..., description="第1步素材输入子任务ID,即 module_generation_steps.id,step_code=material_input"), + req: ShotReplicateGenerateImagePromptRequest = Body(default_factory=ShotReplicateGenerateImagePromptRequest, description="图片提词生成参数,当前无需传参,额外字段会忽略"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): - _ensure_celery_enabled(current_user=current_user, project_id=locals().get("project_id") or locals().get("task_set_id")) + _ensure_celery_enabled(current_user=current_user, project_id=project_id, step_id=step_id) try: - project, step = await submit_image_prompt_optimize(db, current_user=current_user, project_id=project_id, req=req) + project, step = await submit_image_prompt_optimize(db, current_user=current_user, project_id=project_id, material_step_id=step_id, req=req) project_id_value, step_id_value = project.id, step.id await db.commit() except HTTPException: @@ -577,19 +639,25 @@ async def generate_image_prompt( @router.post( - "/projects/{project_id}/generate-image", + "/projects/{project_id}/steps/{step_id}/generate-image", response_model=ShotReplicateActionOut, - summary="根据图片 AI 提词生成图片", + summary="基于第2步图片 AI 提词生成图片", + description=( + "基于第2步 image_prompt_optimize 子任务生成第3步 image_generate。" + "请求体传入图片引擎和图片参数;ChatGenerationTask 幂等键由后端自动生成。" + "如果已存在旧的第3、4、5步,会先软删除旧步骤,再创建新的第3步。" + ), ) async def generate_image( - project_id: str = Path(...), - req: ShotReplicateGenerateImageRequest = Body(...), + project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"), + step_id: str = Path(..., description="第2步图片 AI 提词子任务ID,即 module_generation_steps.id,step_code=image_prompt_optimize"), + req: ShotReplicateGenerateImageRequest = Body(..., description="图片生成引擎和参数;可选值来自图片引擎配置接口"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): - _ensure_celery_enabled(current_user=current_user, project_id=locals().get("project_id") or locals().get("task_set_id")) + _ensure_celery_enabled(current_user=current_user, project_id=project_id, step_id=step_id) try: - project, step, chat_task = await generate_image_from_prompt(db, current_user=current_user, project_id=project_id, req=req) + project, step, chat_task = await generate_image_from_prompt(db, current_user=current_user, project_id=project_id, prompt_step_id=step_id, req=req) project_id_value, step_id_value, chat_task_id_value = project.id, step.id, chat_task.id await db.commit() except HTTPException: @@ -611,19 +679,25 @@ async def generate_image( @router.post( - "/projects/{project_id}/generate-video-prompt", + "/projects/{project_id}/steps/{step_id}/generate-video-prompt", response_model=ShotReplicateActionOut, - summary="生成视频 AI 提词 JSON schema", + summary="基于第3步图片结果生成视频 AI 提词 JSON schema", + description=( + "基于第3步 image_generate 子任务生成第4步 video_prompt_optimize。" + "视频时长、比例、分辨率在本步骤确定并写入第4步 output_json;第5步视频生成只选择视频引擎。" + "如果已存在旧的第4、5步,会先软删除旧步骤,再创建新的第4步并投递 Celery 文本提词任务。" + ), ) async def generate_video_prompt( - project_id: str = Path(...), - req: ShotReplicateGenerateVideoPromptRequest = Body(...), + project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"), + step_id: str = Path(..., description="第3步图片生成子任务ID,即 module_generation_steps.id,step_code=image_generate"), + req: ShotReplicateGenerateVideoPromptRequest = Body(..., description="视频提词生成参数:视频引擎、时长、比例、分辨率和目标平台;可选值来自视频引擎配置接口"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): - _ensure_celery_enabled(current_user=current_user, project_id=locals().get("project_id") or locals().get("task_set_id")) + _ensure_celery_enabled(current_user=current_user, project_id=project_id, step_id=step_id) try: - project, step = await submit_video_prompt_optimize(db, current_user=current_user, project_id=project_id, req=req) + project, step = await submit_video_prompt_optimize(db, current_user=current_user, project_id=project_id, image_step_id=step_id, req=req) project_id_value, step_id_value = project.id, step.id await db.commit() except HTTPException: @@ -652,19 +726,25 @@ async def generate_video_prompt( @router.post( - "/projects/{project_id}/generate-video", + "/projects/{project_id}/steps/{step_id}/generate-video", response_model=ShotReplicateActionOut, - summary="根据视频 AI 提词生成视频", + summary="基于第4步视频 AI 提词生成最终视频", + description=( + "基于第4步 video_prompt_optimize 子任务生成第5步 video_generate。" + "请求体只需要选择视频生成引擎 engine_id;duration、aspect_ratio、resolution 从第4步视频提词结果继承。" + "如果已存在旧的第5步,会先软删除旧步骤,再创建新的第5步。" + ), ) async def generate_video( - project_id: str = Path(...), - req: ShotReplicateGenerateVideoRequest = Body(...), + project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"), + step_id: str = Path(..., description="第4步视频 AI 提词子任务ID,即 module_generation_steps.id,step_code=video_prompt_optimize"), + req: ShotReplicateGenerateVideoRequest = Body(..., description="视频生成参数:只传 engine_id,其它视频参数继承第4步视频提词结果"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): - _ensure_celery_enabled(current_user=current_user, project_id=locals().get("project_id") or locals().get("task_set_id")) + _ensure_celery_enabled(current_user=current_user, project_id=project_id, step_id=step_id) try: - project, step, chat_task = await generate_video_from_prompt(db, current_user=current_user, project_id=project_id, req=req) + project, step, chat_task = await generate_video_from_prompt(db, current_user=current_user, project_id=project_id, prompt_step_id=step_id, req=req) project_id_value, step_id_value, chat_task_id_value = project.id, step.id, chat_task.id await db.commit() except HTTPException: @@ -689,9 +769,10 @@ async def generate_video( "/projects/{project_id}", response_model=ShotReplicateDeleteOut, summary="软删除拆镜复刻项目", + description="软删除拆镜复刻 ModuleGenerationProject,并联动软删除当前有效步骤和关联的 ChatGenerationTask。", ) async def delete_project( - project_id: str = Path(...), + project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): diff --git a/video-gen-api/app/api/v1/sms.py b/video-gen-api/app/api/v1/sms.py index e842ed4f..7f48628c 100644 --- a/video-gen-api/app/api/v1/sms.py +++ b/video-gen-api/app/api/v1/sms.py @@ -123,7 +123,7 @@ async def send_sms_code( description="校验指定手机号、场景下的短信验证码。业务接口一般会内部校验,本接口主要用于前端调试或单独校验。", ) async def verify_sms(req: SmsVerifyRequest): - ok = await verify_sms_code(req.phone, req.code, req.scene.value) + ok = await verify_sms_code(req.phone.strip(), req.code.strip(), req.scene.value) if not ok: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, diff --git a/video-gen-api/app/api/v1/user_oauth.py b/video-gen-api/app/api/v1/user_oauth.py index 72aa50f0..1bcca525 100644 --- a/video-gen-api/app/api/v1/user_oauth.py +++ b/video-gen-api/app/api/v1/user_oauth.py @@ -6,13 +6,12 @@ from app.dependencies import get_current_user, get_db from app.models.user import User from app.models.user_oauth import UserOAuth from app.models.user_oauth_app import UserOAuthApp -from app.schemas.user_oauth import RequestOAuthRequest, RequestOAuthResponse, UserOAuthOut +from app.schemas.user_oauth import RequestOAuthRequest, RequestOAuthResponse, UserOAuthOut, OAuthListResponse from app.services.user_oauth_service import ( build_oauth_url, get_token, get_oauth_list, ) -from app.tasks.user_oauth_tasks import _update_oauth_accounts router = APIRouter(prefix="/user-oauth", tags=["oauth"]) @@ -108,6 +107,7 @@ async def juliang_callback( "/oauth_list", summary="获取账户下所有授权列表", description="获取当前用户下所有授权账户列表,支持按授权登录账号、开户方式、授权账户id筛选", + response_model=OAuthListResponse, ) async def oauth_list( account_userid: str | None = Query(None, description="授权登录账号id"), diff --git a/video-gen-api/app/main.py b/video-gen-api/app/main.py index e77caf37..5c12c3a5 100644 --- a/video-gen-api/app/main.py +++ b/video-gen-api/app/main.py @@ -560,6 +560,150 @@ def create_app() -> FastAPI: async def health(): return {"status": "ok"} + @application.get("/internal/status", response_class=HTMLResponse) + async def status_page(): + from app.tasks.celery_app import celery_app + from app.config import settings + + celery_status = "unknown" + celery_error = "" + redis_status = "unknown" + redis_error = "" + + try: + if celery_app: + inspect = celery_app.control.inspect() + try: + workers = inspect.stats() + if workers: + celery_status = "running" + else: + celery_status = "no_workers" + except Exception as e: + celery_status = "error" + celery_error = str(e) + else: + celery_status = "disabled" + except Exception as e: + celery_status = "error" + celery_error = str(e) + + try: + if settings.REDIS_URL: + import redis + r = redis.from_url(settings.REDIS_URL) + r.ping() + redis_status = "connected" + else: + redis_status = "disabled" + except Exception as e: + redis_status = "disconnected" + redis_error = str(e) + + def get_celery_text(status): + if status == 'running': + return '运行中' + elif status == 'no_workers': + return '无可用 Worker' + elif status == 'disabled': + return '已禁用' + elif status == 'error': + return '连接失败' + else: + return '未知' + + def get_redis_text(status): + if status == 'connected': + return '已连接' + elif status == 'disabled': + return '已禁用' + elif status == 'disconnected': + return '未连接' + else: + return '未知' + + celery_text = get_celery_text(celery_status) + redis_text = get_redis_text(redis_status) + + celery_error_html = f'
错误: {celery_error}
' if celery_error else '' + redis_error_html = f'
错误: {redis_error}
' if redis_error else '' + + html_content = f""" + + + + 服务状态监控 + + + +

服务状态.

+

版本 v{settings.APP_VERSION}

+ +
+

Celery 任务队列

+
+
+ {celery_text} +
+ {celery_error_html} +
+ 说明: Celery 用于异步处理 AI 生成任务、轮询任务和下载任务。如果显示"无可用 Worker",请启动 Celery worker。 +
+
+ +
+

Redis 缓存

+
+
+ {redis_text} +
+ {redis_error_html} +
+ 说明: Redis 用于 Celery 消息队列、任务状态存储和缓存。 +
+
+ +
+

数据库连接

+
+
+ 已连接 +
+
+ 说明: PostgreSQL 数据库已连接。 +
+
+ + ← 返回首页 + +""" + return HTMLResponse(content=html_content) + @application.get("/internal/decrypt-data", response_class=HTMLResponse) async def decrypt_data_page(): html_content = """ @@ -701,7 +845,7 @@ a:hover{text-decoration:underline}

API 文档

Swagger UI 交互式文档

ReDoc

ReDoc 格式文档

-

健康检查

服务状态

+

服务状态

Celery/Redis 监控

解密数据

数据解密

""" diff --git a/video-gen-api/app/schemas/admin.py b/video-gen-api/app/schemas/admin.py index 6299a9ed..f454475d 100644 --- a/video-gen-api/app/schemas/admin.py +++ b/video-gen-api/app/schemas/admin.py @@ -29,7 +29,7 @@ class ModelConfigOut(ModelConfigCreate): class SystemConfigUpdate(BaseModel): - value: str + value: str | int | float class SystemConfigOut(BaseModel): diff --git a/video-gen-api/app/schemas/hot_opening_replicate.py b/video-gen-api/app/schemas/hot_opening_replicate.py index de85b793..8fd6d522 100644 --- a/video-gen-api/app/schemas/hot_opening_replicate.py +++ b/video-gen-api/app/schemas/hot_opening_replicate.py @@ -329,9 +329,9 @@ class HotOpeningGenerateImageRequest(BaseModel): ) engine_id: str | None = Field(None, description="图片生成引擎ID。为空则使用当前启用且优先级最高的图片引擎") - image_size: str | None = Field(None, description="图片分辨率档位,例如 1K、2K。为空使用引擎默认值") - image_proportion: str | None = Field(None, description="图片比例,例如 1:1、16:9、9:16。为空使用默认值") - image_px: str | None = Field(None, description="图片像素尺寸,例如 2048x2048。为空时按引擎支持尺寸自动匹配") + image_size: str | None = Field(None, description="图片分辨率档位,例如 1K、2K。具体可选值来自图片引擎配置接口;为空使用引擎默认值") + image_proportion: str | None = Field(None, description="图片比例,例如 1:1、16:9、9:16。具体可选值来自图片引擎配置接口;为空使用默认值") + image_px: str | None = Field(None, description="图片像素尺寸,例如 1024x1024、2048x2048。具体可选值来自图片引擎配置接口;为空时按引擎支持尺寸自动匹配") class HotOpeningGenerateVideoPromptRequest(BaseModel): @@ -346,9 +346,9 @@ class HotOpeningGenerateVideoPromptRequest(BaseModel): ) engine_id: str | None = Field(None, description="视频引擎ID。用于读取该引擎支持的视频时长、比例、分辨率配置;为空使用最高优先级启用引擎") - duration: int | None = Field(None, ge=1, description="希望用于视频提词规划的视频时长,单位秒。为空时优先使用 HOT_OPENING_DEFAULT_VIDEO_DURATION") - aspect_ratio: str | None = Field(None, description="希望用于视频提词规划的视频比例。为空时优先使用 HOT_OPENING_DEFAULT_VIDEO_RATIO") - resolution: str | None = Field(None, description="希望用于视频提词规划的视频分辨率。为空时优先使用 HOT_OPENING_DEFAULT_VIDEO_RESOLUTION") + duration: int | None = Field(None, ge=1, description="希望用于视频提词规划的视频时长,单位秒。具体可选值来自视频引擎 supported_durations;为空时优先使用 HOT_OPENING_DEFAULT_VIDEO_DURATION") + aspect_ratio: str | None = Field(None, description="希望用于视频提词规划的视频比例,例如 9:16、16:9、1:1。具体可选值来自视频引擎 supported_ratios;为空时优先使用 HOT_OPENING_DEFAULT_VIDEO_RATIO") + resolution: str | None = Field(None, description="希望用于视频提词规划的视频分辨率,例如 480p、720p、1080p。具体可选值来自视频引擎 supported_resolutions;为空时优先使用 HOT_OPENING_DEFAULT_VIDEO_RESOLUTION") target_platform: str | None = Field(None, max_length=64, description="目标平台,例如抖音/快手/小红书。为空时使用 HOT_OPENING_DEFAULT_TARGET_PLATFORM") @@ -370,7 +370,7 @@ class HotOpeningStepOut(BaseModel): module: str = Field(..., description="模块标识,例如 hot_opening_replicate") step_index: int = Field(..., description="步骤序号:1素材输入、2图片提词、3图片生成、4视频提词、5视频生成") step_code: str = Field(..., description="步骤编码:material_input/image_prompt_optimize/image_generate/video_prompt_optimize/video_generate") - status: str = Field(..., description="步骤状态:pending/waiting_user/processing/completed/failed/cancelled") + status: str = Field(..., description="步骤状态:pending=待处理,waiting_user=等待用户操作,processing=处理中,completed=完成,failed=失败,cancelled=取消") version: int = Field(..., description="步骤版本号。重新生成或修改上游步骤后 version+1") is_current: bool = Field(..., description="是否当前有效步骤。旧步骤会软删除且 is_current=false") parent_step_id: str | None = Field(None, description="上一个步骤ID") @@ -425,9 +425,11 @@ class HotOpeningVideoGenerationOut(BaseModel): class HotOpeningTaskDetailOut(BaseModel): id: str = Field(..., description="总任务项目ID。这个ID就是前端项目ID") project_id: str = Field(..., description="兼容前端命名,等同于 id") + user_id: str | None = Field(None, description="所属用户ID;管理员后台排查使用") + user_name: str | None = Field(None, description="所属用户名;管理员后台排查使用") module: str = Field(..., description="模块标识,爆款开头复刻固定为 hot_opening_replicate") title: str | None = Field(None, description="项目标题,默认取生成项目名称") - status: str = Field(..., description="总任务状态:pending/waiting_user/processing/completed/failed/cancelled") + status: str = Field(..., description="总任务状态:pending=已创建,waiting_user=等待用户操作,processing=处理中,completed=完成,failed=失败,cancelled=取消") current_step_code: str | None = Field(None, description="当前所处步骤编码") final_image_url: str | None = Field(None, description="最终新项目图片 URL") final_video_url: str | None = Field(None, description="最终视频 URL") @@ -445,11 +447,15 @@ class HotOpeningTaskDetailOut(BaseModel): class HotOpeningTaskListItemOut(BaseModel): id: str = Field(..., description="总任务项目ID。这个ID就是前端项目ID") project_id: str = Field(..., description="兼容前端命名,等同于 id") + user_id: str | None = Field(None, description="所属用户ID;管理员后台排查使用") + user_name: str | None = Field(None, description="所属用户名;管理员后台排查使用") module: str = Field(..., description="模块标识") title: str | None = Field(None, description="项目标题") - status: str = Field(..., description="总任务状态") + status: str = Field(..., description="总任务状态:pending=已创建,waiting_user=等待用户操作,processing=处理中,completed=完成,failed=失败,cancelled=取消") current_step_code: str | None = Field(None, description="当前步骤") + source_project_name: str | None = Field(None, description="视频素材内容项目名称,来源于第1步素材输入") target_project_name: str | None = Field(None, description="生成项目名称,来源于第1步素材输入") + core_content_point: str | None = Field(None, description="核心内容点,来源于第1步素材输入") final_image_url: str | None = Field(None, description="最终图片 URL") final_video_url: str | None = Field(None, description="最终视频 URL") final_video_cover_url: str | None = Field(None, description="最终视频封面 URL") diff --git a/video-gen-api/app/schemas/pre_test_template.py b/video-gen-api/app/schemas/pre_test_template.py new file mode 100644 index 00000000..c2037fe7 --- /dev/null +++ b/video-gen-api/app/schemas/pre_test_template.py @@ -0,0 +1,111 @@ +from datetime import datetime +from typing import List, Optional + +from pydantic import BaseModel, Field, field_validator + + +class PreTestTemplateCreate(BaseModel): + name: str = Field(..., description="模板名称") + note: Optional[str] = Field(None, description="模板备注") + platform: Optional[str] = Field(None, description="投放平台(AD/QIANCHUAN/LOCAL)") + external_action: Optional[str] = Field(None, description="转化目标") + cpa_bid: Optional[float] = Field(None, description="目标转化成本:[1, 10000]") + audience_gender: Optional[str] = Field(None, description="性别(ALL/MALE/FEMALE)") + audience_age: Optional[List[str]] = Field(None, description="受众年龄列表") + audience_region: Optional[List[int]] = Field(None, description="受众地区code列表") + audience_network: Optional[List[str]] = Field(None, description="网络类型列表") + cus_name: Optional[str] = Field(None, description="客户主体名称") + pricing_type: Optional[str] = Field(None, description="出价类型(OCPC/CPA/OCPM)") + cost_cap: Optional[bool] = Field(None, description="是否最优成本出价(仅AD支持)") + target_cost: Optional[bool] = Field(None, description="是否稳定成本出价(仅AD支持)") + nobid: Optional[bool] = Field(None, description="是否最大转化出价(仅AD支持)") + cpc_bid: Optional[float] = Field(None, description="目标点击成本:[1, 10000]") + budget: Optional[float] = Field(None, description="预算金额:[1, 10000]") + is_default: Optional[bool] = Field(None, description="是否设为默认模板") + + @field_validator('platform') + def validate_platform(cls, v): + if v is None: + return v + allowed = ["AD", "QIANCHUAN", "LOCAL"] + if v not in allowed: + raise ValueError(f"platform must be one of {allowed}") + return v + + @field_validator('pricing_type') + def validate_pricing_type(cls, v): + if v is None: + return v + allowed = ["OCPC", "CPA", "OCPM"] + if v not in allowed: + raise ValueError(f"pricing_type must be one of {allowed}") + return v + + @field_validator('audience_gender') + def validate_gender(cls, v): + if v is None: + return v + allowed = ["ALL", "MALE", "FEMALE"] + if v not in allowed: + raise ValueError(f"audience_gender must be one of {allowed}") + return v + + +class PreTestTemplateUpdate(BaseModel): + name: Optional[str] = Field(None, description="模板名称") + note: Optional[str] = Field(None, description="模板备注") + platform: Optional[str] = Field(None, description="投放平台") + external_action: Optional[str] = Field(None, description="转化目标") + cpa_bid: Optional[float] = Field(None, description="目标转化成本") + audience_gender: Optional[str] = Field(None, description="性别") + audience_age: Optional[List[str]] = Field(None, description="受众年龄列表") + audience_region: Optional[List[int]] = Field(None, description="受众地区code列表") + audience_network: Optional[List[str]] = Field(None, description="网络类型列表") + cus_name: Optional[str] = Field(None, description="客户主体名称") + pricing_type: Optional[str] = Field(None, description="出价类型") + cost_cap: Optional[bool] = Field(None, description="是否最优成本出价") + target_cost: Optional[bool] = Field(None, description="是否稳定成本出价") + nobid: Optional[bool] = Field(None, description="是否最大转化出价") + cpc_bid: Optional[float] = Field(None, description="目标点击成本") + budget: Optional[float] = Field(None, description="预算金额") + is_default: Optional[bool] = Field(None, description="是否设为默认模板") + + +class PreTestTemplateOut(BaseModel): + id: str = Field(..., description="主键") + name: str = Field(..., description="模板名称") + note: Optional[str] = Field(None, description="模板备注") + platform: Optional[str] = Field(None, description="投放平台") + external_action: Optional[str] = Field(None, description="转化目标") + cpa_bid: Optional[float] = Field(None, description="目标转化成本") + audience_gender: Optional[str] = Field(None, description="性别") + audience_age: Optional[List[str]] = Field(None, description="受众年龄列表") + audience_region: Optional[List[int]] = Field(None, description="受众地区code列表") + audience_network: Optional[List[str]] = Field(None, description="网络类型列表") + cus_name: Optional[str] = Field(None, description="客户主体名称") + pricing_type: Optional[str] = Field(None, description="出价类型") + cost_cap: Optional[bool] = Field(None, description="是否最优成本出价") + target_cost: Optional[bool] = Field(None, description="是否稳定成本出价") + nobid: Optional[bool] = Field(None, description="是否最大转化出价") + cpc_bid: Optional[float] = Field(None, description="目标点击成本") + budget: Optional[float] = Field(None, description="预算金额") + is_default: Optional[bool] = Field(None, description="是否默认模板") + user_id: str = Field(..., description="用户id") + created_at: datetime = Field(..., description="创建时间") + updated_at: datetime = Field(..., description="更新时间") + + model_config = {"from_attributes": True} + + +class PaginationInfo(BaseModel): + page: int = Field(..., description="当前页码") + page_size: int = Field(..., description="每页数量") + total: int = Field(..., description="总记录数") + total_pages: int = Field(..., description="总页数") + + +class PreTestTemplateListResponse(BaseModel): + code: int = Field(0, description="返回码") + message: str = Field("查询成功", description="返回消息") + data: List[PreTestTemplateOut] = Field(..., description="模板列表") + pagination: PaginationInfo = Field(..., description="分页信息") diff --git a/video-gen-api/app/schemas/shot_replicate.py b/video-gen-api/app/schemas/shot_replicate.py index a018d673..dbd38fe6 100644 --- a/video-gen-api/app/schemas/shot_replicate.py +++ b/video-gen-api/app/schemas/shot_replicate.py @@ -208,27 +208,30 @@ class ShotReplicateTaskCreate(BaseModel): class ShotReplicateMaterialUpdateRequest(BaseModel): - """修改拆镜复刻第1步素材输入请求体。""" + """修改拆镜复刻第1步素材输入请求体。 + + 拆镜复刻的素材视频来自拆镜片段 segment_video_url,与片段强绑定,不允许修改。 + 本接口只允许修改新产品图片、参考素材项目名、生成项目名和核心内容点。 + """ model_config = ConfigDict( + extra="forbid", json_schema_extra={ "example": { - "material_video_url": "https://example.com/new-source.mp4", "material_image_url": "https://example.com/new-product.png", "source_project_name": "新的参考素材项目名称", "target_project_name": "新的生成项目名称", "core_content_point": "新的50字以内核心内容点", } - } + }, ) - material_video_url: str | None = Field(None, min_length=1, description="素材视频链接,未传则沿用旧值") - material_image_url: str | None = Field(None, min_length=1, description="素材图片链接,未传则沿用旧值") + material_image_url: str | None = Field(None, min_length=1, description="素材图片链接,未传则沿用旧值。用于新产品/目标素材图片,来自已有上传接口") source_project_name: str | None = Field(None, min_length=1, max_length=20, description="视频素材内容项目名称,未传则沿用旧值") target_project_name: str | None = Field(None, min_length=1, max_length=20, description="生成项目名称,未传则沿用旧值") core_content_point: str | None = Field(None, min_length=1, max_length=50, description="生成项目核心内容点,最多50字,未传则沿用旧值") - @field_validator("material_video_url", "material_image_url", "source_project_name", "target_project_name", "core_content_point", mode="before") + @field_validator("material_image_url", "source_project_name", "target_project_name", "core_content_point", mode="before") @classmethod def _strip_optional(cls, value: str | None) -> str | None: if value is None: @@ -240,7 +243,7 @@ class ShotReplicateMaterialUpdateRequest(BaseModel): @model_validator(mode="after") def _require_at_least_one(self) -> "ShotReplicateMaterialUpdateRequest": - if not any(getattr(self, field) is not None for field in ("material_video_url", "material_image_url", "source_project_name", "target_project_name", "core_content_point")): + if not any(getattr(self, field) is not None for field in ("material_image_url", "source_project_name", "target_project_name", "core_content_point")): raise ValueError("至少需要传入一个需要修改的字段") return self @@ -248,7 +251,7 @@ class ShotReplicateMaterialUpdateRequest(BaseModel): class ShotReplicateStepUpdate(BaseModel): """修改拆镜复刻子任务请求体。""" - material_video_url: str | None = Field(None, description="修改第1步素材视频链接") + material_video_url: str | None = Field(None, description="历史兼容字段:拆镜复刻项目素材视频与片段绑定,正式接口不允许修改") material_image_url: str | None = Field(None, description="修改第1步素材图片链接") source_project_name: str | None = Field(None, max_length=20, description="修改第1步视频素材内容项目名称") target_project_name: str | None = Field(None, max_length=20, description="修改第1步生成项目名称") @@ -329,9 +332,9 @@ class ShotReplicateGenerateImageRequest(BaseModel): ) engine_id: str | None = Field(None, description="图片生成引擎ID。为空则使用当前启用且优先级最高的图片引擎") - image_size: str | None = Field(None, description="图片分辨率档位,例如 1K、2K。为空使用引擎默认值") - image_proportion: str | None = Field(None, description="图片比例,例如 1:1、16:9、9:16。为空使用默认值") - image_px: str | None = Field(None, description="图片像素尺寸,例如 2048x2048。为空时按引擎支持尺寸自动匹配") + image_size: str | None = Field(None, description="图片分辨率档位,例如 1K、2K。具体可选值来自图片引擎配置接口;为空使用引擎默认值") + image_proportion: str | None = Field(None, description="图片比例,例如 1:1、16:9、9:16。具体可选值来自图片引擎配置接口;为空使用默认值") + image_px: str | None = Field(None, description="图片像素尺寸,例如 1024x1024、2048x2048。具体可选值来自图片引擎配置接口;为空时按引擎支持尺寸自动匹配") class ShotReplicateGenerateVideoPromptRequest(BaseModel): @@ -346,9 +349,9 @@ class ShotReplicateGenerateVideoPromptRequest(BaseModel): ) engine_id: str | None = Field(None, description="视频引擎ID。用于读取该引擎支持的视频时长、比例、分辨率配置;为空使用最高优先级启用引擎") - duration: int | None = Field(None, ge=1, description="希望用于视频提词规划的视频时长,单位秒。为空时优先使用 SHOT_REPLICATE_DEFAULT_VIDEO_DURATION") - aspect_ratio: str | None = Field(None, description="希望用于视频提词规划的视频比例。为空时优先使用 SHOT_REPLICATE_DEFAULT_VIDEO_RATIO") - resolution: str | None = Field(None, description="希望用于视频提词规划的视频分辨率。为空时优先使用 SHOT_REPLICATE_DEFAULT_VIDEO_RESOLUTION") + duration: int | None = Field(None, ge=1, description="希望用于视频提词规划的视频时长,单位秒。具体可选值来自视频引擎 supported_durations;为空时优先使用 SHOT_REPLICATE_DEFAULT_VIDEO_DURATION") + aspect_ratio: str | None = Field(None, description="希望用于视频提词规划的视频比例,例如 9:16、16:9、1:1。具体可选值来自视频引擎 supported_ratios;为空时优先使用 SHOT_REPLICATE_DEFAULT_VIDEO_RATIO") + resolution: str | None = Field(None, description="希望用于视频提词规划的视频分辨率,例如 480p、720p、1080p。具体可选值来自视频引擎 supported_resolutions;为空时优先使用 SHOT_REPLICATE_DEFAULT_VIDEO_RESOLUTION") target_platform: str | None = Field(None, max_length=64, description="目标平台,例如抖音/快手/小红书。为空时使用 SHOT_REPLICATE_DEFAULT_TARGET_PLATFORM") @@ -425,6 +428,8 @@ class ShotReplicateVideoGenerationOut(BaseModel): class ShotReplicateTaskDetailOut(BaseModel): id: str = Field(..., description="总任务项目ID。这个ID就是前端项目ID") project_id: str = Field(..., description="兼容前端命名,等同于 id") + user_id: str | None = Field(None, description="所属用户ID;管理员后台排查使用") + user_name: str | None = Field(None, description="所属用户名;管理员后台排查使用") module: str = Field(..., description="模块标识,拆镜复刻固定为 shot_replicate") title: str | None = Field(None, description="项目标题,默认取生成项目名称") status: str = Field(..., description="总任务状态:pending/waiting_user/processing/completed/failed/cancelled") @@ -477,13 +482,6 @@ class ShotReplicateDeleteOut(BaseModel): deleted: bool = Field(..., description="是否已软删除") -class ShotReplicateSpecOut(BaseModel): - project_statuses: dict[str, str] = Field(default_factory=lambda: SHOT_REPLICATE_PROJECT_STATUS_DESCRIPTIONS, description="总任务状态说明") - step_statuses: dict[str, str] = Field(default_factory=lambda: SHOT_REPLICATE_STEP_STATUS_DESCRIPTIONS, description="子任务状态说明") - steps: list[dict[str, Any]] = Field(default_factory=lambda: SHOT_REPLICATE_STEP_DESCRIPTIONS, description="5个固定步骤说明") - step_io_schema_version: str = Field(default=SHOT_REPLICATE_STEP_IO_SCHEMA_VERSION, description="步骤 input_json/output_json 结构版本") - step_io_examples: dict[str, dict[str, Any]] = Field(default_factory=lambda: SHOT_REPLICATE_STEP_IO_EXAMPLES, description="每个步骤 input_json/output_json 示例") - # ======================== # 拆镜总任务集 / 片段 API Schema @@ -579,10 +577,14 @@ class ShotTaskSetCreate(BaseModel): class ShotTaskSetListQuery(BaseModel): - status: str | None = Field(None, description="总任务状态筛选,见 ShotTaskSetStatusEnum") - analysis_status: str | None = Field(None, description="分析状态筛选,见 ShotAnalysisStatusEnum") - split_status: str | None = Field(None, description="拆镜状态筛选,见 ShotSplitStatusEnum") - keyword: str | None = Field(None, description="标题/内容关键词") + status: str | None = Field(None, description="总任务状态筛选:pending_analysis/analyzing/analysis_completed/analysis_failed/splitting/split_completed/partial_failed/failed/deleted") + analysis_status: str | None = Field(None, description="分析状态筛选:pending/processing/completed/failed") + split_status: str | None = Field(None, description="拆镜状态筛选:none/pending/processing/completed/failed/retry_waiting") + keyword: str | None = Field(None, description="标题/内容关键词,模糊搜索") + user_id: str | None = Field(None, description="管理员专用:用户ID筛选") + user_name: str | None = Field(None, description="管理员专用:用户名模糊筛选") + created_start: NaiveDatetimeOptional = Field(None, description="管理员专用:创建时间开始") + created_end: NaiveDatetimeOptional = Field(None, description="管理员专用:创建时间结束") page: int = Field(1, ge=1, description="页码") page_size: int = Field(20, ge=1, le=100, description="每页数量") @@ -590,44 +592,46 @@ class ShotTaskSetListQuery(BaseModel): class ShotTaskSetOut(BaseModel): model_config = ConfigDict(from_attributes=True) - id: str - title: str | None = None - video_url: str - video_duration_seconds: float - status: str - analysis_status: str - split_status: str - original_video_content: str | None = None - original_video_category: str | None = None - original_video_audience: str | None = None - segment_count: int = 0 - completed_segment_count: int = 0 - failed_segment_count: int = 0 - analysis_error_message: str | None = None - split_error_message: str | None = None - created_at: NaiveDatetimeOptional = None - updated_at: NaiveDatetimeOptional = None + id: str = Field(..., description="拆镜总任务集ID,即 shot_replicate_task_sets.id") + user_id: str | None = Field(None, description="所属用户ID;管理员后台排查使用") + user_name: str | None = Field(None, description="所属用户名;管理员后台排查使用") + title: str | None = Field(None, description="拆镜总任务标题,可为空") + video_url: str = Field(..., description="原视频 URL,来自已有上传接口") + video_duration_seconds: float = Field(..., description="原视频时长,单位秒,允许浮点") + status: str = Field(..., description="总任务状态:pending_analysis=等待分析,analyzing=分析中,analysis_completed=分析完成,analysis_failed=分析失败,splitting=拆镜中,split_completed=拆镜完成,partial_failed=部分失败,failed=失败,deleted=已软删") + analysis_status: str = Field(..., description="原视频分析状态:pending=待分析,processing=分析中,completed=分析完成,failed=分析失败") + split_status: str = Field(..., description="拆镜状态:none=尚未拆镜,pending=待拆镜,processing=拆镜中,completed=拆镜完成,failed=拆镜失败,retry_waiting=等待恢复重试") + original_video_content: str | None = Field(None, description="AI 分析出的原视频整体内容描述") + original_video_category: str | None = Field(None, description="AI 分析出的原视频分类,例如游戏视频、产品广告、教程等") + original_video_audience: str | None = Field(None, description="AI 分析出的原视频受众人群") + segment_count: int = Field(0, description="当前有效拆镜片段总数") + completed_segment_count: int = Field(0, description="切割完成的片段数量") + failed_segment_count: int = Field(0, description="切割失败的片段数量") + analysis_error_message: str | None = Field(None, description="原视频 AI 分析失败原因") + split_error_message: str | None = Field(None, description="总任务级拆镜失败原因") + created_at: NaiveDatetimeOptional = Field(None, description="创建时间") + updated_at: NaiveDatetimeOptional = Field(None, description="更新时间") class ShotTaskSetListOut(BaseModel): - total: int - page: int - page_size: int - items: list[ShotTaskSetOut] + total: int = Field(..., description="符合筛选条件的总任务集总数") + page: int = Field(..., description="当前页码") + page_size: int = Field(..., description="每页数量") + items: list[ShotTaskSetOut] = Field(default_factory=list, description="拆镜总任务集列表") class ShotTaskSetDetailOut(ShotTaskSetOut): - ai_suggestions: list[ShotAISuggestionOut] = Field(default_factory=list) - analysis_result_json: dict[str, Any] | list[Any] | None = None + ai_suggestions: list[ShotAISuggestionOut] = Field(default_factory=list, description="AI 建议拆镜时间段列表,split-by-ai 接口可按 index 选择") + analysis_result_json: dict[str, Any] | list[Any] | None = Field(None, description="原视频 AI 分析完整 JSON 结果,结构由模型响应决定") class ShotSplitByAIRequest(BaseModel): - selected_indices: list[int] | None = Field(None, description="指定 AI 建议序号。不传则全部拆") - replace_existing: bool = Field(False, description="是否软删旧 AI 建议片段后重新拆") + selected_indices: list[int] | None = Field(None, description="指定 AI 建议序号列表,序号来自 ai_suggestions[].index;不传则按全部 AI 建议拆镜") + replace_existing: bool = Field(False, description="是否软删旧 AI 建议片段后重新拆;false 时保留旧片段并新增未存在片段") class ShotSplitCustomRequest(BaseModel): - start_second: float = Field(..., ge=0, description="自定义拆镜开始秒,允许浮点") + start_second: float = Field(..., ge=0, description="自定义拆镜开始秒,允许浮点,必须大于等于0") end_second: float = Field(..., gt=0, description="自定义拆镜结束秒,允许浮点,必须大于 start_second") @model_validator(mode="after") @@ -640,56 +644,59 @@ class ShotSplitCustomRequest(BaseModel): class ShotSegmentOut(BaseModel): model_config = ConfigDict(from_attributes=True) - id: str - task_set_id: str - segment_index: int - segment_name: str | None = None - source_mode: str - start_second: float - end_second: float - duration_seconds: float - time_node: str - split_status: str - analysis_status: str - replicate_status: str - segment_video_url: str | None = None - original_video_content: str | None = None - original_video_category: str | None = None - original_video_audience: str | None = None - segment_content: str | None = None - segment_category: str | None = None - segment_audience: str | None = None - split_retry_count: int = 0 - split_last_error: str | None = None - analysis_error_message: str | None = None - module_project_id: str | None = None - created_at: NaiveDatetimeOptional = None - updated_at: NaiveDatetimeOptional = None + id: str = Field(..., description="拆镜片段ID,即 shot_replicate_segments.id") + task_set_id: str = Field(..., description="所属拆镜总任务集ID,即 shot_replicate_task_sets.id") + segment_index: int = Field(..., description="片段序号,从1开始") + segment_name: str | None = Field(None, description="片段名称,可为空") + source_mode: str = Field(..., description="片段来源:ai_suggestion=AI 建议拆镜,custom=用户自定义拆镜") + start_second: float = Field(..., description="片段开始秒") + end_second: float = Field(..., description="片段结束秒") + duration_seconds: float = Field(..., description="片段时长,单位秒") + time_node: str = Field(..., description="片段时间节点展示文案,例如 0-5秒") + split_status: str = Field(..., description="切割状态:none=尚未拆镜,pending=待拆镜,processing=拆镜中,completed=拆镜完成,failed=拆镜失败,retry_waiting=等待恢复重试") + analysis_status: str = Field(..., description="片段分析状态:not_required=无需单独分析,pending=等待分析,processing=分析中,completed=分析完成,failed=分析失败") + replicate_status: str = Field(..., description="片段复刻状态:not_started=未复刻,project_created=已创建复刻项目,processing=复刻处理中,completed=复刻完成,failed=复刻失败") + segment_video_url: str | None = Field(None, description="切割后的片段视频 URL。切割完成后有值,用作复刻项目锁定素材视频") + original_video_content: str | None = Field(None, description="原视频整体内容描述,来自总任务 AI 分析") + original_video_category: str | None = Field(None, description="原视频分类,来自总任务 AI 分析") + original_video_audience: str | None = Field(None, description="原视频受众,来自总任务 AI 分析") + segment_content: str | None = Field(None, description="当前片段内容描述") + segment_category: str | None = Field(None, description="当前片段分类") + segment_audience: str | None = Field(None, description="当前片段受众人群") + split_retry_count: int = Field(0, description="切割失败后的恢复重试次数") + split_last_error: str | None = Field(None, description="最近一次切割失败原因") + analysis_error_message: str | None = Field(None, description="片段分析失败原因") + module_project_id: str | None = Field(None, description="由该片段创建的拆镜复刻项目ID,即 module_generation_projects.id") + module_project_title: str | None = Field(None, description="关联拆镜复刻项目标题;后台片段列表展示使用") + module_project_status: str | None = Field(None, description="关联拆镜复刻项目状态;后台片段列表展示使用") + module_project_current_step_code: str | None = Field(None, description="关联拆镜复刻项目当前步骤;后台片段列表展示使用") + created_at: NaiveDatetimeOptional = Field(None, description="创建时间") + updated_at: NaiveDatetimeOptional = Field(None, description="更新时间") class ShotSegmentDetailOut(ShotSegmentOut): - analysis_json: dict[str, Any] | list[Any] | None = None - ai_suggestion_json: dict[str, Any] | list[Any] | None = None + analysis_json: dict[str, Any] | list[Any] | None = Field(None, description="片段 AI 分析完整 JSON,custom 片段可能有值;AI 建议片段通常复用 ai_suggestion_json") + ai_suggestion_json: dict[str, Any] | list[Any] | None = Field(None, description="AI 建议拆镜原始 JSON,source_mode=ai_suggestion 时通常有值") class ShotSegmentListOut(BaseModel): - total: int - page: int - page_size: int - items: list[ShotSegmentOut] + total: int = Field(..., description="符合筛选条件的片段总数") + page: int = Field(..., description="当前页码") + page_size: int = Field(..., description="每页数量") + items: list[ShotSegmentOut] = Field(default_factory=list, description="拆镜片段列表") class ShotSplitByAIOut(BaseModel): - task_set_id: str - status: str - split_status: str - created_segment_count: int - segments: list[ShotSegmentOut] + task_set_id: str = Field(..., description="拆镜总任务集ID") + status: str = Field(..., description="总任务状态:pending_analysis/analyzing/analysis_completed/analysis_failed/splitting/split_completed/partial_failed/failed/deleted") + split_status: str = Field(..., description="拆镜状态:none/pending/processing/completed/failed/retry_waiting") + created_segment_count: int = Field(..., description="本次创建的拆镜片段数量") + segments: list[ShotSegmentOut] = Field(default_factory=list, description="本次创建或返回的拆镜片段列表") class ShotSplitCustomOut(BaseModel): - task_set_id: str - segment: ShotSegmentOut + task_set_id: str = Field(..., description="拆镜总任务集ID") + segment: ShotSegmentOut = Field(..., description="本次创建的自定义拆镜片段") class ShotSegmentReplicationCreateRequest(BaseModel): @@ -704,10 +711,10 @@ class ShotSegmentReplicationCreateRequest(BaseModel): } ) - target_project_name: str = Field(..., min_length=1, max_length=20, description="生成项目名称") - core_content_point: str = Field(..., min_length=1, max_length=50, description="生成项目核心内容点,最多50字") - material_image_url: str = Field(..., min_length=1, description="新产品/目标素材图片链接,来自已有上传接口") - idempotency_key: str | None = Field(None, max_length=64, description="创建 ModuleGenerationProject 幂等键") + target_project_name: str = Field(..., min_length=1, max_length=20, description="生成项目名称,最多20字;会写入 module_generation_projects.title 和第1步 material_input") + core_content_point: str = Field(..., min_length=1, max_length=50, description="生成项目核心内容点,最多50字;用于后续图片 AI 提词和视频 AI 提词") + material_image_url: str = Field(..., min_length=1, description="新产品/目标素材图片链接,来自已有上传接口;作为图片生成参考素材") + idempotency_key: str | None = Field(None, max_length=64, description="创建 ModuleGenerationProject 幂等键;为空时后端可按业务生成或不使用") @field_validator("target_project_name", "core_content_point", "material_image_url", "idempotency_key", mode="before") @classmethod @@ -721,14 +728,14 @@ class ShotSegmentReplicationCreateRequest(BaseModel): class ShotReplicateSpecOut(BaseModel): - project_statuses: dict[str, str] = Field(default_factory=lambda: SHOT_REPLICATE_PROJECT_STATUS_DESCRIPTIONS) - step_statuses: dict[str, str] = Field(default_factory=lambda: SHOT_REPLICATE_STEP_STATUS_DESCRIPTIONS) - steps: list[dict[str, Any]] = Field(default_factory=lambda: SHOT_REPLICATE_STEP_DESCRIPTIONS) - step_io_schema_version: str = SHOT_REPLICATE_STEP_IO_SCHEMA_VERSION - step_io_examples: dict[str, dict[str, Any]] = Field(default_factory=lambda: SHOT_REPLICATE_STEP_IO_EXAMPLES) - task_set_statuses: dict[str, str] = Field(default_factory=lambda: SHOT_TASK_SET_STATUS_DESCRIPTIONS) - analysis_statuses: dict[str, str] = Field(default_factory=lambda: SHOT_ANALYSIS_STATUS_DESCRIPTIONS) - split_statuses: dict[str, str] = Field(default_factory=lambda: SHOT_SPLIT_STATUS_DESCRIPTIONS) - segment_source_modes: dict[str, str] = Field(default_factory=lambda: SHOT_SEGMENT_SOURCE_MODE_DESCRIPTIONS) - segment_analysis_statuses: dict[str, str] = Field(default_factory=lambda: SHOT_SEGMENT_ANALYSIS_STATUS_DESCRIPTIONS) - segment_replicate_statuses: dict[str, str] = Field(default_factory=lambda: SHOT_SEGMENT_REPLICATE_STATUS_DESCRIPTIONS) + project_statuses: dict[str, str] = Field(default_factory=lambda: SHOT_REPLICATE_PROJECT_STATUS_DESCRIPTIONS, description="ModuleGenerationProject 总任务状态说明:pending/waiting_user/processing/completed/failed/cancelled") + step_statuses: dict[str, str] = Field(default_factory=lambda: SHOT_REPLICATE_STEP_STATUS_DESCRIPTIONS, description="ModuleGenerationStep 子任务状态说明:pending/waiting_user/processing/completed/failed/cancelled") + steps: list[dict[str, Any]] = Field(default_factory=lambda: SHOT_REPLICATE_STEP_DESCRIPTIONS, description="5个固定步骤说明:material_input/image_prompt_optimize/image_generate/video_prompt_optimize/video_generate") + step_io_schema_version: str = Field(default=SHOT_REPLICATE_STEP_IO_SCHEMA_VERSION, description="步骤 input_json/output_json 结构版本") + step_io_examples: dict[str, dict[str, Any]] = Field(default_factory=lambda: SHOT_REPLICATE_STEP_IO_EXAMPLES, description="每个步骤 input_json/output_json 示例") + task_set_statuses: dict[str, str] = Field(default_factory=lambda: SHOT_TASK_SET_STATUS_DESCRIPTIONS, description="拆镜总任务集状态说明") + analysis_statuses: dict[str, str] = Field(default_factory=lambda: SHOT_ANALYSIS_STATUS_DESCRIPTIONS, description="原视频/片段视频分析状态说明") + split_statuses: dict[str, str] = Field(default_factory=lambda: SHOT_SPLIT_STATUS_DESCRIPTIONS, description="ffmpeg 拆镜状态说明") + segment_source_modes: dict[str, str] = Field(default_factory=lambda: SHOT_SEGMENT_SOURCE_MODE_DESCRIPTIONS, description="拆镜片段来源说明") + segment_analysis_statuses: dict[str, str] = Field(default_factory=lambda: SHOT_SEGMENT_ANALYSIS_STATUS_DESCRIPTIONS, description="拆镜片段分析状态说明") + segment_replicate_statuses: dict[str, str] = Field(default_factory=lambda: SHOT_SEGMENT_REPLICATE_STATUS_DESCRIPTIONS, description="拆镜片段进入复刻流程后的状态说明") diff --git a/video-gen-api/app/services/hot_opening_replicate_service.py b/video-gen-api/app/services/hot_opening_replicate_service.py index 2fbafdda..34051e1a 100644 --- a/video-gen-api/app/services/hot_opening_replicate_service.py +++ b/video-gen-api/app/services/hot_opening_replicate_service.py @@ -1,12 +1,14 @@ from __future__ import annotations import json +from copy import deepcopy from datetime import datetime, timezone from typing import Any from fastapi import HTTPException -from sqlalchemy import func, select +from sqlalchemy import String, cast, func, or_, select from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy.orm.attributes import flag_modified from app.config import settings from app.enums.common import ModuleEventTypeEnum, ModuleProjectStatusEnum, ModulePromptTypeEnum, ModuleStepStatusEnum @@ -184,6 +186,19 @@ def _merge_dict(old: dict[str, Any] | None, new: dict[str, Any] | None) -> dict[ return merged +def _force_set_json(model_obj: Any, field_name: str, value: Any) -> None: + """强制持久化 JSON / JSONB 字段。 + + SQLAlchemy 对 dict/list 的嵌套原地修改不会稳定触发 dirty 判定。 + 所有编辑类接口在写入 input_json / output_json 时统一走这里: + 1. deepcopy 断开旧引用; + 2. 整体重新赋值; + 3. flag_modified 显式标记字段已变更。 + """ + setattr(model_obj, field_name, deepcopy(value)) + flag_modified(model_obj, field_name) + + async def log_module_event( db: AsyncSession, *, @@ -486,9 +501,16 @@ async def project_to_detail_out(db: AsyncSession, project: ModuleGenerationProje video_url = video_generate_output.get("result_video_url") or (video_chat.video_url if video_chat else None) or project.final_video_url cover_url = video_generate_output.get("result_video_cover_url") or (video_chat.video_cover_url if video_chat else None) or project.final_video_cover_url + user_name: str | None = None + if project.user_id: + user_result = await db.execute(select(User.username).where(User.id == project.user_id).limit(1)) + user_name = user_result.scalar_one_or_none() + return HotOpeningTaskDetailOut( id=project.id, project_id=project.id, + user_id=project.user_id, + user_name=user_name, module=project.module, title=project.title, status=project.status, @@ -586,40 +608,141 @@ async def create_hot_opening_project(db: AsyncSession, current_user: User, req: return project +def _user_name_filter_subquery(value: str): + """后台按用户名筛选时使用的子查询。 + + 只在传入 user_name 时查询 users 表;keyword 不再关联 users,避免后台关键词搜索扩大查询范围。 + """ + like = f"%{value.strip()}%" + return select(User.id).where(User.username.ilike(like)) + + +async def _user_name_map_by_ids(db: AsyncSession, user_ids: set[str]) -> dict[str, str | None]: + """一次性查询当前页涉及的用户,避免列表逐条查询用户表。""" + if not user_ids: + return {} + result = await db.execute(select(User.id, User.username).where(User.id.in_(list(user_ids)))) + return {user_id: username for user_id, username in result.all()} + + +async def _current_step_map_by_project_ids( + db: AsyncSession, + *, + project_ids: set[str], + step_code: str, +) -> dict[str, ModuleGenerationStep]: + """一次性查询当前页项目的指定步骤,避免列表逐条查 material_input。""" + if not project_ids: + return {} + result = await db.execute( + select(ModuleGenerationStep).where( + ModuleGenerationStep.project_id.in_(list(project_ids)), + ModuleGenerationStep.step_code == step_code, + ModuleGenerationStep.is_current.is_(True), + ModuleGenerationStep.deleted_at.is_(None), + ) + ) + return {step.project_id: step for step in result.scalars().all()} + + async def list_hot_opening_projects( db: AsyncSession, *, current_user: User, status: str | None, + keyword: str | None = None, + user_id: str | None = None, + user_name: str | None = None, + created_start: datetime | None = None, + created_end: datetime | None = None, page: int, page_size: int, ) -> HotOpeningTaskListOut: + """ + 爆款开头列表查询。 + + 性能策略: + 1. 列表接口只查列表字段,不调用 project_to_detail_out,避免 steps/chat/user 多重 N+1。 + 2. 主表分页查询完成后,再按当前页 project_ids 批量查 material_input。 + 3. 管理员需要展示 user_name 时,按当前页 user_id 去重后一次性查 User。 + 4. user_name 使用 IN (SELECT users.id ...) 子查询筛选;keyword 不查询 users 表。 + """ query = select(ModuleGenerationProject).where( ModuleGenerationProject.module == MODULE, ModuleGenerationProject.deleted_at.is_(None), ) + if not current_user.is_admin: query = query.where(ModuleGenerationProject.user_id == current_user.id) + else: + if user_id and user_id.strip(): + query = query.where(ModuleGenerationProject.user_id == user_id.strip()) + if user_name and user_name.strip(): + query = query.where(ModuleGenerationProject.user_id.in_(_user_name_filter_subquery(user_name))) + if created_start: + query = query.where(ModuleGenerationProject.created_at >= created_start) + if created_end: + query = query.where(ModuleGenerationProject.created_at <= created_end) + if status: query = query.where(ModuleGenerationProject.status == status) - total = (await db.execute(select(func.count()).select_from(query.subquery()))).scalar_one() - result = await db.execute(query.order_by(ModuleGenerationProject.created_at.desc()).offset((page - 1) * page_size).limit(page_size)) - projects = list(result.scalars().all()) + if keyword and keyword.strip(): + like = f"%{keyword.strip()}%" + material_step_subquery = ( + select(ModuleGenerationStep.project_id).where( + ModuleGenerationStep.step_code == HotOpeningStepCodeEnum.MATERIAL_INPUT.value, + ModuleGenerationStep.is_current.is_(True), + ModuleGenerationStep.deleted_at.is_(None), + cast(ModuleGenerationStep.input_json, String).ilike(like), + ) + ) + query = query.where( + or_( + ModuleGenerationProject.id.ilike(like), + ModuleGenerationProject.title.ilike(like), + ModuleGenerationProject.current_step_code.ilike(like), + ModuleGenerationProject.error_message.ilike(like), + ModuleGenerationProject.id.in_(material_step_subquery), + ) + ) + + total = int((await db.execute(select(func.count()).select_from(query.subquery()))).scalar() or 0) + result = await db.execute( + query.order_by(ModuleGenerationProject.created_at.desc()) + .offset((page - 1) * page_size) + .limit(page_size) + ) + projects = list(result.scalars().unique().all()) + project_ids = {project.id for project in projects if project.id} + + material_step_map = await _current_step_map_by_project_ids( + db, + project_ids=project_ids, + step_code=HotOpeningStepCodeEnum.MATERIAL_INPUT.value, + ) + user_name_map: dict[str, str | None] = {} + if current_user.is_admin: + user_ids = {project.user_id for project in projects if project.user_id} + user_name_map = await _user_name_map_by_ids(db, user_ids) items: list[HotOpeningTaskListItemOut] = [] for project in projects: - material_step = await _get_current_step_by_code(db, project.id, HotOpeningStepCodeEnum.MATERIAL_INPUT.value) + material_step = material_step_map.get(project.id) material = _step_payload(material_step.input_json if material_step else None) items.append( HotOpeningTaskListItemOut( id=project.id, project_id=project.id, + user_id=project.user_id, + user_name=user_name_map.get(project.user_id) if current_user.is_admin and project.user_id else None, module=project.module, title=project.title, status=project.status, current_step_code=project.current_step_code, + source_project_name=material.get("source_project_name"), target_project_name=material.get("target_project_name"), + core_content_point=material.get("core_content_point"), final_image_url=build_resource_signed_url(project.final_image_url) if project.final_image_url else None, final_video_url=build_resource_signed_url(project.final_video_url) if project.final_video_url else None, final_video_cover_url=build_resource_signed_url(project.final_video_cover_url) if project.final_video_cover_url else None, @@ -681,8 +804,21 @@ async def update_hot_opening_step( if req.output_json: output_data = _merge_dict(output_data, req.output_json) - step.input_json = _step_input(step_code=step.step_code, payload=input_data, source_step_id=step.source_step_id, parent_step_id=step.parent_step_id) - step.output_json = _step_output(step_code=step.step_code, status=ModuleStepStatusEnum.COMPLETED.value, payload=output_data) + _force_set_json( + step, + "input_json", + _step_input( + step_code=step.step_code, + payload=input_data, + source_step_id=step.source_step_id, + parent_step_id=step.parent_step_id, + ), + ) + _force_set_json( + step, + "output_json", + _step_output(step_code=step.step_code, status=ModuleStepStatusEnum.COMPLETED.value, payload=output_data), + ) step.status = ModuleStepStatusEnum.COMPLETED.value step.error_message = None step.completed_at = _now() @@ -692,6 +828,7 @@ async def update_hot_opening_step( await _soft_delete_steps_from_index(db, project=project, start_index=step.step_index + 1) await log_module_event(db, project=project, step=step, event_type=ModuleEventTypeEnum.STEP_UPDATED.value, message="用户修改子任务内容") + await db.flush() return project, step @@ -784,11 +921,15 @@ async def update_hot_opening_image_prompt( output_data["manual_edited"] = True output_data["manual_edited_at"] = _now().isoformat() - step.output_json = _step_output( - step_code=HotOpeningStepCodeEnum.IMAGE_PROMPT_OPTIMIZE.value, - status=ModuleStepStatusEnum.COMPLETED.value, - payload=output_data, - usage=usage, + _force_set_json( + step, + "output_json", + _step_output( + step_code=HotOpeningStepCodeEnum.IMAGE_PROMPT_OPTIMIZE.value, + status=ModuleStepStatusEnum.COMPLETED.value, + payload=output_data, + usage=usage, + ), ) step.status = ModuleStepStatusEnum.COMPLETED.value step.error_message = None @@ -812,6 +953,7 @@ async def update_hot_opening_image_prompt( message="用户直接修改图片 AI 优化提词,已软删除后续步骤", detail={"start_deleted_step_index": STEP_INDEX_MAP[HotOpeningStepCodeEnum.IMAGE_GENERATE.value]}, ) + await db.flush() return project, step @@ -856,11 +998,15 @@ async def update_hot_opening_video_prompt_schema( output_data["manual_edited"] = True output_data["manual_edited_at"] = _now().isoformat() - step.output_json = _step_output( - step_code=HotOpeningStepCodeEnum.VIDEO_PROMPT_OPTIMIZE.value, - status=ModuleStepStatusEnum.COMPLETED.value, - payload=output_data, - usage=usage, + _force_set_json( + step, + "output_json", + _step_output( + step_code=HotOpeningStepCodeEnum.VIDEO_PROMPT_OPTIMIZE.value, + status=ModuleStepStatusEnum.COMPLETED.value, + payload=output_data, + usage=usage, + ), ) step.status = ModuleStepStatusEnum.COMPLETED.value step.error_message = None @@ -900,6 +1046,7 @@ async def update_hot_opening_video_prompt_schema( ], }, ) + await db.flush() return project, step @@ -1030,16 +1177,20 @@ async def run_image_prompt_optimize(db: AsyncSession, *, project_id: str, step_i }) step.status = ModuleStepStatusEnum.COMPLETED.value step.completed_at = _now() - step.output_json = _step_output( - step_code=HotOpeningStepCodeEnum.IMAGE_PROMPT_OPTIMIZE.value, - status=ModuleStepStatusEnum.COMPLETED.value, - payload={ - "optimized_prompt": optimized, - "prompt": optimized, - "original_prompt": prompt_text, - "references": references, - }, - usage=usage, + _force_set_json( + step, + "output_json", + _step_output( + step_code=HotOpeningStepCodeEnum.IMAGE_PROMPT_OPTIMIZE.value, + status=ModuleStepStatusEnum.COMPLETED.value, + payload={ + "optimized_prompt": optimized, + "prompt": optimized, + "original_prompt": prompt_text, + "references": references, + }, + usage=usage, + ), ) project.status = ModuleProjectStatusEnum.WAITING_USER.value project.current_step_code = HotOpeningStepCodeEnum.IMAGE_PROMPT_OPTIMIZE.value @@ -1319,16 +1470,20 @@ async def run_video_prompt_optimize(db: AsyncSession, *, project_id: str, step_i }) step.status = ModuleStepStatusEnum.COMPLETED.value step.completed_at = _now() - step.output_json = _step_output( - step_code=HotOpeningStepCodeEnum.VIDEO_PROMPT_OPTIMIZE.value, - status=ModuleStepStatusEnum.COMPLETED.value, - payload={ - "prompt_schema": prompt_schema, - "final_prompt": final_prompt, - "params_used_for_prompt": video_config, - "target_platform": target_platform, - }, - usage=usage, + _force_set_json( + step, + "output_json", + _step_output( + step_code=HotOpeningStepCodeEnum.VIDEO_PROMPT_OPTIMIZE.value, + status=ModuleStepStatusEnum.COMPLETED.value, + payload={ + "prompt_schema": prompt_schema, + "final_prompt": final_prompt, + "params_used_for_prompt": video_config, + "target_platform": target_platform, + }, + usage=usage, + ), ) project.status = ModuleProjectStatusEnum.WAITING_USER.value project.current_step_code = HotOpeningStepCodeEnum.VIDEO_PROMPT_OPTIMIZE.value @@ -1477,10 +1632,14 @@ async def handle_chat_generation_task_completed(db: AsyncSession, task: ChatGene if step.step_code == HotOpeningStepCodeEnum.IMAGE_GENERATE.value: step.status = ModuleStepStatusEnum.COMPLETED.value step.completed_at = _now() - step.output_json = _step_output( - step_code=HotOpeningStepCodeEnum.IMAGE_GENERATE.value, - status=ModuleStepStatusEnum.COMPLETED.value, - result={"result_image_url": task.image_url, "chat_task_id": task.id}, + _force_set_json( + step, + "output_json", + _step_output( + step_code=HotOpeningStepCodeEnum.IMAGE_GENERATE.value, + status=ModuleStepStatusEnum.COMPLETED.value, + result={"result_image_url": task.image_url, "chat_task_id": task.id}, + ), ) project.final_image_url = task.image_url project.status = ModuleProjectStatusEnum.WAITING_USER.value @@ -1489,10 +1648,14 @@ async def handle_chat_generation_task_completed(db: AsyncSession, task: ChatGene elif step.step_code == HotOpeningStepCodeEnum.VIDEO_GENERATE.value: step.status = ModuleStepStatusEnum.COMPLETED.value step.completed_at = _now() - step.output_json = _step_output( - step_code=HotOpeningStepCodeEnum.VIDEO_GENERATE.value, - status=ModuleStepStatusEnum.COMPLETED.value, - result={"result_video_url": task.video_url, "result_video_cover_url": task.video_cover_url, "chat_task_id": task.id}, + _force_set_json( + step, + "output_json", + _step_output( + step_code=HotOpeningStepCodeEnum.VIDEO_GENERATE.value, + status=ModuleStepStatusEnum.COMPLETED.value, + result={"result_video_url": task.video_url, "result_video_cover_url": task.video_cover_url, "chat_task_id": task.id}, + ), ) project.final_video_url = task.video_url project.final_video_cover_url = task.video_cover_url diff --git a/video-gen-api/app/services/hot_opening_video_prompt_service.py b/video-gen-api/app/services/hot_opening_video_prompt_service.py index 218a0921..bec47701 100644 --- a/video-gen-api/app/services/hot_opening_video_prompt_service.py +++ b/video-gen-api/app/services/hot_opening_video_prompt_service.py @@ -341,33 +341,162 @@ def fill_none_with_wu(value: Any) -> Any: return value +TOP_LEVEL_SCHEMA_KEYS = tuple(CLIENT_SCHEMA_V1.keys()) + ("动态时间规划", "输出规格限制") + +OBJECT_FIELD_WHITELISTS: dict[str, set[str]] = { + key: set(value.keys()) + for key, value in CLIENT_SCHEMA_V1.items() + if isinstance(value, dict) +} +OBJECT_FIELD_WHITELISTS.setdefault("画面属性", set()).add("推荐分辨率") +OBJECT_FIELD_WHITELISTS["输出规格限制"] = {"支持时长", "支持比例", "支持分辨率", "当前推荐分辨率"} + +ACTION_FLOW_CONTENT_KEYS = ("动作内容", "动作", "动作说明", "内容", "说明", "主体动作", "动作变化") +CAMERA_FLOW_CONTENT_KEYS = ("镜头内容", "镜头", "镜头说明", "运镜", "运镜说明", "内容", "说明") +TIME_PLAN_ALLOWED_KEYS = ("时间段", "阶段", "说明") +PLACEHOLDER_FLOW_TEXTS = { + "展示主体动作、核心卖点或主要视觉内容", + "展示主要动作、核心卖点或主要视觉内容", + "展示核心卖点或主要视觉内容", + "展示主体动作", + "无", +} +EMPTY_VALUE_TEXTS = {"", "无", "null", "None", "none", "未提及", "不适用"} + + +def _clean_schema_text(value: Any) -> str: + if value is None: + return "" + if isinstance(value, (dict, list)): + try: + return json.dumps(value, ensure_ascii=False) + except Exception: + return str(value) + return str(value).strip() + + +def _is_empty_schema_value(value: Any) -> bool: + return _clean_schema_text(value) in EMPTY_VALUE_TEXTS + + +def _normalize_schema_object(section_key: str, value: Any) -> dict[str, Any]: + default_value = CLIENT_SCHEMA_V1.get(section_key) + if not isinstance(default_value, dict): + default_value = {} + source = value if isinstance(value, dict) else {} + merged = copy.deepcopy(default_value) + allowed_keys = OBJECT_FIELD_WHITELISTS.get(section_key, set(default_value.keys())) + for field_key in allowed_keys: + if field_key in source: + merged[field_key] = fill_none_with_wu(source.get(field_key)) + return merged + + +def normalize_top_level_schema_fields(result: dict[str, Any]) -> dict[str, Any]: + """按客户端视频提词 schema 白名单清洗顶层和普通对象字段。 + + AI 偶尔会把解释性文本作为 JSON key 输出。普通对象中的非预设字段直接过滤, + 动作流程/镜头流程这类列表字段在后续 flow normalize 中单独处理。 + """ + source = result if isinstance(result, dict) else {} + normalized: dict[str, Any] = {} + for key in TOP_LEVEL_SCHEMA_KEYS: + if key in OBJECT_FIELD_WHITELISTS: + normalized[key] = _normalize_schema_object(key, source.get(key)) + elif key in source: + normalized[key] = fill_none_with_wu(source.get(key)) + elif key in CLIENT_SCHEMA_V1: + normalized[key] = copy.deepcopy(CLIENT_SCHEMA_V1[key]) + for key, default_value in CLIENT_SCHEMA_V1.items(): + if key not in normalized: + normalized[key] = copy.deepcopy(default_value) + return normalized + + def ensure_top_keys(result: dict[str, Any]) -> dict[str, Any]: - schema = copy.deepcopy(CLIENT_SCHEMA_V1) - for key, default_value in schema.items(): - if key not in result: - result[key] = default_value - elif isinstance(default_value, dict) and isinstance(result.get(key), dict): - merged = copy.deepcopy(default_value) - merged.update(result[key]) - result[key] = merged - return result + return normalize_top_level_schema_fields(result) + + +def _pick_flow_content(item: dict[str, Any], content_keys: tuple[str, ...]) -> str: + for key in content_keys: + if key in item and not _is_empty_schema_value(item.get(key)): + return _clean_schema_text(item.get(key)) + return "" + + +def _collect_extra_flow_texts( + item: dict[str, Any], + *, + content_keys: tuple[str, ...], + allowed_keys: set[str], +) -> list[str]: + extras: list[str] = [] + for key, value in item.items(): + if key in allowed_keys or key in content_keys: + continue + key_text = _clean_schema_text(key) + value_text = _clean_schema_text(value) + if key_text and key_text not in EMPTY_VALUE_TEXTS: + extras.append(key_text) + if value_text and value_text not in EMPTY_VALUE_TEXTS and value_text != key_text: + extras.append(value_text) + # 去重但保留顺序,避免 AI 重复写入同一句。 + deduped: list[str] = [] + for text in extras: + if text not in deduped: + deduped.append(text) + return deduped + + +def _merge_flow_content(base_content: str, extra_texts: list[str], fallback: str) -> str: + base_content = _clean_schema_text(base_content) + if extra_texts and (not base_content or base_content in PLACEHOLDER_FLOW_TEXTS or base_content == fallback): + return ";".join(extra_texts) + parts = [base_content] if base_content and base_content not in EMPTY_VALUE_TEXTS else [] + for text in extra_texts: + if text and text not in parts: + parts.append(text) + return ";".join(parts) if parts else fallback + + +def _normalize_flow_item( + raw_item: Any, + *, + plan_item: dict[str, str], + content_key: str, + content_keys: tuple[str, ...], +) -> dict[str, str]: + item = raw_item if isinstance(raw_item, dict) else {} + allowed_keys = {"时间段", content_key} + base_content = _pick_flow_content(item, content_keys) + extra_texts = _collect_extra_flow_texts(item, content_keys=content_keys, allowed_keys=allowed_keys) + fallback = plan_item.get("说明") or "无" + return { + "时间段": plan_item.get("时间段") or _clean_schema_text(item.get("时间段")) or "无", + content_key: _merge_flow_content(base_content, extra_texts, fallback), + } + + +def _normalize_time_plan(plan: list[dict[str, str]], value: Any) -> list[dict[str, str]]: + source = value if isinstance(value, list) else [] + normalized: list[dict[str, str]] = [] + for index, plan_item in enumerate(plan): + raw_item = source[index] if index < len(source) and isinstance(source[index], dict) else {} + item: dict[str, str] = { + "时间段": plan_item.get("时间段") or _clean_schema_text(raw_item.get("时间段")) or "无", + "阶段": _clean_schema_text(raw_item.get("阶段")) or plan_item.get("阶段") or "无", + "说明": _clean_schema_text(raw_item.get("说明")) or plan_item.get("说明") or "无", + } + # 动态时间规划只保留 时间段/阶段/说明,多余字段不入库。 + normalized.append(item) + return normalized def ensure_flow_matches_time_plan(result: dict[str, Any], duration: int) -> dict[str, Any]: plan = build_time_plan(duration) - if not isinstance(result.get("动作流程"), list) or not result["动作流程"]: - result["动作流程"] = [ - {"时间段": item["时间段"], "动作内容": item["说明"]} - for item in plan - ] - if not isinstance(result.get("镜头流程"), list) or not result["镜头流程"]: - result["镜头流程"] = [ - {"时间段": item["时间段"], "镜头内容": item["说明"]} - for item in plan - ] - result["动作流程"] = _align_flow_time_ranges(result["动作流程"], plan, "动作内容") - result["镜头流程"] = _align_flow_time_ranges(result["镜头流程"], plan, "镜头内容") - result["动态时间规划"] = plan + result["动作流程"] = _align_flow_time_ranges(result.get("动作流程"), plan, "动作内容") + result["镜头流程"] = _align_flow_time_ranges(result.get("镜头流程"), plan, "镜头内容") + result["动态时间规划"] = _normalize_time_plan(plan, result.get("动态时间规划")) return result @@ -462,16 +591,20 @@ def clean_final_prompt_specs(schema: dict[str, Any], video_config: dict[str, Any return schema -def _align_flow_time_ranges(flow: Any, plan: list[dict[str, str]], default_content_key: str) -> list[dict[str, Any]]: +def _align_flow_time_ranges(flow: Any, plan: list[dict[str, str]], default_content_key: str) -> list[dict[str, str]]: source = flow if isinstance(flow, list) else [] - aligned: list[dict[str, Any]] = [] + content_keys = ACTION_FLOW_CONTENT_KEYS if default_content_key == "动作内容" else CAMERA_FLOW_CONTENT_KEYS + aligned: list[dict[str, str]] = [] for index, plan_item in enumerate(plan): - old_item = source[index] if index < len(source) and isinstance(source[index], dict) else {} - item = dict(old_item) - item["时间段"] = plan_item["时间段"] - if not any(k in item and str(item.get(k)).strip() for k in (default_content_key, "动作", "镜头", "说明", "内容")): - item[default_content_key] = plan_item["说明"] - aligned.append(item) + raw_item = source[index] if index < len(source) else {} + aligned.append( + _normalize_flow_item( + raw_item, + plan_item=plan_item, + content_key=default_content_key, + content_keys=content_keys, + ) + ) return aligned diff --git a/video-gen-api/app/services/pre_test_template_service.py b/video-gen-api/app/services/pre_test_template_service.py new file mode 100644 index 00000000..0bd4df58 --- /dev/null +++ b/video-gen-api/app/services/pre_test_template_service.py @@ -0,0 +1,258 @@ +import json +from typing import Optional + +from sqlalchemy import select, update +from sqlalchemy.ext.asyncio import AsyncSession + +from app.models.pre_test_template import PreTestTemplate +from app.utils.id_gen import generate_id + + +async def create_pre_test_template( + user_id: str, + db: AsyncSession, + name: str, + note: Optional[str] = None, + platform: Optional[str] = None, + external_action: Optional[str] = None, + cpa_bid: Optional[float] = None, + audience_gender: Optional[str] = None, + audience_age: Optional[list] = None, + audience_region: Optional[list] = None, + audience_network: Optional[list] = None, + cus_name: Optional[str] = None, + pricing_type: Optional[str] = None, + cost_cap: Optional[bool] = None, + target_cost: Optional[bool] = None, + nobid: Optional[bool] = None, + cpc_bid: Optional[float] = None, + budget: Optional[float] = None, + is_default: Optional[bool] = None, +) -> PreTestTemplate: + if is_default: + await db.execute( + update(PreTestTemplate) + .where( + PreTestTemplate.user_id == user_id, + PreTestTemplate.is_default == True, + PreTestTemplate.deleted_at.is_(None), + ) + .values(is_default=False) + ) + + template = PreTestTemplate( + id=generate_id(), + user_id=user_id, + name=name, + note=note, + platform=platform, + external_action=external_action, + cpa_bid=cpa_bid, + audience_gender=audience_gender, + audience_age=json.dumps(audience_age) if audience_age else None, + audience_region=json.dumps(audience_region) if audience_region else None, + audience_network=json.dumps(audience_network) if audience_network else None, + cus_name=cus_name, + pricing_type=pricing_type, + cost_cap=cost_cap, + target_cost=target_cost, + nobid=nobid, + cpc_bid=cpc_bid, + budget=budget, + is_default=is_default, + ) + + db.add(template) + await db.commit() + await db.refresh(template) + return template + + +async def update_pre_test_template( + template_id: str, + user_id: str, + db: AsyncSession, + **kwargs, +) -> Optional[PreTestTemplate]: + result = await db.execute( + select(PreTestTemplate).where( + PreTestTemplate.id == template_id, + PreTestTemplate.user_id == user_id, + PreTestTemplate.deleted_at.is_(None), + ) + ) + template = result.scalar_one_or_none() + + if not template: + return None + + if kwargs.get("is_default"): + await db.execute( + update(PreTestTemplate) + .where( + PreTestTemplate.user_id == user_id, + PreTestTemplate.is_default == True, + PreTestTemplate.id != template_id, + PreTestTemplate.deleted_at.is_(None), + ) + .values(is_default=False) + ) + + update_data = {} + if "name" in kwargs: + update_data["name"] = kwargs["name"] + if "note" in kwargs: + update_data["note"] = kwargs["note"] + if "platform" in kwargs: + update_data["platform"] = kwargs["platform"] + if "external_action" in kwargs: + update_data["external_action"] = kwargs["external_action"] + if "cpa_bid" in kwargs: + update_data["cpa_bid"] = kwargs["cpa_bid"] + if "audience_gender" in kwargs: + update_data["audience_gender"] = kwargs["audience_gender"] + if "audience_age" in kwargs: + update_data["audience_age"] = json.dumps(kwargs["audience_age"]) if kwargs["audience_age"] else None + if "audience_region" in kwargs: + update_data["audience_region"] = json.dumps(kwargs["audience_region"]) if kwargs["audience_region"] else None + if "audience_network" in kwargs: + update_data["audience_network"] = json.dumps(kwargs["audience_network"]) if kwargs["audience_network"] else None + if "cus_name" in kwargs: + update_data["cus_name"] = kwargs["cus_name"] + if "pricing_type" in kwargs: + update_data["pricing_type"] = kwargs["pricing_type"] + if "cost_cap" in kwargs: + update_data["cost_cap"] = kwargs["cost_cap"] + if "target_cost" in kwargs: + update_data["target_cost"] = kwargs["target_cost"] + if "nobid" in kwargs: + update_data["nobid"] = kwargs["nobid"] + if "cpc_bid" in kwargs: + update_data["cpc_bid"] = kwargs["cpc_bid"] + if "budget" in kwargs: + update_data["budget"] = kwargs["budget"] + if "is_default" in kwargs: + update_data["is_default"] = kwargs["is_default"] + + if update_data: + await db.execute( + update(PreTestTemplate) + .where(PreTestTemplate.id == template_id) + .values(**update_data) + ) + await db.commit() + await db.refresh(template) + + return template + + +async def delete_pre_test_template( + template_id: str, + user_id: str, + db: AsyncSession, +) -> bool: + result = await db.execute( + select(PreTestTemplate).where( + PreTestTemplate.id == template_id, + PreTestTemplate.user_id == user_id, + PreTestTemplate.deleted_at.is_(None), + ) + ) + template = result.scalar_one_or_none() + + if not template: + return False + + from datetime import datetime + template.deleted_at = datetime.now() + await db.commit() + return True + + +async def get_pre_test_template( + template_id: str, + user_id: str, + db: AsyncSession, +) -> Optional[PreTestTemplate]: + result = await db.execute( + select(PreTestTemplate).where( + PreTestTemplate.id == template_id, + PreTestTemplate.user_id == user_id, + PreTestTemplate.deleted_at.is_(None), + ) + ) + return result.scalar_one_or_none() + + +async def get_pre_test_template_list( + user_id: str, + db: AsyncSession, + platform: Optional[str] = None, + page: int = 1, + page_size: int = 10, +) -> dict: + if page < 1: + page = 1 + if page_size < 1: + page_size = 10 + if page_size > 100: + page_size = 100 + + query = select(PreTestTemplate).where( + PreTestTemplate.user_id == user_id, + PreTestTemplate.deleted_at.is_(None), + ) + + if platform: + query = query.where(PreTestTemplate.platform == platform) + + query = query.order_by(PreTestTemplate.is_default.desc(), PreTestTemplate.created_at.desc()) + + total_result = await db.execute(query.with_only_columns(PreTestTemplate.id)) + total = len(total_result.scalars().all()) + + offset = (page - 1) * page_size + query = query.offset(offset).limit(page_size) + + result = await db.execute(query) + templates = result.scalars().all() + + return { + "data": templates, + "total": total, + "page": page, + "page_size": page_size, + } + + +async def get_default_template( + user_id: str, + db: AsyncSession, +) -> Optional[PreTestTemplate]: + # 如果有默认模板,返回默认模板 + # 如果有多条默认的模板,返回最新创建的模板 + # 如果没有设置默认模板,返回最新创建的模板 + result = await db.execute( + select(PreTestTemplate) + .where( + PreTestTemplate.user_id == user_id, + PreTestTemplate.is_default == True, + PreTestTemplate.deleted_at.is_(None), + ) + .order_by(PreTestTemplate.created_at.desc()) + ) + template = result.scalar_one_or_none() + + if template: + return template + + # 如果没有默认模板,返回最新创建的模板 + result = await db.execute( + select(PreTestTemplate) + .where( + PreTestTemplate.user_id == user_id, + PreTestTemplate.deleted_at.is_(None), + ) + .order_by(PreTestTemplate.created_at.desc()) + ) + return result.scalar_one_or_none() \ No newline at end of file diff --git a/video-gen-api/app/services/shot_replicate_flow_service.py b/video-gen-api/app/services/shot_replicate_flow_service.py index 22343d57..0d000938 100644 --- a/video-gen-api/app/services/shot_replicate_flow_service.py +++ b/video-gen-api/app/services/shot_replicate_flow_service.py @@ -493,9 +493,16 @@ async def project_to_detail_out(db: AsyncSession, project: ModuleGenerationProje video_url = video_generate_output.get("result_video_url") or (video_chat.video_url if video_chat else None) or project.final_video_url cover_url = video_generate_output.get("result_video_cover_url") or (video_chat.video_cover_url if video_chat else None) or project.final_video_cover_url + user_name: str | None = None + if project.user_id: + user_result = await db.execute(select(User.username).where(User.id == project.user_id).limit(1)) + user_name = user_result.scalar_one_or_none() + return ShotReplicateTaskDetailOut( id=project.id, project_id=project.id, + user_id=project.user_id, + user_name=user_name, module=project.module, title=project.title, status=project.status, @@ -593,6 +600,26 @@ async def create_shot_replicate_project(db: AsyncSession, current_user: User, re return project +async def _current_step_map_by_project_ids( + db: AsyncSession, + *, + project_ids: set[str], + step_code: str, +) -> dict[str, ModuleGenerationStep]: + """一次性查询当前页项目的指定步骤,避免列表逐条查 material_input。""" + if not project_ids: + return {} + result = await db.execute( + select(ModuleGenerationStep).where( + ModuleGenerationStep.project_id.in_(list(project_ids)), + ModuleGenerationStep.step_code == step_code, + ModuleGenerationStep.is_current.is_(True), + ModuleGenerationStep.deleted_at.is_(None), + ) + ) + return {step.project_id: step for step in result.scalars().all()} + + async def list_shot_replicate_projects( db: AsyncSession, *, @@ -601,6 +628,11 @@ async def list_shot_replicate_projects( page: int, page_size: int, ) -> ShotReplicateTaskListOut: + """ + 拆镜复刻项目列表查询。 + + 这个列表目前不是后台主入口,但仍避免逐条查 material_input,保持和爆款开头列表一致的批量查询策略。 + """ query = select(ModuleGenerationProject).where( ModuleGenerationProject.module == MODULE, ModuleGenerationProject.deleted_at.is_(None), @@ -610,13 +642,23 @@ async def list_shot_replicate_projects( if status: query = query.where(ModuleGenerationProject.status == status) - total = (await db.execute(select(func.count()).select_from(query.subquery()))).scalar_one() - result = await db.execute(query.order_by(ModuleGenerationProject.created_at.desc()).offset((page - 1) * page_size).limit(page_size)) - projects = list(result.scalars().all()) + total = int((await db.execute(select(func.count()).select_from(query.subquery()))).scalar() or 0) + result = await db.execute( + query.order_by(ModuleGenerationProject.created_at.desc()) + .offset((page - 1) * page_size) + .limit(page_size) + ) + projects = list(result.scalars().unique().all()) + project_ids = {project.id for project in projects if project.id} + material_step_map = await _current_step_map_by_project_ids( + db, + project_ids=project_ids, + step_code=ShotReplicateStepCodeEnum.MATERIAL_INPUT.value, + ) items: list[ShotReplicateTaskListItemOut] = [] for project in projects: - material_step = await _get_current_step_by_code(db, project.id, ShotReplicateStepCodeEnum.MATERIAL_INPUT.value) + material_step = material_step_map.get(project.id) material = _step_payload(material_step.input_json if material_step else None) items.append( ShotReplicateTaskListItemOut( @@ -717,8 +759,10 @@ async def update_shot_replicate_material_input( old_material_step = await _get_current_step_by_code(db, project.id, ShotReplicateStepCodeEnum.MATERIAL_INPUT.value) old_material = _step_payload(old_material_step.input_json if old_material_step else None) + # 拆镜复刻的素材视频来自 shot_replicate_segments.segment_video_url, + # 与片段强绑定,不允许前端在项目素材修改接口中覆盖。 material = { - "material_video_url": req.material_video_url if req.material_video_url is not None else old_material.get("material_video_url"), + "material_video_url": old_material.get("material_video_url"), "material_image_url": req.material_image_url if req.material_image_url is not None else old_material.get("material_image_url"), "source_project_name": req.source_project_name if req.source_project_name is not None else old_material.get("source_project_name"), "target_project_name": req.target_project_name if req.target_project_name is not None else old_material.get("target_project_name"), diff --git a/video-gen-api/app/services/shot_replicate_taskset_service.py b/video-gen-api/app/services/shot_replicate_taskset_service.py index 2ad87bf4..af9c4c91 100644 --- a/video-gen-api/app/services/shot_replicate_taskset_service.py +++ b/video-gen-api/app/services/shot_replicate_taskset_service.py @@ -7,7 +7,7 @@ from typing import Any from fastapi import HTTPException from app.config import settings -from sqlalchemy import func, select +from sqlalchemy import String, cast, func, or_, select from sqlalchemy.ext.asyncio import AsyncSession from app.enums.shot_replicate import ( @@ -19,6 +19,7 @@ from app.enums.shot_replicate import ( ShotSplitStatusEnum, ShotTaskSetStatusEnum, ) +from app.models.module_generation_project import ModuleGenerationProject from app.models.shot_replicate_segment import ShotReplicateSegment from app.models.shot_replicate_task_set import ShotReplicateTaskSet from app.models.user import User @@ -85,26 +86,37 @@ def _normalize_suggestions(value: Any) -> list[dict[str, Any]]: return normalized -def _task_set_to_out(task_set: ShotReplicateTaskSet) -> ShotTaskSetOut: - return ShotTaskSetOut.model_validate(task_set) +def _task_set_to_out(task_set: ShotReplicateTaskSet, user_name: str | None = None) -> ShotTaskSetOut: + data = ShotTaskSetOut.model_validate(task_set) + data.user_name = user_name + return data -def _task_set_to_detail_out(task_set: ShotReplicateTaskSet) -> ShotTaskSetDetailOut: +def _task_set_to_detail_out(task_set: ShotReplicateTaskSet, user_name: str | None = None) -> ShotTaskSetDetailOut: suggestions = [ShotAISuggestionOut(**{k: v for k, v in item.items() if k != "raw"}) for item in _normalize_suggestions(task_set.ai_suggestion_json)] base = ShotTaskSetDetailOut.model_validate(task_set) + base.user_name = user_name base.ai_suggestions = suggestions return base -def _segment_to_out(segment: ShotReplicateSegment) -> ShotSegmentOut: +def _segment_to_out(segment: ShotReplicateSegment, project: ModuleGenerationProject | None = None) -> ShotSegmentOut: data = ShotSegmentOut.model_validate(segment) data.segment_name = f"片段{segment.segment_index}" + if project: + data.module_project_title = project.title + data.module_project_status = project.status + data.module_project_current_step_code = project.current_step_code return data -def _segment_to_detail_out(segment: ShotReplicateSegment) -> ShotSegmentDetailOut: +def _segment_to_detail_out(segment: ShotReplicateSegment, project: ModuleGenerationProject | None = None) -> ShotSegmentDetailOut: data = ShotSegmentDetailOut.model_validate(segment) data.segment_name = f"片段{segment.segment_index}" + if project: + data.module_project_title = project.title + data.module_project_status = project.status + data.module_project_current_step_code = project.current_step_code return data @@ -201,6 +213,23 @@ async def create_task_set(db: AsyncSession, *, current_user: User, req: ShotTask return task_set +def _user_name_filter_subquery(value: str): + """后台按用户名筛选时使用的子查询。 + + 只在传入 user_name 时查询 users 表;keyword 不再关联 users,避免后台关键词搜索扩大查询范围。 + """ + like = f"%{value.strip()}%" + return select(User.id).where(User.username.ilike(like)) + + +async def _user_name_map_by_ids(db: AsyncSession, user_ids: set[str]) -> dict[str, str | None]: + """一次性查询当前页涉及的用户,避免列表逐条查询用户表。""" + if not user_ids: + return {} + result = await db.execute(select(User.id, User.username).where(User.id.in_(list(user_ids)))) + return {user_id: username for user_id, username in result.all()} + + async def list_task_sets( db: AsyncSession, *, @@ -209,39 +238,85 @@ async def list_task_sets( analysis_status: str | None = None, split_status: str | None = None, keyword: str | None = None, + user_id: str | None = None, + user_name: str | None = None, + created_start: datetime | None = None, + created_end: datetime | None = None, page: int = 1, page_size: int = 20, ) -> ShotTaskSetListOut: + """ + 拆镜总任务集列表查询。 + + 性能策略: + 1. 主列表不 join User,避免 count/list 复杂化。 + 2. 管理员按 user_name 搜索时使用 IN (SELECT users.id ...) 子查询;keyword 不查询 users 表。 + 3. 当前页数据取出后,再按 user_id 去重批量查 user_name,用于后台渲染。 + """ query = select(ShotReplicateTaskSet).where(ShotReplicateTaskSet.deleted_at.is_(None)) + if not current_user.is_admin: query = query.where(ShotReplicateTaskSet.user_id == current_user.id) + else: + if user_id and user_id.strip(): + query = query.where(ShotReplicateTaskSet.user_id == user_id.strip()) + if user_name and user_name.strip(): + query = query.where(ShotReplicateTaskSet.user_id.in_(_user_name_filter_subquery(user_name))) + if created_start: + query = query.where(ShotReplicateTaskSet.created_at >= created_start) + if created_end: + query = query.where(ShotReplicateTaskSet.created_at <= created_end) + if status: query = query.where(ShotReplicateTaskSet.status == status) if analysis_status: query = query.where(ShotReplicateTaskSet.analysis_status == analysis_status) if split_status: query = query.where(ShotReplicateTaskSet.split_status == split_status) - if keyword: + if keyword and keyword.strip(): like = f"%{keyword.strip()}%" - query = query.where( - (ShotReplicateTaskSet.title.ilike(like)) - | (ShotReplicateTaskSet.original_video_content.ilike(like)) - | (ShotReplicateTaskSet.original_video_category.ilike(like)) - ) + conditions = [ + ShotReplicateTaskSet.id.ilike(like), + ShotReplicateTaskSet.title.ilike(like), + ShotReplicateTaskSet.original_video_content.ilike(like), + ShotReplicateTaskSet.original_video_category.ilike(like), + ShotReplicateTaskSet.original_video_audience.ilike(like), + cast(ShotReplicateTaskSet.ai_suggestion_json, String).ilike(like), + ] + query = query.where(or_(*conditions)) total_result = await db.execute(select(func.count()).select_from(query.subquery())) total = int(total_result.scalar() or 0) - rows = await db.execute( + result = await db.execute( query.order_by(ShotReplicateTaskSet.created_at.desc()) .offset((page - 1) * page_size) .limit(page_size) ) - return ShotTaskSetListOut(total=total, page=page, page_size=page_size, items=[_task_set_to_out(item) for item in rows.scalars().all()]) + task_sets = list(result.scalars().unique().all()) + + user_name_map: dict[str, str | None] = {} + if current_user.is_admin: + user_ids = {task_set.user_id for task_set in task_sets if task_set.user_id} + user_name_map = await _user_name_map_by_ids(db, user_ids) + + return ShotTaskSetListOut( + total=total, + page=page, + page_size=page_size, + items=[ + _task_set_to_out( + task_set, + user_name_map.get(task_set.user_id) if current_user.is_admin and task_set.user_id else None, + ) + for task_set in task_sets + ], + ) async def task_set_detail(db: AsyncSession, *, current_user: User, task_set_id: str) -> ShotTaskSetDetailOut: task_set = await get_task_set_for_user(db, task_set_id=task_set_id, user=current_user) - return _task_set_to_detail_out(task_set) + user_result = await db.execute(select(User.username).where(User.id == task_set.user_id).limit(1)) + return _task_set_to_detail_out(task_set, user_result.scalar_one_or_none()) async def _next_segment_index(db: AsyncSession, task_set_id: str) -> int: @@ -499,9 +574,13 @@ async def list_segments( page_size: int = 20, ) -> ShotSegmentListOut: await get_task_set_for_user(db, task_set_id=task_set_id, user=current_user) - query = select(ShotReplicateSegment).where( - ShotReplicateSegment.task_set_id == task_set_id, - ShotReplicateSegment.deleted_at.is_(None), + query = ( + select(ShotReplicateSegment, ModuleGenerationProject) + .outerjoin(ModuleGenerationProject, ModuleGenerationProject.id == ShotReplicateSegment.module_project_id) + .where( + ShotReplicateSegment.task_set_id == task_set_id, + ShotReplicateSegment.deleted_at.is_(None), + ) ) if not current_user.is_admin: query = query.where(ShotReplicateSegment.user_id == current_user.id) @@ -521,9 +600,18 @@ async def list_segments( .offset((page - 1) * page_size) .limit(page_size) ) - return ShotSegmentListOut(total=total, page=page, page_size=page_size, items=[_segment_to_out(item) for item in rows.scalars().all()]) + return ShotSegmentListOut( + total=total, + page=page, + page_size=page_size, + items=[_segment_to_out(segment, project) for segment, project in rows.all()], + ) async def segment_detail(db: AsyncSession, *, current_user: User, segment_id: str) -> ShotSegmentDetailOut: segment = await get_segment_for_user(db, segment_id=segment_id, user=current_user) - return _segment_to_detail_out(segment) + project: ModuleGenerationProject | None = None + if segment.module_project_id: + project_result = await db.execute(select(ModuleGenerationProject).where(ModuleGenerationProject.id == segment.module_project_id).limit(1)) + project = project_result.scalar_one_or_none() + return _segment_to_detail_out(segment, project) diff --git a/video-gen-api/app/services/sms.py b/video-gen-api/app/services/sms.py index 51b1bd88..0ced3156 100644 --- a/video-gen-api/app/services/sms.py +++ b/video-gen-api/app/services/sms.py @@ -173,7 +173,7 @@ async def verify_sms_code(phone: str, code: str, scene: str = "login") -> bool: stored = await redis.get(key) if isinstance(stored, bytes): stored = stored.decode() - if stored and str(stored) == str(code): + if stored is not None and stored == code: await redis.delete(key) return True return False diff --git a/video-gen-api/app/utils/area.py b/video-gen-api/app/utils/area.py new file mode 100644 index 00000000..3f1eec23 --- /dev/null +++ b/video-gen-api/app/utils/area.py @@ -0,0 +1,241 @@ +import json +import os +from typing import Optional, List, Dict + +# 缓存文件路径 +CACHE_FILE_PATH = os.path.join(os.path.dirname(__file__), 'area_cache.json') + + +class AreaInfo: + def __init__(self, code: str, name: str, level: str, geoname_id: int = None): + self.code = code + self.name = name + self.level = level + self.geoname_id = geoname_id + self.sub_districts: List[AreaInfo] = [] + + def to_dict(self): + return { + "code": self.code, + "name": self.name, + "level": self.level, + "geoname_id": self.geoname_id, + "sub_districts": [sd.to_dict() for sd in self.sub_districts] if self.sub_districts else [], + } + + @classmethod + def from_dict(cls, data: dict): + area = cls( + code=data.get("code"), + name=data.get("name"), + level=data.get("level"), + geoname_id=data.get("geoname_id"), + ) + sub_districts = data.get("sub_districts", []) + for sub in sub_districts: + area.sub_districts.append(cls.from_dict(sub)) + return area + + +def parse_district_data(district_data: dict) -> AreaInfo: + """解析巨量接口返回的区域数据""" + area = AreaInfo( + code=district_data.get("code"), + name=district_data.get("name"), + level=district_data.get("level"), + geoname_id=district_data.get("geoname_id"), + ) + + sub_districts = district_data.get("sub_districts") + if sub_districts: + for sub in sub_districts: + area.sub_districts.append(parse_district_data(sub)) + + return area + + +def save_area_cache(areas: List[AreaInfo]) -> None: + """将区域数据保存到缓存文件""" + data = [area.to_dict() for area in areas] + with open(CACHE_FILE_PATH, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + + +def load_area_cache() -> Optional[List[AreaInfo]]: + """从缓存文件加载区域数据""" + if not os.path.exists(CACHE_FILE_PATH): + return None + + try: + with open(CACHE_FILE_PATH, 'r', encoding='utf-8') as f: + data = json.load(f) + return [AreaInfo.from_dict(item) for item in data] + except (json.JSONDecodeError, IOError): + return None + + +def clear_area_cache() -> None: + """清除缓存文件""" + if os.path.exists(CACHE_FILE_PATH): + os.remove(CACHE_FILE_PATH) + + +def filter_by_level(areas: List[AreaInfo], target_level: str) -> List[AreaInfo]: + """ + 根据级别过滤区域信息 + + :param areas: 区域列表 + :param target_level: ONE_LEVEL / TWO_LEVEL / THREE_LEVEL + :return: 指定级别的区域列表 + """ + result = [] + + def traverse(area: AreaInfo): + if area.level == target_level: + filtered = AreaInfo( + code=area.code, + name=area.name, + level=area.level, + geoname_id=area.geoname_id, + ) + result.append(filtered) + + if area.sub_districts: + for sub in area.sub_districts: + traverse(sub) + + for area in areas: + traverse(area) + + return result + + +def get_first_level_areas(areas: List[AreaInfo]) -> List[AreaInfo]: + """获取所有一级区域(省/直辖市)""" + return filter_by_level(areas, "ONE_LEVEL") + + +def get_second_level_areas(areas: List[AreaInfo], parent_code: str = None) -> List[AreaInfo]: + """ + 获取二级区域(市) + + :param areas: 区域列表 + :param parent_code: 一级区域code,不传则返回所有二级区域 + :return: 二级区域列表 + """ + if parent_code: + def find_parent_and_get_children(area: AreaInfo): + if area.code == parent_code: + return [AreaInfo( + code=sub.code, + name=sub.name, + level=sub.level, + geoname_id=sub.geoname_id, + ) for sub in area.sub_districts] if area.sub_districts else [] + + if area.sub_districts: + for sub in area.sub_districts: + result = find_parent_and_get_children(sub) + if result: + return result + return [] + + for area in areas: + result = find_parent_and_get_children(area) + if result: + return result + return [] + else: + return filter_by_level(areas, "TWO_LEVEL") + + +def get_third_level_areas(areas: List[AreaInfo], parent_code: str) -> List[AreaInfo]: + """ + 获取三级区域(区/县) + + :param areas: 区域列表 + :param parent_code: 二级区域code + :return: 三级区域列表 + """ + def find_parent_and_get_children(area: AreaInfo): + if area.code == parent_code: + return [AreaInfo( + code=sub.code, + name=sub.name, + level=sub.level, + geoname_id=sub.geoname_id, + ) for sub in area.sub_districts] if area.sub_districts else [] + + if area.sub_districts: + for sub in area.sub_districts: + result = find_parent_and_get_children(sub) + if result: + return result + return [] + + for area in areas: + result = find_parent_and_get_children(area) + if result: + return result + return [] + + +def get_area_by_level(areas: List[AreaInfo], level: str, parent_code: str = None) -> List[AreaInfo]: + """ + 根据级别获取区域信息 + + :param areas: 区域列表 + :param level: ONE_LEVEL / TWO_LEVEL / THREE_LEVEL + :param parent_code: 父级区域code(TWO_LEVEL和THREE_LEVEL时可选/必填) + :return: 区域列表 + """ + level = level.upper() + + if level == "ONE_LEVEL": + return get_first_level_areas(areas) + elif level == "TWO_LEVEL": + return get_second_level_areas(areas, parent_code) + elif level == "THREE_LEVEL": + if not parent_code: + raise ValueError("获取三级区域需要提供二级区域code") + return get_third_level_areas(areas, parent_code) + else: + raise ValueError(f"不支持的级别: {level}") + + +async def fetch_and_cache_area_data(oauth_id: str, advertiser_id: str = 1836693172153543, code: str = "CN") -> List[AreaInfo]: + """ + 从接口获取区域数据并缓存到文件 + + :param oauth_id: 授权ID + :param code: 行政区域编码,默认中国CN + :return: 区域列表 + """ + from app.utils.douyinApi import DouyinApi + + params = { + "advertiser_id": advertiser_id, + "codes": json.dumps([code]), + "language": "ZH_CN", + "sub_district": "THREE_LEVEL", + "version": "V2_3_2" + } + + area_response = await DouyinApi().get_area(oauth_id=oauth_id, params=params) + + if area_response.get("code") != 0: + raise Exception(f"获取区域信息失败: {area_response.get('message', '未知错误')}") + + districts_data = area_response.get("data", {}).get("districts", []) + if not districts_data: + raise Exception("接口返回的区域数据为空") + + area_list = [parse_district_data(d) for d in districts_data] + save_area_cache(area_list) + + return area_list + + +def get_cached_area_data() -> Optional[List[AreaInfo]]: + """获取缓存的区域数据""" + return load_area_cache() diff --git a/video-gen-api/app/utils/area_cache.json b/video-gen-api/app/utils/area_cache.json new file mode 100644 index 00000000..b717ca28 --- /dev/null +++ b/video-gen-api/app/utils/area_cache.json @@ -0,0 +1,23257 @@ +[ + { + "code": "CN", + "name": "中国", + "level": "NONE", + "geoname_id": 1814991, + "sub_districts": [ + { + "code": "34", + "name": "安徽", + "level": "ONE_LEVEL", + "geoname_id": 1818058, + "sub_districts": [ + { + "code": "340800", + "name": "安庆", + "level": "TWO_LEVEL", + "geoname_id": 1817993, + "sub_districts": [ + { + "code": "340803", + "name": "大观", + "level": "THREE_LEVEL", + "geoname_id": 6643450, + "sub_districts": [] + }, + { + "code": "340822", + "name": "怀宁", + "level": "THREE_LEVEL", + "geoname_id": 1807676, + "sub_districts": [] + }, + { + "code": "3408820000001", + "name": "潜山", + "level": "THREE_LEVEL", + "geoname_id": 1798253, + "sub_districts": [] + }, + { + "code": "340826", + "name": "宿松", + "level": "THREE_LEVEL", + "geoname_id": 1793760, + "sub_districts": [] + }, + { + "code": "340881", + "name": "桐城", + "level": "THREE_LEVEL", + "geoname_id": 1792696, + "sub_districts": [] + }, + { + "code": "340825", + "name": "太湖", + "level": "THREE_LEVEL", + "geoname_id": 1793659, + "sub_districts": [] + }, + { + "code": "340827", + "name": "望江", + "level": "THREE_LEVEL", + "geoname_id": 1792012, + "sub_districts": [] + }, + { + "code": "340802", + "name": "迎江", + "level": "THREE_LEVEL", + "geoname_id": 6643451, + "sub_districts": [] + }, + { + "code": "340811", + "name": "宜秀", + "level": "THREE_LEVEL", + "geoname_id": 6643449, + "sub_districts": [] + }, + { + "code": "340828", + "name": "岳西", + "level": "THREE_LEVEL", + "geoname_id": 1792882, + "sub_districts": [] + } + ] + }, + { + "code": "340300", + "name": "蚌埠", + "level": "TWO_LEVEL", + "geoname_id": 1816440, + "sub_districts": [ + { + "code": "340303", + "name": "蚌山", + "level": "THREE_LEVEL", + "geoname_id": 6643474, + "sub_districts": [] + }, + { + "code": "340323", + "name": "固镇", + "level": "THREE_LEVEL", + "geoname_id": 1809134, + "sub_districts": [] + }, + { + "code": "340311", + "name": "淮上", + "level": "THREE_LEVEL", + "geoname_id": 6643475, + "sub_districts": [] + }, + { + "code": "340321", + "name": "怀远", + "level": "THREE_LEVEL", + "geoname_id": 340321, + "sub_districts": [] + }, + { + "code": "340302", + "name": "龙子湖", + "level": "THREE_LEVEL", + "geoname_id": 6643476, + "sub_districts": [] + }, + { + "code": "340322", + "name": "五河", + "level": "THREE_LEVEL", + "geoname_id": 1791238, + "sub_districts": [] + }, + { + "code": "340304", + "name": "禹会", + "level": "THREE_LEVEL", + "geoname_id": 6643473, + "sub_districts": [] + } + ] + }, + { + "code": "341600", + "name": "亳州", + "level": "TWO_LEVEL", + "geoname_id": 1816234, + "sub_districts": [ + { + "code": "341621", + "name": "涡阳", + "level": "THREE_LEVEL", + "geoname_id": 1809270, + "sub_districts": [] + }, + { + "code": "341623", + "name": "利辛", + "level": "THREE_LEVEL", + "geoname_id": 1802795, + "sub_districts": [] + }, + { + "code": "341622", + "name": "蒙城", + "level": "THREE_LEVEL", + "geoname_id": 1800761, + "sub_districts": [] + }, + { + "code": "341602", + "name": "谯城", + "level": "THREE_LEVEL", + "geoname_id": 1816232, + "sub_districts": [] + } + ] + }, + { + "code": "341100", + "name": "滁州", + "level": "TWO_LEVEL", + "geoname_id": 1814757, + "sub_districts": [ + { + "code": "341125", + "name": "定远", + "level": "THREE_LEVEL", + "geoname_id": 1812731, + "sub_districts": [] + }, + { + "code": "341126", + "name": "凤阳", + "level": "THREE_LEVEL", + "geoname_id": 1811185, + "sub_districts": [] + }, + { + "code": "341122", + "name": "来安", + "level": "THREE_LEVEL", + "geoname_id": 1804611, + "sub_districts": [] + }, + { + "code": "341102", + "name": "琅琊", + "level": "THREE_LEVEL", + "geoname_id": 6643471, + "sub_districts": [] + }, + { + "code": "341182", + "name": "明光", + "level": "THREE_LEVEL", + "geoname_id": 1805970, + "sub_districts": [] + }, + { + "code": "341103", + "name": "南谯", + "level": "THREE_LEVEL", + "geoname_id": 6643472, + "sub_districts": [] + }, + { + "code": "341124", + "name": "全椒", + "level": "THREE_LEVEL", + "geoname_id": 1797377, + "sub_districts": [] + }, + { + "code": "341181", + "name": "天长", + "level": "THREE_LEVEL", + "geoname_id": 1793015, + "sub_districts": [] + } + ] + }, + { + "code": "341700", + "name": "池州", + "level": "TWO_LEVEL", + "geoname_id": 1814934, + "sub_districts": [ + { + "code": "341721", + "name": "东至", + "level": "THREE_LEVEL", + "geoname_id": 1812050, + "sub_districts": [] + }, + { + "code": "341702", + "name": "贵池", + "level": "THREE_LEVEL", + "geoname_id": 1809531, + "sub_districts": [] + }, + { + "code": "341723", + "name": "青阳", + "level": "THREE_LEVEL", + "geoname_id": 1797648, + "sub_districts": [] + }, + { + "code": "341722", + "name": "石台", + "level": "THREE_LEVEL", + "geoname_id": 1794993, + "sub_districts": [] + } + ] + }, + { + "code": "341200", + "name": "阜阳", + "level": "TWO_LEVEL", + "geoname_id": 1810845, + "sub_districts": [ + { + "code": "341225", + "name": "阜南", + "level": "THREE_LEVEL", + "geoname_id": 1810955, + "sub_districts": [] + }, + { + "code": "341282", + "name": "界首", + "level": "THREE_LEVEL", + "geoname_id": 1805844, + "sub_districts": [] + }, + { + "code": "341221", + "name": "临泉", + "level": "THREE_LEVEL", + "geoname_id": 1803361, + "sub_districts": [] + }, + { + "code": "341222", + "name": "太和", + "level": "THREE_LEVEL", + "geoname_id": 1793675, + "sub_districts": [] + }, + { + "code": "341203", + "name": "颍东", + "level": "THREE_LEVEL", + "geoname_id": 6643455, + "sub_districts": [] + }, + { + "code": "341204", + "name": "颍泉", + "level": "THREE_LEVEL", + "geoname_id": 6643454, + "sub_districts": [] + }, + { + "code": "341226", + "name": "颍上", + "level": "THREE_LEVEL", + "geoname_id": 1786585, + "sub_districts": [] + }, + { + "code": "341202", + "name": "颍州", + "level": "THREE_LEVEL", + "geoname_id": 6643456, + "sub_districts": [] + } + ] + }, + { + "code": "340600", + "name": "淮北", + "level": "TWO_LEVEL", + "geoname_id": 1807700, + "sub_districts": [ + { + "code": "340602", + "name": "杜集", + "level": "THREE_LEVEL", + "geoname_id": 6643481, + "sub_districts": [] + }, + { + "code": "340604", + "name": "烈山", + "level": "THREE_LEVEL", + "geoname_id": 340604, + "sub_districts": [] + }, + { + "code": "340621", + "name": "濉溪", + "level": "THREE_LEVEL", + "geoname_id": 1793885, + "sub_districts": [] + }, + { + "code": "340603", + "name": "相山", + "level": "THREE_LEVEL", + "geoname_id": 6643482, + "sub_districts": [] + } + ] + }, + { + "code": "340100", + "name": "合肥", + "level": "TWO_LEVEL", + "geoname_id": 1808722, + "sub_districts": [ + { + "code": "3401110000003", + "name": "包河", + "level": "THREE_LEVEL", + "geoname_id": 6643479, + "sub_districts": [] + }, + { + "code": "340121", + "name": "长丰", + "level": "THREE_LEVEL", + "geoname_id": 1815747, + "sub_districts": [] + }, + { + "code": "340181", + "name": "巢湖", + "level": "THREE_LEVEL", + "geoname_id": 1815427, + "sub_districts": [] + }, + { + "code": "340122", + "name": "肥东", + "level": "THREE_LEVEL", + "geoname_id": 1811457, + "sub_districts": [] + }, + { + "code": "340123", + "name": "肥西", + "level": "THREE_LEVEL", + "geoname_id": 1811436, + "sub_districts": [] + }, + { + "code": "3401710000003", + "name": "合肥高新技术产业开发区", + "level": "THREE_LEVEL", + "geoname_id": 659010094, + "sub_districts": [] + }, + { + "code": "3401720000003", + "name": "合肥经济技术开发区", + "level": "THREE_LEVEL", + "geoname_id": 659010089, + "sub_districts": [] + }, + { + "code": "340124", + "name": "庐江", + "level": "THREE_LEVEL", + "geoname_id": 1802067, + "sub_districts": [] + }, + { + "code": "340103", + "name": "庐阳", + "level": "THREE_LEVEL", + "geoname_id": 6643477, + "sub_districts": [] + }, + { + "code": "3401040000003", + "name": "蜀山", + "level": "THREE_LEVEL", + "geoname_id": 6643478, + "sub_districts": [] + }, + { + "code": "340102", + "name": "瑶海", + "level": "THREE_LEVEL", + "geoname_id": 6643480, + "sub_districts": [] + } + ] + }, + { + "code": "340400", + "name": "淮南", + "level": "TWO_LEVEL", + "geoname_id": 1807680, + "sub_districts": [ + { + "code": "340405", + "name": "八公山", + "level": "THREE_LEVEL", + "geoname_id": 6643461, + "sub_districts": [] + }, + { + "code": "340402", + "name": "大通", + "level": "THREE_LEVEL", + "geoname_id": 6643459, + "sub_districts": [] + }, + { + "code": "340421", + "name": "凤台", + "level": "THREE_LEVEL", + "geoname_id": 1811225, + "sub_districts": [] + }, + { + "code": "340406", + "name": "潘集", + "level": "THREE_LEVEL", + "geoname_id": 6643457, + "sub_districts": [] + }, + { + "code": "340422", + "name": "寿县", + "level": "THREE_LEVEL", + "geoname_id": 1794783, + "sub_districts": [] + }, + { + "code": "340403", + "name": "田家庵", + "level": "THREE_LEVEL", + "geoname_id": 6643458, + "sub_districts": [] + }, + { + "code": "340404", + "name": "谢家集", + "level": "THREE_LEVEL", + "geoname_id": 6643460, + "sub_districts": [] + } + ] + }, + { + "code": "341000", + "name": "黄山", + "level": "TWO_LEVEL", + "geoname_id": 1792359, + "sub_districts": [ + { + "code": "341003", + "name": "黄山", + "level": "THREE_LEVEL", + "geoname_id": 6643462, + "sub_districts": [] + }, + { + "code": "341004", + "name": "徽州", + "level": "THREE_LEVEL", + "geoname_id": 6643463, + "sub_districts": [] + }, + { + "code": "341024", + "name": "祁门", + "level": "THREE_LEVEL", + "geoname_id": 1797969, + "sub_districts": [] + }, + { + "code": "341021", + "name": "歙县", + "level": "THREE_LEVEL", + "geoname_id": 1795534, + "sub_districts": [] + }, + { + "code": "341002", + "name": "屯溪", + "level": "THREE_LEVEL", + "geoname_id": 1792358, + "sub_districts": [] + }, + { + "code": "341022", + "name": "休宁", + "level": "THREE_LEVEL", + "geoname_id": 1788267, + "sub_districts": [] + }, + { + "code": "341023", + "name": "黟县", + "level": "THREE_LEVEL", + "geoname_id": 1816316, + "sub_districts": [] + } + ] + }, + { + "code": "341500", + "name": "六安", + "level": "TWO_LEVEL", + "geoname_id": 1802206, + "sub_districts": [ + { + "code": "341522", + "name": "霍邱", + "level": "THREE_LEVEL", + "geoname_id": 1806650, + "sub_districts": [] + }, + { + "code": "341525", + "name": "霍山", + "level": "THREE_LEVEL", + "geoname_id": 1806644, + "sub_districts": [] + }, + { + "code": "341502", + "name": "金安", + "level": "THREE_LEVEL", + "geoname_id": 6643452, + "sub_districts": [] + }, + { + "code": "341524", + "name": "金寨", + "level": "THREE_LEVEL", + "geoname_id": 1805306, + "sub_districts": [] + }, + { + "code": "341523", + "name": "舒城", + "level": "THREE_LEVEL", + "geoname_id": 1794543, + "sub_districts": [] + }, + { + "code": "341503", + "name": "裕安", + "level": "THREE_LEVEL", + "geoname_id": 6643453, + "sub_districts": [] + }, + { + "code": "341504", + "name": "叶集", + "level": "THREE_LEVEL", + "geoname_id": 341504, + "sub_districts": [] + } + ] + }, + { + "code": "340500", + "name": "马鞍山", + "level": "TWO_LEVEL", + "geoname_id": 1801618, + "sub_districts": [ + { + "code": "340506", + "name": "博望", + "level": "THREE_LEVEL", + "geoname_id": 1816254, + "sub_districts": [] + }, + { + "code": "340521", + "name": "当涂", + "level": "THREE_LEVEL", + "geoname_id": 1813850, + "sub_districts": [] + }, + { + "code": "340503", + "name": "花山", + "level": "THREE_LEVEL", + "geoname_id": 6643469, + "sub_districts": [] + }, + { + "code": "340522", + "name": "含山", + "level": "THREE_LEVEL", + "geoname_id": 1808888, + "sub_districts": [] + }, + { + "code": "340523", + "name": "和县", + "level": "THREE_LEVEL", + "geoname_id": 1808229, + "sub_districts": [] + }, + { + "code": "340504", + "name": "雨山", + "level": "THREE_LEVEL", + "geoname_id": 6643470, + "sub_districts": [] + } + ] + }, + { + "code": "341300", + "name": "宿州", + "level": "TWO_LEVEL", + "geoname_id": 1793743, + "sub_districts": [ + { + "code": "341321", + "name": "砀山", + "level": "THREE_LEVEL", + "geoname_id": 1813854, + "sub_districts": [] + }, + { + "code": "341323", + "name": "灵璧", + "level": "THREE_LEVEL", + "geoname_id": 1803553, + "sub_districts": [] + }, + { + "code": "341324", + "name": "泗县", + "level": "THREE_LEVEL", + "geoname_id": 1794110, + "sub_districts": [] + }, + { + "code": "341322", + "name": "萧县", + "level": "THREE_LEVEL", + "geoname_id": 1789930, + "sub_districts": [] + }, + { + "code": "341302", + "name": "埇桥", + "level": "THREE_LEVEL", + "geoname_id": 6643484, + "sub_districts": [] + } + ] + }, + { + "code": "340700", + "name": "铜陵", + "level": "TWO_LEVEL", + "geoname_id": 1792621, + "sub_districts": [ + { + "code": "340711", + "name": "郊区", + "level": "THREE_LEVEL", + "geoname_id": 6643487, + "sub_districts": [] + }, + { + "code": "340705", + "name": "铜官", + "level": "THREE_LEVEL", + "geoname_id": 340705, + "sub_districts": [] + }, + { + "code": "340706", + "name": "义安", + "level": "THREE_LEVEL", + "geoname_id": 340706, + "sub_districts": [] + }, + { + "code": "340722", + "name": "枞阳", + "level": "THREE_LEVEL", + "geoname_id": 1783651, + "sub_districts": [] + } + ] + }, + { + "code": "340200", + "name": "芜湖", + "level": "TWO_LEVEL", + "geoname_id": 1791236, + "sub_districts": [ + { + "code": "3402120000001", + "name": "繁昌", + "level": "THREE_LEVEL", + "geoname_id": 1811606, + "sub_districts": [] + }, + { + "code": "340202", + "name": "镜湖", + "level": "THREE_LEVEL", + "geoname_id": 6643467, + "sub_districts": [] + }, + { + "code": "340207", + "name": "鸠江", + "level": "THREE_LEVEL", + "geoname_id": 6643464, + "sub_districts": [] + }, + { + "code": "340223", + "name": "南陵", + "level": "THREE_LEVEL", + "geoname_id": 1799914, + "sub_districts": [] + }, + { + "code": "3402810000001", + "name": "无为", + "level": "THREE_LEVEL", + "geoname_id": 1790929, + "sub_districts": [] + }, + { + "code": "3402100000001", + "name": "湾沚", + "level": "THREE_LEVEL", + "geoname_id": 7069199, + "sub_districts": [] + }, + { + "code": "3402090000001", + "name": "弋江", + "level": "THREE_LEVEL", + "geoname_id": 7060473, + "sub_districts": [] + } + ] + }, + { + "code": "341800", + "name": "宣城", + "level": "TWO_LEVEL", + "geoname_id": 1788080, + "sub_districts": [ + { + "code": "3418820000001", + "name": "广德", + "level": "THREE_LEVEL", + "geoname_id": 1809937, + "sub_districts": [] + }, + { + "code": "341825", + "name": "旌德", + "level": "THREE_LEVEL", + "geoname_id": 1805681, + "sub_districts": [] + }, + { + "code": "341823", + "name": "泾县", + "level": "THREE_LEVEL", + "geoname_id": 1805570, + "sub_districts": [] + }, + { + "code": "341824", + "name": "绩溪", + "level": "THREE_LEVEL", + "geoname_id": 1805023, + "sub_districts": [] + }, + { + "code": "341821", + "name": "郎溪", + "level": "THREE_LEVEL", + "geoname_id": 1804495, + "sub_districts": [] + }, + { + "code": "341881", + "name": "宁国", + "level": "THREE_LEVEL", + "geoname_id": 1799385, + "sub_districts": [] + }, + { + "code": "341802", + "name": "宣州", + "level": "THREE_LEVEL", + "geoname_id": 1788079, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "82", + "name": "澳门", + "level": "ONE_LEVEL", + "geoname_id": 1821274, + "sub_districts": [] + }, + { + "code": "11", + "name": "北京", + "level": "ONE_LEVEL", + "geoname_id": 2038349, + "sub_districts": [ + { + "code": "110000", + "name": "北京", + "level": "TWO_LEVEL", + "geoname_id": 1816670, + "sub_districts": [ + { + "code": "110114", + "name": "昌平", + "level": "THREE_LEVEL", + "geoname_id": 2038153, + "sub_districts": [] + }, + { + "code": "110105", + "name": "朝阳", + "level": "THREE_LEVEL", + "geoname_id": 1815402, + "sub_districts": [] + }, + { + "code": "110101", + "name": "东城", + "level": "THREE_LEVEL", + "geoname_id": 1812638, + "sub_districts": [] + }, + { + "code": "110115", + "name": "大兴", + "level": "THREE_LEVEL", + "geoname_id": 1813286, + "sub_districts": [] + }, + { + "code": "110111", + "name": "房山", + "level": "THREE_LEVEL", + "geoname_id": 1811541, + "sub_districts": [] + }, + { + "code": "110106", + "name": "丰台", + "level": "THREE_LEVEL", + "geoname_id": 1811227, + "sub_districts": [] + }, + { + "code": "110108", + "name": "海淀", + "level": "THREE_LEVEL", + "geoname_id": 1809104, + "sub_districts": [] + }, + { + "code": "110116", + "name": "怀柔", + "level": "THREE_LEVEL", + "geoname_id": 2036763, + "sub_districts": [] + }, + { + "code": "110109", + "name": "门头沟", + "level": "THREE_LEVEL", + "geoname_id": 1800656, + "sub_districts": [] + }, + { + "code": "110118", + "name": "密云", + "level": "THREE_LEVEL", + "geoname_id": 8389521, + "sub_districts": [] + }, + { + "code": "110117", + "name": "平谷", + "level": "THREE_LEVEL", + "geoname_id": 2035468, + "sub_districts": [] + }, + { + "code": "110107", + "name": "石景山", + "level": "THREE_LEVEL", + "geoname_id": 1795253, + "sub_districts": [] + }, + { + "code": "110113", + "name": "顺义", + "level": "THREE_LEVEL", + "geoname_id": 2034753, + "sub_districts": [] + }, + { + "code": "110112", + "name": "通州", + "level": "THREE_LEVEL", + "geoname_id": 1792555, + "sub_districts": [] + }, + { + "code": "110102", + "name": "西城", + "level": "THREE_LEVEL", + "geoname_id": 1789635, + "sub_districts": [] + }, + { + "code": "110119", + "name": "延庆", + "level": "THREE_LEVEL", + "geoname_id": 2033457, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "50", + "name": "重庆", + "level": "ONE_LEVEL", + "geoname_id": 1814905, + "sub_districts": [ + { + "code": "500000", + "name": "重庆", + "level": "TWO_LEVEL", + "geoname_id": 1814906, + "sub_districts": [ + { + "code": "500109", + "name": "北碚", + "level": "THREE_LEVEL", + "geoname_id": 1909732, + "sub_districts": [] + }, + { + "code": "500113", + "name": "巴南", + "level": "THREE_LEVEL", + "geoname_id": 1909733, + "sub_districts": [] + }, + { + "code": "500120", + "name": "璧山", + "level": "THREE_LEVEL", + "geoname_id": 500120, + "sub_districts": [] + }, + { + "code": "500229", + "name": "城口", + "level": "THREE_LEVEL", + "geoname_id": 1815237, + "sub_districts": [] + }, + { + "code": "500115", + "name": "长寿", + "level": "THREE_LEVEL", + "geoname_id": 1815538, + "sub_districts": [] + }, + { + "code": "500104", + "name": "大渡口", + "level": "THREE_LEVEL", + "geoname_id": 1942237, + "sub_districts": [] + }, + { + "code": "500231", + "name": "垫江", + "level": "THREE_LEVEL", + "geoname_id": 1812936, + "sub_districts": [] + }, + { + "code": "500111", + "name": "大足", + "level": "THREE_LEVEL", + "geoname_id": 1813042, + "sub_districts": [] + }, + { + "code": "500230", + "name": "丰都", + "level": "THREE_LEVEL", + "geoname_id": 1811387, + "sub_districts": [] + }, + { + "code": "500236", + "name": "奉节", + "level": "THREE_LEVEL", + "geoname_id": 1811310, + "sub_districts": [] + }, + { + "code": "500102", + "name": "涪陵", + "level": "THREE_LEVEL", + "geoname_id": 1810978, + "sub_districts": [] + }, + { + "code": "500117", + "name": "合川", + "level": "THREE_LEVEL", + "geoname_id": 1808752, + "sub_districts": [] + }, + { + "code": "500105", + "name": "江北", + "level": "THREE_LEVEL", + "geoname_id": 1806413, + "sub_districts": [] + }, + { + "code": "500116", + "name": "江津", + "level": "THREE_LEVEL", + "geoname_id": 1806348, + "sub_districts": [] + }, + { + "code": "500107", + "name": "九龙坡", + "level": "THREE_LEVEL", + "geoname_id": 1805144, + "sub_districts": [] + }, + { + "code": "500154", + "name": "开州", + "level": "THREE_LEVEL", + "geoname_id": 500154, + "sub_districts": [] + }, + { + "code": "5001550000001", + "name": "梁平", + "level": "THREE_LEVEL", + "geoname_id": 1803993, + "sub_districts": [] + }, + { + "code": "500108", + "name": "南岸", + "level": "THREE_LEVEL", + "geoname_id": 1909730, + "sub_districts": [] + }, + { + "code": "500119", + "name": "南川", + "level": "THREE_LEVEL", + "geoname_id": 1800142, + "sub_districts": [] + }, + { + "code": "500243", + "name": "彭水", + "level": "THREE_LEVEL", + "geoname_id": 1798914, + "sub_districts": [] + }, + { + "code": "500110", + "name": "綦江", + "level": "THREE_LEVEL", + "geoname_id": 1798038, + "sub_districts": [] + }, + { + "code": "500114", + "name": "黔江", + "level": "THREE_LEVEL", + "geoname_id": 1798314, + "sub_districts": [] + }, + { + "code": "500153", + "name": "荣昌", + "level": "THREE_LEVEL", + "geoname_id": 1797123, + "sub_districts": [] + }, + { + "code": "500106", + "name": "沙坪坝", + "level": "THREE_LEVEL", + "geoname_id": 1795834, + "sub_districts": [] + }, + { + "code": "500240", + "name": "石柱", + "level": "THREE_LEVEL", + "geoname_id": 1794844, + "sub_districts": [] + }, + { + "code": "500151", + "name": "铜梁", + "level": "THREE_LEVEL", + "geoname_id": 1792625, + "sub_districts": [] + }, + { + "code": "500152", + "name": "潼南", + "level": "THREE_LEVEL", + "geoname_id": 1792607, + "sub_districts": [] + }, + { + "code": "5001560000001", + "name": "武隆", + "level": "THREE_LEVEL", + "geoname_id": 1791088, + "sub_districts": [] + }, + { + "code": "500237", + "name": "巫山", + "level": "THREE_LEVEL", + "geoname_id": 1791004, + "sub_districts": [] + }, + { + "code": "500238", + "name": "巫溪", + "level": "THREE_LEVEL", + "geoname_id": 1790901, + "sub_districts": [] + }, + { + "code": "500101", + "name": "万州", + "level": "THREE_LEVEL", + "geoname_id": 1791746, + "sub_districts": [] + }, + { + "code": "500241", + "name": "秀山", + "level": "THREE_LEVEL", + "geoname_id": 1788260, + "sub_districts": [] + }, + { + "code": "500112", + "name": "渝北", + "level": "THREE_LEVEL", + "geoname_id": 1909731, + "sub_districts": [] + }, + { + "code": "500118", + "name": "永川", + "level": "THREE_LEVEL", + "geoname_id": 8419426, + "sub_districts": [] + }, + { + "code": "500242", + "name": "酉阳", + "level": "THREE_LEVEL", + "geoname_id": 1786135, + "sub_districts": [] + }, + { + "code": "500235", + "name": "云阳", + "level": "THREE_LEVEL", + "geoname_id": 1785653, + "sub_districts": [] + }, + { + "code": "500103", + "name": "渝中", + "level": "THREE_LEVEL", + "geoname_id": 1816835, + "sub_districts": [] + }, + { + "code": "500233", + "name": "忠县", + "level": "THREE_LEVEL", + "geoname_id": 1784281, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "35", + "name": "福建", + "level": "ONE_LEVEL", + "geoname_id": 1811017, + "sub_districts": [ + { + "code": "350100", + "name": "福州", + "level": "TWO_LEVEL", + "geoname_id": 1810821, + "sub_districts": [ + { + "code": "3501120000001", + "name": "长乐", + "level": "THREE_LEVEL", + "geoname_id": 1815677, + "sub_districts": [] + }, + { + "code": "350104", + "name": "仓山", + "level": "THREE_LEVEL", + "geoname_id": 6607660, + "sub_districts": [] + }, + { + "code": "350181", + "name": "福清", + "level": "THREE_LEVEL", + "geoname_id": 1810940, + "sub_districts": [] + }, + { + "code": "350102", + "name": "鼓楼", + "level": "THREE_LEVEL", + "geoname_id": 6607645, + "sub_districts": [] + }, + { + "code": "350111", + "name": "晋安", + "level": "THREE_LEVEL", + "geoname_id": 6607663, + "sub_districts": [] + }, + { + "code": "350122", + "name": "连江", + "level": "THREE_LEVEL", + "geoname_id": 1803894, + "sub_districts": [] + }, + { + "code": "350123", + "name": "罗源", + "level": "THREE_LEVEL", + "geoname_id": 1801780, + "sub_districts": [] + }, + { + "code": "350121", + "name": "闽侯", + "level": "THREE_LEVEL", + "geoname_id": 1800476, + "sub_districts": [] + }, + { + "code": "350124", + "name": "闽清", + "level": "THREE_LEVEL", + "geoname_id": 1800461, + "sub_districts": [] + }, + { + "code": "350105", + "name": "马尾", + "level": "THREE_LEVEL", + "geoname_id": 6607662, + "sub_districts": [] + }, + { + "code": "350128", + "name": "平潭", + "level": "THREE_LEVEL", + "geoname_id": 1798676, + "sub_districts": [] + }, + { + "code": "350103", + "name": "台江", + "level": "THREE_LEVEL", + "geoname_id": 6607655, + "sub_districts": [] + }, + { + "code": "350125", + "name": "永泰", + "level": "THREE_LEVEL", + "geoname_id": 1786256, + "sub_districts": [] + } + ] + }, + { + "code": "350800", + "name": "龙岩", + "level": "TWO_LEVEL", + "geoname_id": 1802276, + "sub_districts": [ + { + "code": "350821", + "name": "长汀", + "level": "THREE_LEVEL", + "geoname_id": 1815513, + "sub_districts": [] + }, + { + "code": "350825", + "name": "连城", + "level": "THREE_LEVEL", + "geoname_id": 1804116, + "sub_districts": [] + }, + { + "code": "350823", + "name": "上杭", + "level": "THREE_LEVEL", + "geoname_id": 1796228, + "sub_districts": [] + }, + { + "code": "350824", + "name": "武平", + "level": "THREE_LEVEL", + "geoname_id": 1798846, + "sub_districts": [] + }, + { + "code": "350802", + "name": "新罗", + "level": "THREE_LEVEL", + "geoname_id": 6607506, + "sub_districts": [] + }, + { + "code": "350803", + "name": "永定", + "level": "THREE_LEVEL", + "geoname_id": 1786361, + "sub_districts": [] + }, + { + "code": "350881", + "name": "漳平", + "level": "THREE_LEVEL", + "geoname_id": 1805688, + "sub_districts": [] + } + ] + }, + { + "code": "350900", + "name": "宁德", + "level": "TWO_LEVEL", + "geoname_id": 1806097, + "sub_districts": [ + { + "code": "350981", + "name": "福安", + "level": "THREE_LEVEL", + "geoname_id": 1808872, + "sub_districts": [] + }, + { + "code": "350982", + "name": "福鼎", + "level": "THREE_LEVEL", + "geoname_id": 1811049, + "sub_districts": [] + }, + { + "code": "350922", + "name": "古田", + "level": "THREE_LEVEL", + "geoname_id": 1809199, + "sub_districts": [] + }, + { + "code": "350902", + "name": "蕉城", + "level": "THREE_LEVEL", + "geoname_id": 6607620, + "sub_districts": [] + }, + { + "code": "350923", + "name": "屏南", + "level": "THREE_LEVEL", + "geoname_id": 1798729, + "sub_districts": [] + }, + { + "code": "350924", + "name": "寿宁", + "level": "THREE_LEVEL", + "geoname_id": 1794791, + "sub_districts": [] + }, + { + "code": "350921", + "name": "霞浦", + "level": "THREE_LEVEL", + "geoname_id": 1789831, + "sub_districts": [] + }, + { + "code": "350925", + "name": "周宁", + "level": "THREE_LEVEL", + "geoname_id": 1784118, + "sub_districts": [] + }, + { + "code": "350926", + "name": "柘荣", + "level": "THREE_LEVEL", + "geoname_id": 1794762, + "sub_districts": [] + } + ] + }, + { + "code": "350700", + "name": "南平", + "level": "TWO_LEVEL", + "geoname_id": 1799838, + "sub_districts": [ + { + "code": "350723", + "name": "光泽", + "level": "THREE_LEVEL", + "geoname_id": 1809860, + "sub_districts": [] + }, + { + "code": "350783", + "name": "建瓯", + "level": "THREE_LEVEL", + "geoname_id": 1806166, + "sub_districts": [] + }, + { + "code": "350703", + "name": "建阳", + "level": "THREE_LEVEL", + "geoname_id": 1806120, + "sub_districts": [] + }, + { + "code": "350722", + "name": "浦城", + "level": "THREE_LEVEL", + "geoname_id": 1798529, + "sub_districts": [] + }, + { + "code": "350721", + "name": "顺昌", + "level": "THREE_LEVEL", + "geoname_id": 1794358, + "sub_districts": [] + }, + { + "code": "350781", + "name": "邵武", + "level": "THREE_LEVEL", + "geoname_id": 1795856, + "sub_districts": [] + }, + { + "code": "350724", + "name": "松溪", + "level": "THREE_LEVEL", + "geoname_id": 1793964, + "sub_districts": [] + }, + { + "code": "350782", + "name": "武夷山", + "level": "THREE_LEVEL", + "geoname_id": 1922013, + "sub_districts": [] + }, + { + "code": "350702", + "name": "延平", + "level": "THREE_LEVEL", + "geoname_id": 6607623, + "sub_districts": [] + }, + { + "code": "350725", + "name": "政和", + "level": "THREE_LEVEL", + "geoname_id": 1784700, + "sub_districts": [] + } + ] + }, + { + "code": "350300", + "name": "莆田", + "level": "TWO_LEVEL", + "geoname_id": 1798445, + "sub_districts": [ + { + "code": "350302", + "name": "城厢", + "level": "THREE_LEVEL", + "geoname_id": 6607724, + "sub_districts": [] + }, + { + "code": "350303", + "name": "涵江", + "level": "THREE_LEVEL", + "geoname_id": 6607729, + "sub_districts": [] + }, + { + "code": "350304", + "name": "荔城", + "level": "THREE_LEVEL", + "geoname_id": 11203926, + "sub_districts": [] + }, + { + "code": "350305", + "name": "秀屿", + "level": "THREE_LEVEL", + "geoname_id": 6607732, + "sub_districts": [] + }, + { + "code": "350322", + "name": "仙游", + "level": "THREE_LEVEL", + "geoname_id": 1790350, + "sub_districts": [] + } + ] + }, + { + "code": "350500", + "name": "泉州", + "level": "TWO_LEVEL", + "geoname_id": 1797353, + "sub_districts": [ + { + "code": "350524", + "name": "安溪", + "level": "THREE_LEVEL", + "geoname_id": 1817948, + "sub_districts": [] + }, + { + "code": "350526", + "name": "德化", + "level": "THREE_LEVEL", + "geoname_id": 1813027, + "sub_districts": [] + }, + { + "code": "350503", + "name": "丰泽", + "level": "THREE_LEVEL", + "geoname_id": 6607503, + "sub_districts": [] + }, + { + "code": "350521", + "name": "惠安", + "level": "THREE_LEVEL", + "geoname_id": 1806894, + "sub_districts": [] + }, + { + "code": "350582", + "name": "晋江", + "level": "THREE_LEVEL", + "geoname_id": 1797658, + "sub_districts": [] + }, + { + "code": "350527", + "name": "金门", + "level": "THREE_LEVEL", + "geoname_id": 350527, + "sub_districts": [] + }, + { + "code": "350502", + "name": "鲤城", + "level": "THREE_LEVEL", + "geoname_id": 6607502, + "sub_districts": [] + }, + { + "code": "350504", + "name": "洛江", + "level": "THREE_LEVEL", + "geoname_id": 6607504, + "sub_districts": [] + }, + { + "code": "350583", + "name": "南安", + "level": "THREE_LEVEL", + "geoname_id": 1800195, + "sub_districts": [] + }, + { + "code": "350505", + "name": "泉港", + "level": "THREE_LEVEL", + "geoname_id": 6607505, + "sub_districts": [] + }, + { + "code": "350581", + "name": "石狮", + "level": "THREE_LEVEL", + "geoname_id": 1921550, + "sub_districts": [] + }, + { + "code": "350525", + "name": "永春", + "level": "THREE_LEVEL", + "geoname_id": 1786369, + "sub_districts": [] + } + ] + }, + { + "code": "350400", + "name": "三明", + "level": "TWO_LEVEL", + "geoname_id": 1796663, + "sub_districts": [ + { + "code": "350425", + "name": "大田", + "level": "THREE_LEVEL", + "geoname_id": 1813464, + "sub_districts": [] + }, + { + "code": "350428", + "name": "将乐", + "level": "THREE_LEVEL", + "geoname_id": 1806304, + "sub_districts": [] + }, + { + "code": "350430", + "name": "建宁", + "level": "THREE_LEVEL", + "geoname_id": 1806168, + "sub_districts": [] + }, + { + "code": "350421", + "name": "明溪", + "level": "THREE_LEVEL", + "geoname_id": 1800492, + "sub_districts": [] + }, + { + "code": "350424", + "name": "宁化", + "level": "THREE_LEVEL", + "geoname_id": 1799377, + "sub_districts": [] + }, + { + "code": "350423", + "name": "清流", + "level": "THREE_LEVEL", + "geoname_id": 1797838, + "sub_districts": [] + }, + { + "code": "3504050000001", + "name": "沙县", + "level": "THREE_LEVEL", + "geoname_id": 1795756, + "sub_districts": [] + }, + { + "code": "3504040000000", + "name": "三元", + "level": "THREE_LEVEL", + "geoname_id": 6607705, + "sub_districts": [] + }, + { + "code": "350429", + "name": "泰宁", + "level": "THREE_LEVEL", + "geoname_id": 1793645, + "sub_districts": [] + }, + { + "code": "350481", + "name": "永安", + "level": "THREE_LEVEL", + "geoname_id": 1786401, + "sub_districts": [] + }, + { + "code": "350426", + "name": "尤溪", + "level": "THREE_LEVEL", + "geoname_id": 1786138, + "sub_districts": [] + } + ] + }, + { + "code": "350200", + "name": "厦门", + "level": "TWO_LEVEL", + "geoname_id": 1790645, + "sub_districts": [ + { + "code": "350205", + "name": "海沧", + "level": "THREE_LEVEL", + "geoname_id": 6607668, + "sub_districts": [] + }, + { + "code": "350206", + "name": "湖里", + "level": "THREE_LEVEL", + "geoname_id": 6607697, + "sub_districts": [] + }, + { + "code": "350211", + "name": "集美", + "level": "THREE_LEVEL", + "geoname_id": 6607699, + "sub_districts": [] + }, + { + "code": "350203", + "name": "思明", + "level": "THREE_LEVEL", + "geoname_id": 6607664, + "sub_districts": [] + }, + { + "code": "350212", + "name": "同安", + "level": "THREE_LEVEL", + "geoname_id": 1792716, + "sub_districts": [] + }, + { + "code": "350213", + "name": "翔安", + "level": "THREE_LEVEL", + "geoname_id": 7925580, + "sub_districts": [] + } + ] + }, + { + "code": "350600", + "name": "漳州", + "level": "TWO_LEVEL", + "geoname_id": 1785018, + "sub_districts": [ + { + "code": "3506050000001", + "name": "长泰", + "level": "THREE_LEVEL", + "geoname_id": 1815531, + "sub_districts": [] + }, + { + "code": "350626", + "name": "东山", + "level": "THREE_LEVEL", + "geoname_id": 1812269, + "sub_districts": [] + }, + { + "code": "350629", + "name": "华安", + "level": "THREE_LEVEL", + "geoname_id": 1807749, + "sub_districts": [] + }, + { + "code": "3506040000001", + "name": "龙海", + "level": "THREE_LEVEL", + "geoname_id": 1802632, + "sub_districts": [] + }, + { + "code": "350603", + "name": "龙文", + "level": "THREE_LEVEL", + "geoname_id": 1977996, + "sub_districts": [] + }, + { + "code": "350627", + "name": "南靖", + "level": "THREE_LEVEL", + "geoname_id": 1799957, + "sub_districts": [] + }, + { + "code": "350628", + "name": "平和", + "level": "THREE_LEVEL", + "geoname_id": 1798794, + "sub_districts": [] + }, + { + "code": "350602", + "name": "芗城", + "level": "THREE_LEVEL", + "geoname_id": 6607501, + "sub_districts": [] + }, + { + "code": "350622", + "name": "云霄", + "level": "THREE_LEVEL", + "geoname_id": 1785660, + "sub_districts": [] + }, + { + "code": "350624", + "name": "诏安", + "level": "THREE_LEVEL", + "geoname_id": 1784965, + "sub_districts": [] + }, + { + "code": "350623", + "name": "漳浦", + "level": "THREE_LEVEL", + "geoname_id": 1785103, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "44", + "name": "广东", + "level": "ONE_LEVEL", + "geoname_id": 1809935, + "sub_districts": [ + { + "code": "445100", + "name": "潮州", + "level": "TWO_LEVEL", + "geoname_id": 1815395, + "sub_districts": [ + { + "code": "445103", + "name": "潮安", + "level": "THREE_LEVEL", + "geoname_id": 1919706, + "sub_districts": [] + }, + { + "code": "445122", + "name": "饶平", + "level": "THREE_LEVEL", + "geoname_id": 1797241, + "sub_districts": [] + }, + { + "code": "445102", + "name": "湘桥", + "level": "THREE_LEVEL", + "geoname_id": 6571338, + "sub_districts": [] + } + ] + }, + { + "code": "441900", + "name": "东莞", + "level": "TWO_LEVEL", + "geoname_id": 1812545, + "sub_districts": [ + { + "code": "441900", + "name": "东莞", + "level": "THREE_LEVEL", + "geoname_id": 1812532, + "sub_districts": [] + } + ] + }, + { + "code": "440600", + "name": "佛山", + "level": "TWO_LEVEL", + "geoname_id": 1811103, + "sub_districts": [ + { + "code": "440604", + "name": "禅城", + "level": "THREE_LEVEL", + "geoname_id": 6571340, + "sub_districts": [] + }, + { + "code": "440608", + "name": "高明", + "level": "THREE_LEVEL", + "geoname_id": 1810452, + "sub_districts": [] + }, + { + "code": "440605", + "name": "南海", + "level": "THREE_LEVEL", + "geoname_id": 1800036, + "sub_districts": [] + }, + { + "code": "440606", + "name": "顺德", + "level": "THREE_LEVEL", + "geoname_id": 1814082, + "sub_districts": [] + }, + { + "code": "440607", + "name": "三水", + "level": "THREE_LEVEL", + "geoname_id": 1796607, + "sub_districts": [] + } + ] + }, + { + "code": "440100", + "name": "广州", + "level": "TWO_LEVEL", + "geoname_id": 1809858, + "sub_districts": [ + { + "code": "440111", + "name": "白云", + "level": "THREE_LEVEL", + "geoname_id": 6571346, + "sub_districts": [] + }, + { + "code": "440117", + "name": "从化", + "level": "THREE_LEVEL", + "geoname_id": 1805880, + "sub_districts": [] + }, + { + "code": "440114", + "name": "花都", + "level": "THREE_LEVEL", + "geoname_id": 1807008, + "sub_districts": [] + }, + { + "code": "440112", + "name": "黄埔", + "level": "THREE_LEVEL", + "geoname_id": 6571343, + "sub_districts": [] + }, + { + "code": "440105", + "name": "海珠", + "level": "THREE_LEVEL", + "geoname_id": 6571341, + "sub_districts": [] + }, + { + "code": "440103", + "name": "荔湾", + "level": "THREE_LEVEL", + "geoname_id": 6571345, + "sub_districts": [] + }, + { + "code": "440115", + "name": "南沙", + "level": "THREE_LEVEL", + "geoname_id": 6571339, + "sub_districts": [] + }, + { + "code": "440113", + "name": "番禺", + "level": "THREE_LEVEL", + "geoname_id": 1799000, + "sub_districts": [] + }, + { + "code": "440106", + "name": "天河", + "level": "THREE_LEVEL", + "geoname_id": 6571342, + "sub_districts": [] + }, + { + "code": "440104", + "name": "越秀", + "level": "THREE_LEVEL", + "geoname_id": 6571344, + "sub_districts": [] + }, + { + "code": "440118", + "name": "增城", + "level": "THREE_LEVEL", + "geoname_id": 1785436, + "sub_districts": [] + } + ] + }, + { + "code": "441600", + "name": "河源", + "level": "TWO_LEVEL", + "geoname_id": 1786112, + "sub_districts": [ + { + "code": "441625", + "name": "东源", + "level": "THREE_LEVEL", + "geoname_id": 1917078, + "sub_districts": [] + }, + { + "code": "441624", + "name": "和平", + "level": "THREE_LEVEL", + "geoname_id": 1808338, + "sub_districts": [] + }, + { + "code": "441622", + "name": "龙川", + "level": "THREE_LEVEL", + "geoname_id": 1802678, + "sub_districts": [] + }, + { + "code": "441623", + "name": "连平", + "level": "THREE_LEVEL", + "geoname_id": 1803890, + "sub_districts": [] + }, + { + "code": "441602", + "name": "源城", + "level": "THREE_LEVEL", + "geoname_id": 6571350, + "sub_districts": [] + }, + { + "code": "441621", + "name": "紫金", + "level": "THREE_LEVEL", + "geoname_id": 1783725, + "sub_districts": [] + } + ] + }, + { + "code": "441300", + "name": "惠州", + "level": "TWO_LEVEL", + "geoname_id": 1806776, + "sub_districts": [ + { + "code": "441322", + "name": "博罗", + "level": "THREE_LEVEL", + "geoname_id": 1816276, + "sub_districts": [] + }, + { + "code": "441302", + "name": "惠城", + "level": "THREE_LEVEL", + "geoname_id": 6571331, + "sub_districts": [] + }, + { + "code": "441323", + "name": "惠东", + "level": "THREE_LEVEL", + "geoname_id": 1806874, + "sub_districts": [] + }, + { + "code": "441303", + "name": "惠阳", + "level": "THREE_LEVEL", + "geoname_id": 1806781, + "sub_districts": [] + }, + { + "code": "441324", + "name": "龙门", + "level": "THREE_LEVEL", + "geoname_id": 1802505, + "sub_districts": [] + } + ] + }, + { + "code": "440700", + "name": "江门", + "level": "TWO_LEVEL", + "geoname_id": 1806299, + "sub_districts": [ + { + "code": "440785", + "name": "恩平", + "level": "THREE_LEVEL", + "geoname_id": 1811721, + "sub_districts": [] + }, + { + "code": "440784", + "name": "鹤山", + "level": "THREE_LEVEL", + "geoname_id": 1808306, + "sub_districts": [] + }, + { + "code": "440704", + "name": "江海", + "level": "THREE_LEVEL", + "geoname_id": 6571324, + "sub_districts": [] + }, + { + "code": "440783", + "name": "开平", + "level": "THREE_LEVEL", + "geoname_id": 1804862, + "sub_districts": [] + }, + { + "code": "440703", + "name": "蓬江", + "level": "THREE_LEVEL", + "geoname_id": 440703, + "sub_districts": [] + }, + { + "code": "440781", + "name": "台山", + "level": "THREE_LEVEL", + "geoname_id": 1793700, + "sub_districts": [] + }, + { + "code": "440705", + "name": "新会", + "level": "THREE_LEVEL", + "geoname_id": 1806882, + "sub_districts": [] + } + ] + }, + { + "code": "445200", + "name": "揭阳", + "level": "TWO_LEVEL", + "geoname_id": 1797121, + "sub_districts": [ + { + "code": "445224", + "name": "惠来", + "level": "THREE_LEVEL", + "geoname_id": 1806856, + "sub_districts": [] + }, + { + "code": "445203", + "name": "揭东", + "level": "THREE_LEVEL", + "geoname_id": 1919661, + "sub_districts": [] + }, + { + "code": "445222", + "name": "揭西", + "level": "THREE_LEVEL", + "geoname_id": 1805831, + "sub_districts": [] + }, + { + "code": "445281", + "name": "普宁", + "level": "THREE_LEVEL", + "geoname_id": 1802940, + "sub_districts": [] + }, + { + "code": "445202", + "name": "榕城", + "level": "THREE_LEVEL", + "geoname_id": 6571337, + "sub_districts": [] + } + ] + }, + { + "code": "440900", + "name": "茂名", + "level": "TWO_LEVEL", + "geoname_id": 1801180, + "sub_districts": [ + { + "code": "440904", + "name": "电白", + "level": "THREE_LEVEL", + "geoname_id": 1812951, + "sub_districts": [] + }, + { + "code": "440981", + "name": "高州", + "level": "THREE_LEVEL", + "geoname_id": 1810293, + "sub_districts": [] + }, + { + "code": "440982", + "name": "化州", + "level": "THREE_LEVEL", + "geoname_id": 1806959, + "sub_districts": [] + }, + { + "code": "440902", + "name": "茂南", + "level": "THREE_LEVEL", + "geoname_id": 6571321, + "sub_districts": [] + }, + { + "code": "440983", + "name": "信宜", + "level": "THREE_LEVEL", + "geoname_id": 1788511, + "sub_districts": [] + } + ] + }, + { + "code": "441400", + "name": "梅州", + "level": "TWO_LEVEL", + "geoname_id": 1800794, + "sub_districts": [ + { + "code": "441422", + "name": "大埔", + "level": "THREE_LEVEL", + "geoname_id": 1814563, + "sub_districts": [] + }, + { + "code": "441423", + "name": "丰顺", + "level": "THREE_LEVEL", + "geoname_id": 1811233, + "sub_districts": [] + }, + { + "code": "441427", + "name": "蕉岭", + "level": "THREE_LEVEL", + "geoname_id": 1806039, + "sub_districts": [] + }, + { + "code": "441402", + "name": "梅江", + "level": "THREE_LEVEL", + "geoname_id": 6571355, + "sub_districts": [] + }, + { + "code": "441403", + "name": "梅县", + "level": "THREE_LEVEL", + "geoname_id": 8540996, + "sub_districts": [] + }, + { + "code": "441426", + "name": "平远", + "level": "THREE_LEVEL", + "geoname_id": 1798621, + "sub_districts": [] + }, + { + "code": "441424", + "name": "五华", + "level": "THREE_LEVEL", + "geoname_id": 1791232, + "sub_districts": [] + }, + { + "code": "441481", + "name": "兴宁", + "level": "THREE_LEVEL", + "geoname_id": 1788956, + "sub_districts": [] + } + ] + }, + { + "code": "441800", + "name": "清远", + "level": "TWO_LEVEL", + "geoname_id": 1797945, + "sub_districts": [ + { + "code": "441821", + "name": "佛冈", + "level": "THREE_LEVEL", + "geoname_id": 1811107, + "sub_districts": [] + }, + { + "code": "441826", + "name": "连南", + "level": "THREE_LEVEL", + "geoname_id": 1803892, + "sub_districts": [] + }, + { + "code": "441825", + "name": "连山", + "level": "THREE_LEVEL", + "geoname_id": 1803881, + "sub_districts": [] + }, + { + "code": "441882", + "name": "连州", + "level": "THREE_LEVEL", + "geoname_id": 1803854, + "sub_districts": [] + }, + { + "code": "441802", + "name": "清城", + "level": "THREE_LEVEL", + "geoname_id": 6571353, + "sub_districts": [] + }, + { + "code": "441803", + "name": "清新", + "level": "THREE_LEVEL", + "geoname_id": 6571354, + "sub_districts": [] + }, + { + "code": "441881", + "name": "英德", + "level": "THREE_LEVEL", + "geoname_id": 1786633, + "sub_districts": [] + }, + { + "code": "441823", + "name": "阳山", + "level": "THREE_LEVEL", + "geoname_id": 1787334, + "sub_districts": [] + } + ] + }, + { + "code": "440200", + "name": "韶关", + "level": "TWO_LEVEL", + "geoname_id": 1795874, + "sub_districts": [ + { + "code": "440281", + "name": "乐昌", + "level": "THREE_LEVEL", + "geoname_id": 1804254, + "sub_districts": [] + }, + { + "code": "440282", + "name": "南雄", + "level": "THREE_LEVEL", + "geoname_id": 1799646, + "sub_districts": [] + }, + { + "code": "440205", + "name": "曲江", + "level": "THREE_LEVEL", + "geoname_id": 1797322, + "sub_districts": [] + }, + { + "code": "440224", + "name": "仁化", + "level": "THREE_LEVEL", + "geoname_id": 1797193, + "sub_districts": [] + }, + { + "code": "440232", + "name": "乳源", + "level": "THREE_LEVEL", + "geoname_id": 1797012, + "sub_districts": [] + }, + { + "code": "440222", + "name": "始兴", + "level": "THREE_LEVEL", + "geoname_id": 1794911, + "sub_districts": [] + }, + { + "code": "440203", + "name": "武江", + "level": "THREE_LEVEL", + "geoname_id": 6571351, + "sub_districts": [] + }, + { + "code": "440229", + "name": "翁源", + "level": "THREE_LEVEL", + "geoname_id": 1791497, + "sub_districts": [] + }, + { + "code": "440233", + "name": "新丰", + "level": "THREE_LEVEL", + "geoname_id": 1789070, + "sub_districts": [] + }, + { + "code": "440204", + "name": "浈江", + "level": "THREE_LEVEL", + "geoname_id": 6571352, + "sub_districts": [] + } + ] + }, + { + "code": "440500", + "name": "汕头", + "level": "TWO_LEVEL", + "geoname_id": 1795932, + "sub_districts": [ + { + "code": "440515", + "name": "澄海", + "level": "THREE_LEVEL", + "geoname_id": 1815270, + "sub_districts": [] + }, + { + "code": "440514", + "name": "潮南", + "level": "THREE_LEVEL", + "geoname_id": 6571333, + "sub_districts": [] + }, + { + "code": "440513", + "name": "潮阳", + "level": "THREE_LEVEL", + "geoname_id": 1815399, + "sub_districts": [] + }, + { + "code": "440512", + "name": "濠江", + "level": "THREE_LEVEL", + "geoname_id": 6571334, + "sub_districts": [] + }, + { + "code": "440511", + "name": "金平", + "level": "THREE_LEVEL", + "geoname_id": 6571336, + "sub_districts": [] + }, + { + "code": "440507", + "name": "龙湖", + "level": "THREE_LEVEL", + "geoname_id": 6571335, + "sub_districts": [] + }, + { + "code": "440523", + "name": "南澳", + "level": "THREE_LEVEL", + "geoname_id": 1800190, + "sub_districts": [] + } + ] + }, + { + "code": "441500", + "name": "汕尾", + "level": "TWO_LEVEL", + "geoname_id": 6571356, + "sub_districts": [ + { + "code": "441521", + "name": "海丰", + "level": "THREE_LEVEL", + "geoname_id": 1809098, + "sub_districts": [] + }, + { + "code": "441581", + "name": "陆丰", + "level": "THREE_LEVEL", + "geoname_id": 1802130, + "sub_districts": [] + }, + { + "code": "441523", + "name": "陆河", + "level": "THREE_LEVEL", + "geoname_id": 6571357, + "sub_districts": [] + }, + { + "code": "441502", + "name": "城区", + "level": "THREE_LEVEL", + "geoname_id": 6571332, + "sub_districts": [] + } + ] + }, + { + "code": "440300", + "name": "深圳", + "level": "TWO_LEVEL", + "geoname_id": 1795565, + "sub_districts": [ + { + "code": "440306", + "name": "宝安", + "level": "THREE_LEVEL", + "geoname_id": 1816983, + "sub_districts": [] + }, + { + "code": "440304", + "name": "福田", + "level": "THREE_LEVEL", + "geoname_id": 6571328, + "sub_districts": [] + }, + { + "code": "440311", + "name": "光明", + "level": "THREE_LEVEL", + "geoname_id": 11876377, + "sub_districts": [] + }, + { + "code": "440307", + "name": "龙岗", + "level": "THREE_LEVEL", + "geoname_id": 6571330, + "sub_districts": [] + }, + { + "code": "440303", + "name": "罗湖", + "level": "THREE_LEVEL", + "geoname_id": 6571358, + "sub_districts": [] + }, + { + "code": "440309", + "name": "龙华", + "level": "THREE_LEVEL", + "geoname_id": 11876378, + "sub_districts": [] + }, + { + "code": "440305", + "name": "南山", + "level": "THREE_LEVEL", + "geoname_id": 6571327, + "sub_districts": [] + }, + { + "code": "440310", + "name": "坪山", + "level": "THREE_LEVEL", + "geoname_id": 11876379, + "sub_districts": [] + }, + { + "code": "440308", + "name": "盐田", + "level": "THREE_LEVEL", + "geoname_id": 6571329, + "sub_districts": [] + } + ] + }, + { + "code": "445300", + "name": "云浮", + "level": "TWO_LEVEL", + "geoname_id": 1785725, + "sub_districts": [ + { + "code": "445381", + "name": "罗定", + "level": "THREE_LEVEL", + "geoname_id": 1801965, + "sub_districts": [] + }, + { + "code": "445321", + "name": "新兴", + "level": "THREE_LEVEL", + "geoname_id": 1788555, + "sub_districts": [] + }, + { + "code": "445303", + "name": "云安", + "level": "THREE_LEVEL", + "geoname_id": 1912213, + "sub_districts": [] + }, + { + "code": "445302", + "name": "云城", + "level": "THREE_LEVEL", + "geoname_id": 6571359, + "sub_districts": [] + }, + { + "code": "445322", + "name": "郁南", + "level": "THREE_LEVEL", + "geoname_id": 1785745, + "sub_districts": [] + } + ] + }, + { + "code": "441700", + "name": "阳江", + "level": "TWO_LEVEL", + "geoname_id": 1806408, + "sub_districts": [ + { + "code": "441702", + "name": "江城", + "level": "THREE_LEVEL", + "geoname_id": 6571322, + "sub_districts": [] + }, + { + "code": "441781", + "name": "阳春", + "level": "THREE_LEVEL", + "geoname_id": 1787659, + "sub_districts": [] + }, + { + "code": "441704", + "name": "阳东", + "level": "THREE_LEVEL", + "geoname_id": 1913429, + "sub_districts": [] + }, + { + "code": "441721", + "name": "阳西", + "level": "THREE_LEVEL", + "geoname_id": 1913374, + "sub_districts": [] + } + ] + }, + { + "code": "440400", + "name": "珠海", + "level": "TWO_LEVEL", + "geoname_id": 1790437, + "sub_districts": [ + { + "code": "440403", + "name": "斗门", + "level": "THREE_LEVEL", + "geoname_id": 1811991, + "sub_districts": [] + }, + { + "code": "440404", + "name": "金湾", + "level": "THREE_LEVEL", + "geoname_id": 6571325, + "sub_districts": [] + }, + { + "code": "440402", + "name": "香洲", + "level": "THREE_LEVEL", + "geoname_id": 6571326, + "sub_districts": [] + } + ] + }, + { + "code": "440800", + "name": "湛江", + "level": "TWO_LEVEL", + "geoname_id": 1784990, + "sub_districts": [ + { + "code": "440802", + "name": "赤坎", + "level": "THREE_LEVEL", + "geoname_id": 6571318, + "sub_districts": [] + }, + { + "code": "440881", + "name": "廉江", + "level": "THREE_LEVEL", + "geoname_id": 1803895, + "sub_districts": [] + }, + { + "code": "440882", + "name": "雷州", + "level": "THREE_LEVEL", + "geoname_id": 6571360, + "sub_districts": [] + }, + { + "code": "440811", + "name": "麻章", + "level": "THREE_LEVEL", + "geoname_id": 6571319, + "sub_districts": [] + }, + { + "code": "440804", + "name": "坡头", + "level": "THREE_LEVEL", + "geoname_id": 6571317, + "sub_districts": [] + }, + { + "code": "440823", + "name": "遂溪", + "level": "THREE_LEVEL", + "geoname_id": 1793886, + "sub_districts": [] + }, + { + "code": "440883", + "name": "吴川", + "level": "THREE_LEVEL", + "geoname_id": 1791334, + "sub_districts": [] + }, + { + "code": "440803", + "name": "霞山", + "level": "THREE_LEVEL", + "geoname_id": 6571316, + "sub_districts": [] + }, + { + "code": "440825", + "name": "徐闻", + "level": "THREE_LEVEL", + "geoname_id": 1787836, + "sub_districts": [] + } + ] + }, + { + "code": "441200", + "name": "肇庆", + "level": "TWO_LEVEL", + "geoname_id": 1784853, + "sub_districts": [ + { + "code": "441203", + "name": "鼎湖", + "level": "THREE_LEVEL", + "geoname_id": 6571349, + "sub_districts": [] + }, + { + "code": "441226", + "name": "德庆", + "level": "THREE_LEVEL", + "geoname_id": 1812980, + "sub_districts": [] + }, + { + "code": "441202", + "name": "端州", + "level": "THREE_LEVEL", + "geoname_id": 6571348, + "sub_districts": [] + }, + { + "code": "441225", + "name": "封开", + "level": "THREE_LEVEL", + "geoname_id": 1811306, + "sub_districts": [] + }, + { + "code": "441223", + "name": "广宁", + "level": "THREE_LEVEL", + "geoname_id": 1809893, + "sub_districts": [] + }, + { + "code": "441204", + "name": "高要", + "level": "THREE_LEVEL", + "geoname_id": 1800201, + "sub_districts": [] + }, + { + "code": "441224", + "name": "怀集", + "level": "THREE_LEVEL", + "geoname_id": 1807686, + "sub_districts": [] + }, + { + "code": "441284", + "name": "四会", + "level": "THREE_LEVEL", + "geoname_id": 1794252, + "sub_districts": [] + } + ] + }, + { + "code": "442000", + "name": "中山", + "level": "TWO_LEVEL", + "geoname_id": 1915223, + "sub_districts": [ + { + "code": "442000", + "name": "中山", + "level": "THREE_LEVEL", + "geoname_id": 1784313, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "62", + "name": "甘肃", + "level": "ONE_LEVEL", + "geoname_id": 1810676, + "sub_districts": [ + { + "code": "620400", + "name": "白银", + "level": "TWO_LEVEL", + "geoname_id": 1817240, + "sub_districts": [ + { + "code": "620402", + "name": "白银", + "level": "THREE_LEVEL", + "geoname_id": 6642866, + "sub_districts": [] + }, + { + "code": "620422", + "name": "会宁", + "level": "THREE_LEVEL", + "geoname_id": 1806817, + "sub_districts": [] + }, + { + "code": "620423", + "name": "景泰", + "level": "THREE_LEVEL", + "geoname_id": 1786442, + "sub_districts": [] + }, + { + "code": "620421", + "name": "靖远", + "level": "THREE_LEVEL", + "geoname_id": 1805549, + "sub_districts": [] + }, + { + "code": "620403", + "name": "平川", + "level": "THREE_LEVEL", + "geoname_id": 8595855, + "sub_districts": [] + } + ] + }, + { + "code": "621100", + "name": "定西", + "level": "TWO_LEVEL", + "geoname_id": 1812749, + "sub_districts": [ + { + "code": "621102", + "name": "安定", + "level": "THREE_LEVEL", + "geoname_id": 1812739, + "sub_districts": [] + }, + { + "code": "621124", + "name": "临洮", + "level": "THREE_LEVEL", + "geoname_id": 1803347, + "sub_districts": [] + }, + { + "code": "621122", + "name": "陇西", + "level": "THREE_LEVEL", + "geoname_id": 1802288, + "sub_districts": [] + }, + { + "code": "621126", + "name": "岷县", + "level": "THREE_LEVEL", + "geoname_id": 1800454, + "sub_districts": [] + }, + { + "code": "621121", + "name": "通渭", + "level": "THREE_LEVEL", + "geoname_id": 1792559, + "sub_districts": [] + }, + { + "code": "621123", + "name": "渭源", + "level": "THREE_LEVEL", + "geoname_id": 1791570, + "sub_districts": [] + }, + { + "code": "621125", + "name": "漳县", + "level": "THREE_LEVEL", + "geoname_id": 1785047, + "sub_districts": [] + } + ] + }, + { + "code": "623000", + "name": "甘南", + "level": "TWO_LEVEL", + "geoname_id": 1810686, + "sub_districts": [ + { + "code": "623024", + "name": "迭部", + "level": "THREE_LEVEL", + "geoname_id": 1793028, + "sub_districts": [] + }, + { + "code": "623001", + "name": "合作", + "level": "THREE_LEVEL", + "geoname_id": 6642882, + "sub_districts": [] + }, + { + "code": "623026", + "name": "碌曲", + "level": "THREE_LEVEL", + "geoname_id": 1801747, + "sub_districts": [] + }, + { + "code": "623021", + "name": "临潭", + "level": "THREE_LEVEL", + "geoname_id": 1803348, + "sub_districts": [] + }, + { + "code": "623025", + "name": "玛曲", + "level": "THREE_LEVEL", + "geoname_id": 1801080, + "sub_districts": [] + }, + { + "code": "623027", + "name": "夏河", + "level": "THREE_LEVEL", + "geoname_id": 1790711, + "sub_districts": [] + }, + { + "code": "623022", + "name": "卓尼", + "level": "THREE_LEVEL", + "geoname_id": 1804995, + "sub_districts": [] + }, + { + "code": "623023", + "name": "舟曲", + "level": "THREE_LEVEL", + "geoname_id": 1783955, + "sub_districts": [] + } + ] + }, + { + "code": "620300", + "name": "金昌", + "level": "TWO_LEVEL", + "geoname_id": 1805733, + "sub_districts": [ + { + "code": "620302", + "name": "金川", + "level": "THREE_LEVEL", + "geoname_id": 6642873, + "sub_districts": [] + }, + { + "code": "620321", + "name": "永昌", + "level": "THREE_LEVEL", + "geoname_id": 1786375, + "sub_districts": [] + } + ] + }, + { + "code": "620900", + "name": "酒泉", + "level": "TWO_LEVEL", + "geoname_id": 1279945, + "sub_districts": [ + { + "code": "620924", + "name": "阿克塞", + "level": "THREE_LEVEL", + "geoname_id": 1281781, + "sub_districts": [] + }, + { + "code": "620982", + "name": "敦煌", + "level": "THREE_LEVEL", + "geoname_id": 1529531, + "sub_districts": [] + }, + { + "code": "620922", + "name": "瓜州", + "level": "THREE_LEVEL", + "geoname_id": 1529644, + "sub_districts": [] + }, + { + "code": "620921", + "name": "金塔", + "level": "THREE_LEVEL", + "geoname_id": 1280943, + "sub_districts": [] + }, + { + "code": "620923", + "name": "肃北", + "level": "THREE_LEVEL", + "geoname_id": 1279962, + "sub_districts": [] + }, + { + "code": "620902", + "name": "肃州", + "level": "THREE_LEVEL", + "geoname_id": 1280930, + "sub_districts": [] + }, + { + "code": "620981", + "name": "玉门", + "level": "THREE_LEVEL", + "geoname_id": 1279547, + "sub_districts": [] + } + ] + }, + { + "code": "620200", + "name": "嘉峪关", + "level": "TWO_LEVEL", + "geoname_id": 1280957, + "sub_districts": [ + { + "code": "620200", + "name": "嘉峪关", + "level": "THREE_LEVEL", + "geoname_id": 1280956, + "sub_districts": [] + } + ] + }, + { + "code": "621200", + "name": "陇南", + "level": "TWO_LEVEL", + "geoname_id": 1802494, + "sub_districts": [ + { + "code": "621221", + "name": "成县", + "level": "THREE_LEVEL", + "geoname_id": 1815189, + "sub_districts": [] + }, + { + "code": "621223", + "name": "宕昌", + "level": "THREE_LEVEL", + "geoname_id": 1813874, + "sub_districts": [] + }, + { + "code": "621227", + "name": "徽县", + "level": "THREE_LEVEL", + "geoname_id": 1806791, + "sub_districts": [] + }, + { + "code": "621224", + "name": "康县", + "level": "THREE_LEVEL", + "geoname_id": 1804816, + "sub_districts": [] + }, + { + "code": "621228", + "name": "两当", + "level": "THREE_LEVEL", + "geoname_id": 1804080, + "sub_districts": [] + }, + { + "code": "621226", + "name": "礼县", + "level": "THREE_LEVEL", + "geoname_id": 1802815, + "sub_districts": [] + }, + { + "code": "621202", + "name": "武都", + "level": "THREE_LEVEL", + "geoname_id": 1791288, + "sub_districts": [] + }, + { + "code": "621222", + "name": "文县", + "level": "THREE_LEVEL", + "geoname_id": 1791408, + "sub_districts": [] + }, + { + "code": "621225", + "name": "西和", + "level": "THREE_LEVEL", + "geoname_id": 1789436, + "sub_districts": [] + } + ] + }, + { + "code": "622900", + "name": "临夏", + "level": "TWO_LEVEL", + "geoname_id": 1803330, + "sub_districts": [ + { + "code": "622926", + "name": "东乡族", + "level": "THREE_LEVEL", + "geoname_id": 1812151, + "sub_districts": [] + }, + { + "code": "622924", + "name": "广河", + "level": "THREE_LEVEL", + "geoname_id": 1809919, + "sub_districts": [] + }, + { + "code": "622925", + "name": "和政", + "level": "THREE_LEVEL", + "geoname_id": 1808190, + "sub_districts": [] + }, + { + "code": "622927", + "name": "积石山", + "level": "THREE_LEVEL", + "geoname_id": 1805272, + "sub_districts": [] + }, + { + "code": "622922", + "name": "康乐", + "level": "THREE_LEVEL", + "geoname_id": 1804824, + "sub_districts": [] + }, + { + "code": "622901", + "name": "临夏市", + "level": "THREE_LEVEL", + "geoname_id": 1803322, + "sub_districts": [] + }, + { + "code": "622921", + "name": "临夏县", + "level": "THREE_LEVEL", + "geoname_id": 1803321, + "sub_districts": [] + }, + { + "code": "622923", + "name": "永靖", + "level": "THREE_LEVEL", + "geoname_id": 1786323, + "sub_districts": [] + } + ] + }, + { + "code": "620100", + "name": "兰州", + "level": "TWO_LEVEL", + "geoname_id": 1804430, + "sub_districts": [ + { + "code": "620105", + "name": "安宁", + "level": "THREE_LEVEL", + "geoname_id": 6642869, + "sub_districts": [] + }, + { + "code": "620102", + "name": "城关", + "level": "THREE_LEVEL", + "geoname_id": 6642872, + "sub_districts": [] + }, + { + "code": "620122", + "name": "皋兰", + "level": "THREE_LEVEL", + "geoname_id": 1810492, + "sub_districts": [] + }, + { + "code": "620111", + "name": "红古", + "level": "THREE_LEVEL", + "geoname_id": 6642871, + "sub_districts": [] + }, + { + "code": "620171", + "name": "兰州", + "level": "THREE_LEVEL", + "geoname_id": 1804429, + "sub_districts": [] + }, + { + "code": "620103", + "name": "七里河", + "level": "THREE_LEVEL", + "geoname_id": 6642868, + "sub_districts": [] + }, + { + "code": "620104", + "name": "西固", + "level": "THREE_LEVEL", + "geoname_id": 6642870, + "sub_districts": [] + }, + { + "code": "620121", + "name": "永登", + "level": "THREE_LEVEL", + "geoname_id": 1786366, + "sub_districts": [] + }, + { + "code": "620123", + "name": "榆中", + "level": "THREE_LEVEL", + "geoname_id": 1785532, + "sub_districts": [] + } + ] + }, + { + "code": "620800", + "name": "平凉", + "level": "TWO_LEVEL", + "geoname_id": 1798760, + "sub_districts": [ + { + "code": "620823", + "name": "崇信", + "level": "THREE_LEVEL", + "geoname_id": 1814881, + "sub_districts": [] + }, + { + "code": "6208810000001", + "name": "华亭", + "level": "THREE_LEVEL", + "geoname_id": 1807017, + "sub_districts": [] + }, + { + "code": "620821", + "name": "泾川", + "level": "THREE_LEVEL", + "geoname_id": 1805686, + "sub_districts": [] + }, + { + "code": "620826", + "name": "静宁", + "level": "THREE_LEVEL", + "geoname_id": 1805604, + "sub_districts": [] + }, + { + "code": "620802", + "name": "崆峒", + "level": "THREE_LEVEL", + "geoname_id": 1798757, + "sub_districts": [] + }, + { + "code": "620822", + "name": "灵台", + "level": "THREE_LEVEL", + "geoname_id": 1803459, + "sub_districts": [] + }, + { + "code": "620825", + "name": "庄浪", + "level": "THREE_LEVEL", + "geoname_id": 1784051, + "sub_districts": [] + } + ] + }, + { + "code": "621000", + "name": "庆阳", + "level": "TWO_LEVEL", + "geoname_id": 1797652, + "sub_districts": [ + { + "code": "621023", + "name": "华池", + "level": "THREE_LEVEL", + "geoname_id": 1807736, + "sub_districts": [] + }, + { + "code": "621024", + "name": "合水", + "level": "THREE_LEVEL", + "geoname_id": 1808278, + "sub_districts": [] + }, + { + "code": "621022", + "name": "环县", + "level": "THREE_LEVEL", + "geoname_id": 1807080, + "sub_districts": [] + }, + { + "code": "621026", + "name": "宁县", + "level": "THREE_LEVEL", + "geoname_id": 1799353, + "sub_districts": [] + }, + { + "code": "621021", + "name": "庆城", + "level": "THREE_LEVEL", + "geoname_id": 1797647, + "sub_districts": [] + }, + { + "code": "621002", + "name": "西峰", + "level": "THREE_LEVEL", + "geoname_id": 1789507, + "sub_districts": [] + }, + { + "code": "621025", + "name": "正宁", + "level": "THREE_LEVEL", + "geoname_id": 1784679, + "sub_districts": [] + }, + { + "code": "621027", + "name": "镇原", + "level": "THREE_LEVEL", + "geoname_id": 1784582, + "sub_districts": [] + } + ] + }, + { + "code": "620500", + "name": "天水", + "level": "TWO_LEVEL", + "geoname_id": 1792891, + "sub_districts": [ + { + "code": "620523", + "name": "甘谷", + "level": "THREE_LEVEL", + "geoname_id": 1810722, + "sub_districts": [] + }, + { + "code": "620503", + "name": "麦积", + "level": "THREE_LEVEL", + "geoname_id": 6642865, + "sub_districts": [] + }, + { + "code": "620522", + "name": "秦安", + "level": "THREE_LEVEL", + "geoname_id": 1797961, + "sub_districts": [] + }, + { + "code": "620521", + "name": "清水", + "level": "THREE_LEVEL", + "geoname_id": 1797717, + "sub_districts": [] + }, + { + "code": "620502", + "name": "秦州", + "level": "THREE_LEVEL", + "geoname_id": 6642864, + "sub_districts": [] + }, + { + "code": "620524", + "name": "武山", + "level": "THREE_LEVEL", + "geoname_id": 1791003, + "sub_districts": [] + }, + { + "code": "620525", + "name": "张家川", + "level": "THREE_LEVEL", + "geoname_id": 1785210, + "sub_districts": [] + } + ] + }, + { + "code": "620600", + "name": "武威", + "level": "TWO_LEVEL", + "geoname_id": 1803936, + "sub_districts": [ + { + "code": "620622", + "name": "古浪", + "level": "THREE_LEVEL", + "geoname_id": 1809421, + "sub_districts": [] + }, + { + "code": "620602", + "name": "凉州", + "level": "THREE_LEVEL", + "geoname_id": 1790928, + "sub_districts": [] + }, + { + "code": "620621", + "name": "民勤", + "level": "THREE_LEVEL", + "geoname_id": 1800460, + "sub_districts": [] + }, + { + "code": "620623", + "name": "天祝", + "level": "THREE_LEVEL", + "geoname_id": 1792825, + "sub_districts": [] + } + ] + }, + { + "code": "620700", + "name": "张掖", + "level": "TWO_LEVEL", + "geoname_id": 1785036, + "sub_districts": [ + { + "code": "620724", + "name": "高台", + "level": "THREE_LEVEL", + "geoname_id": 1281236, + "sub_districts": [] + }, + { + "code": "620702", + "name": "甘州", + "level": "THREE_LEVEL", + "geoname_id": 1785034, + "sub_districts": [] + }, + { + "code": "620723", + "name": "临泽", + "level": "THREE_LEVEL", + "geoname_id": 1803308, + "sub_districts": [] + }, + { + "code": "620722", + "name": "民乐", + "level": "THREE_LEVEL", + "geoname_id": 1800464, + "sub_districts": [] + }, + { + "code": "620725", + "name": "山丹", + "level": "THREE_LEVEL", + "geoname_id": 1796335, + "sub_districts": [] + }, + { + "code": "620721", + "name": "肃南", + "level": "THREE_LEVEL", + "geoname_id": 1279950, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "45", + "name": "广西", + "level": "ONE_LEVEL", + "geoname_id": 1809867, + "sub_districts": [ + { + "code": "450500", + "name": "北海", + "level": "TWO_LEVEL", + "geoname_id": 1816705, + "sub_districts": [ + { + "code": "450502", + "name": "海城", + "level": "THREE_LEVEL", + "geoname_id": 8021155, + "sub_districts": [] + }, + { + "code": "450521", + "name": "合浦", + "level": "THREE_LEVEL", + "geoname_id": 1808332, + "sub_districts": [] + }, + { + "code": "450512", + "name": "铁山港", + "level": "THREE_LEVEL", + "geoname_id": 8021157, + "sub_districts": [] + }, + { + "code": "450503", + "name": "银海", + "level": "THREE_LEVEL", + "geoname_id": 8021156, + "sub_districts": [] + } + ] + }, + { + "code": "451000", + "name": "百色", + "level": "TWO_LEVEL", + "geoname_id": 1816268, + "sub_districts": [ + { + "code": "451024", + "name": "德保", + "level": "THREE_LEVEL", + "geoname_id": 1813038, + "sub_districts": [] + }, + { + "code": "451081", + "name": "靖西", + "level": "THREE_LEVEL", + "geoname_id": 1805561, + "sub_districts": [] + }, + { + "code": "451031", + "name": "隆林", + "level": "THREE_LEVEL", + "geoname_id": 1802539, + "sub_districts": [] + }, + { + "code": "451027", + "name": "凌云", + "level": "THREE_LEVEL", + "geoname_id": 1803426, + "sub_districts": [] + }, + { + "code": "451028", + "name": "乐业", + "level": "THREE_LEVEL", + "geoname_id": 1804135, + "sub_districts": [] + }, + { + "code": "451026", + "name": "那坡", + "level": "THREE_LEVEL", + "geoname_id": 1799527, + "sub_districts": [] + }, + { + "code": "4510820000001", + "name": "平果", + "level": "THREE_LEVEL", + "geoname_id": 1798801, + "sub_districts": [] + }, + { + "code": "451022", + "name": "田东", + "level": "THREE_LEVEL", + "geoname_id": 1792996, + "sub_districts": [] + }, + { + "code": "451029", + "name": "田林", + "level": "THREE_LEVEL", + "geoname_id": 1792938, + "sub_districts": [] + }, + { + "code": "4510030000001", + "name": "田阳", + "level": "THREE_LEVEL", + "geoname_id": 1792846, + "sub_districts": [] + }, + { + "code": "451030", + "name": "西林", + "level": "THREE_LEVEL", + "geoname_id": 1789321, + "sub_districts": [] + }, + { + "code": "451002", + "name": "右江", + "level": "THREE_LEVEL", + "geoname_id": 1816267, + "sub_districts": [] + } + ] + }, + { + "code": "451400", + "name": "崇左", + "level": "TWO_LEVEL", + "geoname_id": 7909220, + "sub_districts": [ + { + "code": "451424", + "name": "大新", + "level": "THREE_LEVEL", + "geoname_id": 1813276, + "sub_districts": [] + }, + { + "code": "451421", + "name": "扶绥", + "level": "THREE_LEVEL", + "geoname_id": 1810900, + "sub_districts": [] + }, + { + "code": "451402", + "name": "江州", + "level": "THREE_LEVEL", + "geoname_id": 1814871, + "sub_districts": [] + }, + { + "code": "451423", + "name": "龙州", + "level": "THREE_LEVEL", + "geoname_id": 1802246, + "sub_districts": [] + }, + { + "code": "451422", + "name": "宁明", + "level": "THREE_LEVEL", + "geoname_id": 1799364, + "sub_districts": [] + }, + { + "code": "451481", + "name": "凭祥", + "level": "THREE_LEVEL", + "geoname_id": 1798651, + "sub_districts": [] + }, + { + "code": "451425", + "name": "天等", + "level": "THREE_LEVEL", + "geoname_id": 1792998, + "sub_districts": [] + } + ] + }, + { + "code": "450600", + "name": "防城港", + "level": "TWO_LEVEL", + "geoname_id": 7909223, + "sub_districts": [ + { + "code": "450681", + "name": "东兴", + "level": "THREE_LEVEL", + "geoname_id": 8021215, + "sub_districts": [] + }, + { + "code": "450603", + "name": "防城", + "level": "THREE_LEVEL", + "geoname_id": 1811591, + "sub_districts": [] + }, + { + "code": "450602", + "name": "港口", + "level": "THREE_LEVEL", + "geoname_id": 8021158, + "sub_districts": [] + }, + { + "code": "450621", + "name": "上思", + "level": "THREE_LEVEL", + "geoname_id": 1796103, + "sub_districts": [] + } + ] + }, + { + "code": "450800", + "name": "贵港", + "level": "TWO_LEVEL", + "geoname_id": 1809532, + "sub_districts": [ + { + "code": "450802", + "name": "港北", + "level": "THREE_LEVEL", + "geoname_id": 1809466, + "sub_districts": [] + }, + { + "code": "450803", + "name": "港南", + "level": "THREE_LEVEL", + "geoname_id": 8021160, + "sub_districts": [] + }, + { + "code": "450881", + "name": "桂平", + "level": "THREE_LEVEL", + "geoname_id": 1809485, + "sub_districts": [] + }, + { + "code": "450821", + "name": "平南", + "level": "THREE_LEVEL", + "geoname_id": 1798730, + "sub_districts": [] + }, + { + "code": "450804", + "name": "覃塘", + "level": "THREE_LEVEL", + "geoname_id": 8021161, + "sub_districts": [] + } + ] + }, + { + "code": "450300", + "name": "桂林", + "level": "TWO_LEVEL", + "geoname_id": 1809498, + "sub_districts": [ + { + "code": "450303", + "name": "叠彩", + "level": "THREE_LEVEL", + "geoname_id": 8021149, + "sub_districts": [] + }, + { + "code": "450332", + "name": "恭城", + "level": "THREE_LEVEL", + "geoname_id": 1810150, + "sub_districts": [] + }, + { + "code": "450327", + "name": "灌阳", + "level": "THREE_LEVEL", + "geoname_id": 1809718, + "sub_districts": [] + }, + { + "code": "450323", + "name": "灵川", + "level": "THREE_LEVEL", + "geoname_id": 1803545, + "sub_districts": [] + }, + { + "code": "450312", + "name": "临桂", + "level": "THREE_LEVEL", + "geoname_id": 1803450, + "sub_districts": [] + }, + { + "code": "4503810000001", + "name": "荔浦", + "level": "THREE_LEVEL", + "geoname_id": 1803289, + "sub_districts": [] + }, + { + "code": "450328", + "name": "龙胜", + "level": "THREE_LEVEL", + "geoname_id": 1802429, + "sub_districts": [] + }, + { + "code": "450330", + "name": "平乐", + "level": "THREE_LEVEL", + "geoname_id": 1798765, + "sub_districts": [] + }, + { + "code": "450305", + "name": "七星", + "level": "THREE_LEVEL", + "geoname_id": 8021146, + "sub_districts": [] + }, + { + "code": "450324", + "name": "全州", + "level": "THREE_LEVEL", + "geoname_id": 1797349, + "sub_districts": [] + }, + { + "code": "450325", + "name": "兴安", + "level": "THREE_LEVEL", + "geoname_id": 1789055, + "sub_districts": [] + }, + { + "code": "450302", + "name": "秀峰", + "level": "THREE_LEVEL", + "geoname_id": 8021145, + "sub_districts": [] + }, + { + "code": "450304", + "name": "象山", + "level": "THREE_LEVEL", + "geoname_id": 8021150, + "sub_districts": [] + }, + { + "code": "450326", + "name": "永福", + "level": "THREE_LEVEL", + "geoname_id": 1786349, + "sub_districts": [] + }, + { + "code": "450311", + "name": "雁山", + "level": "THREE_LEVEL", + "geoname_id": 8021151, + "sub_districts": [] + }, + { + "code": "450321", + "name": "阳朔", + "level": "THREE_LEVEL", + "geoname_id": 1787322, + "sub_districts": [] + }, + { + "code": "450329", + "name": "资源", + "level": "THREE_LEVEL", + "geoname_id": 1783675, + "sub_districts": [] + } + ] + }, + { + "code": "451200", + "name": "河池", + "level": "TWO_LEVEL", + "geoname_id": 1808757, + "sub_districts": [ + { + "code": "451227", + "name": "巴马", + "level": "THREE_LEVEL", + "geoname_id": 1817130, + "sub_districts": [] + }, + { + "code": "451228", + "name": "都安", + "level": "THREE_LEVEL", + "geoname_id": 1811937, + "sub_districts": [] + }, + { + "code": "451229", + "name": "大化", + "level": "THREE_LEVEL", + "geoname_id": 8537721, + "sub_districts": [] + }, + { + "code": "451224", + "name": "东兰", + "level": "THREE_LEVEL", + "geoname_id": 1812411, + "sub_districts": [] + }, + { + "code": "451223", + "name": "凤山", + "level": "THREE_LEVEL", + "geoname_id": 1811240, + "sub_districts": [] + }, + { + "code": "451226", + "name": "环江", + "level": "THREE_LEVEL", + "geoname_id": 1807091, + "sub_districts": [] + }, + { + "code": "451202", + "name": "金城江", + "level": "THREE_LEVEL", + "geoname_id": 1808756, + "sub_districts": [] + }, + { + "code": "451225", + "name": "罗城", + "level": "THREE_LEVEL", + "geoname_id": 1801981, + "sub_districts": [] + }, + { + "code": "451221", + "name": "南丹", + "level": "THREE_LEVEL", + "geoname_id": 1800118, + "sub_districts": [] + }, + { + "code": "451222", + "name": "天峨", + "level": "THREE_LEVEL", + "geoname_id": 1792990, + "sub_districts": [] + }, + { + "code": "4512030000001", + "name": "宜州", + "level": "THREE_LEVEL", + "geoname_id": 1786461, + "sub_districts": [] + } + ] + }, + { + "code": "451100", + "name": "贺州", + "level": "TWO_LEVEL", + "geoname_id": 7909224, + "sub_districts": [ + { + "code": "451102", + "name": "八步", + "level": "THREE_LEVEL", + "geoname_id": 1808230, + "sub_districts": [] + }, + { + "code": "451123", + "name": "富川", + "level": "THREE_LEVEL", + "geoname_id": 1811064, + "sub_districts": [] + }, + { + "code": "451103", + "name": "平桂", + "level": "THREE_LEVEL", + "geoname_id": 9912459, + "sub_districts": [] + }, + { + "code": "451121", + "name": "昭平", + "level": "THREE_LEVEL", + "geoname_id": 1784857, + "sub_districts": [] + }, + { + "code": "451122", + "name": "钟山", + "level": "THREE_LEVEL", + "geoname_id": 1784312, + "sub_districts": [] + } + ] + }, + { + "code": "451300", + "name": "来宾", + "level": "TWO_LEVEL", + "geoname_id": 1804609, + "sub_districts": [ + { + "code": "451381", + "name": "合山", + "level": "THREE_LEVEL", + "geoname_id": 1808307, + "sub_districts": [] + }, + { + "code": "451324", + "name": "金秀", + "level": "THREE_LEVEL", + "geoname_id": 1805322, + "sub_districts": [] + }, + { + "code": "451323", + "name": "武宣", + "level": "THREE_LEVEL", + "geoname_id": 1790895, + "sub_districts": [] + }, + { + "code": "451302", + "name": "兴宾", + "level": "THREE_LEVEL", + "geoname_id": 1804607, + "sub_districts": [] + }, + { + "code": "451321", + "name": "忻城", + "level": "THREE_LEVEL", + "geoname_id": 1789165, + "sub_districts": [] + }, + { + "code": "451322", + "name": "象州", + "level": "THREE_LEVEL", + "geoname_id": 1790432, + "sub_districts": [] + } + ] + }, + { + "code": "450200", + "name": "柳州", + "level": "TWO_LEVEL", + "geoname_id": 1802851, + "sub_districts": [ + { + "code": "450202", + "name": "城中", + "level": "THREE_LEVEL", + "geoname_id": 8021143, + "sub_districts": [] + }, + { + "code": "450205", + "name": "柳北", + "level": "THREE_LEVEL", + "geoname_id": 8021144, + "sub_districts": [] + }, + { + "code": "450222", + "name": "柳城", + "level": "THREE_LEVEL", + "geoname_id": 1803192, + "sub_districts": [] + }, + { + "code": "4502060000001", + "name": "柳江", + "level": "THREE_LEVEL", + "geoname_id": 1803053, + "sub_districts": [] + }, + { + "code": "450204", + "name": "柳南", + "level": "THREE_LEVEL", + "geoname_id": 450204, + "sub_districts": [] + }, + { + "code": "450223", + "name": "鹿寨", + "level": "THREE_LEVEL", + "geoname_id": 1801648, + "sub_districts": [] + }, + { + "code": "450224", + "name": "融安", + "level": "THREE_LEVEL", + "geoname_id": 1797124, + "sub_districts": [] + }, + { + "code": "450225", + "name": "融水", + "level": "THREE_LEVEL", + "geoname_id": 1797093, + "sub_districts": [] + }, + { + "code": "450226", + "name": "三江", + "level": "THREE_LEVEL", + "geoname_id": 1796767, + "sub_districts": [] + }, + { + "code": "450203", + "name": "鱼峰", + "level": "THREE_LEVEL", + "geoname_id": 8021142, + "sub_districts": [] + } + ] + }, + { + "code": "450100", + "name": "南宁", + "level": "TWO_LEVEL", + "geoname_id": 1799869, + "sub_districts": [ + { + "code": "450126", + "name": "宾阳", + "level": "THREE_LEVEL", + "geoname_id": 1816339, + "sub_districts": [] + }, + { + "code": "4501810000001", + "name": "横县", + "level": "THREE_LEVEL", + "geoname_id": 1808376, + "sub_districts": [] + }, + { + "code": "450105", + "name": "江南", + "level": "THREE_LEVEL", + "geoname_id": 8021139, + "sub_districts": [] + }, + { + "code": "450123", + "name": "隆安", + "level": "THREE_LEVEL", + "geoname_id": 1802705, + "sub_districts": [] + }, + { + "code": "450108", + "name": "良庆", + "level": "THREE_LEVEL", + "geoname_id": 8624078, + "sub_districts": [] + }, + { + "code": "450124", + "name": "马山", + "level": "THREE_LEVEL", + "geoname_id": 1801059, + "sub_districts": [] + }, + { + "code": "450103", + "name": "青秀", + "level": "THREE_LEVEL", + "geoname_id": 8021141, + "sub_districts": [] + }, + { + "code": "450125", + "name": "上林", + "level": "THREE_LEVEL", + "geoname_id": 1796171, + "sub_districts": [] + }, + { + "code": "450110", + "name": "武鸣", + "level": "THREE_LEVEL", + "geoname_id": 1791061, + "sub_districts": [] + }, + { + "code": "450102", + "name": "兴宁", + "level": "THREE_LEVEL", + "geoname_id": 8021140, + "sub_districts": [] + }, + { + "code": "450107", + "name": "西乡塘", + "level": "THREE_LEVEL", + "geoname_id": 1788204, + "sub_districts": [] + }, + { + "code": "450109", + "name": "邕宁", + "level": "THREE_LEVEL", + "geoname_id": 1786281, + "sub_districts": [] + } + ] + }, + { + "code": "450700", + "name": "钦州", + "level": "TWO_LEVEL", + "geoname_id": 1797551, + "sub_districts": [ + { + "code": "450721", + "name": "灵山", + "level": "THREE_LEVEL", + "geoname_id": 1803469, + "sub_districts": [] + }, + { + "code": "450722", + "name": "浦北", + "level": "THREE_LEVEL", + "geoname_id": 1798535, + "sub_districts": [] + }, + { + "code": "450703", + "name": "钦北", + "level": "THREE_LEVEL", + "geoname_id": 8021159, + "sub_districts": [] + }, + { + "code": "450702", + "name": "钦南", + "level": "THREE_LEVEL", + "geoname_id": 1797549, + "sub_districts": [] + } + ] + }, + { + "code": "450400", + "name": "梧州", + "level": "TWO_LEVEL", + "geoname_id": 1790840, + "sub_districts": [ + { + "code": "450421", + "name": "苍梧", + "level": "THREE_LEVEL", + "geoname_id": 1816085, + "sub_districts": [] + }, + { + "code": "450481", + "name": "岑溪", + "level": "THREE_LEVEL", + "geoname_id": 1815906, + "sub_districts": [] + }, + { + "code": "450405", + "name": "长洲", + "level": "THREE_LEVEL", + "geoname_id": 8021154, + "sub_districts": [] + }, + { + "code": "450406", + "name": "龙圩", + "level": "THREE_LEVEL", + "geoname_id": 1802287, + "sub_districts": [] + }, + { + "code": "450423", + "name": "蒙山", + "level": "THREE_LEVEL", + "geoname_id": 1800697, + "sub_districts": [] + }, + { + "code": "450422", + "name": "藤县", + "level": "THREE_LEVEL", + "geoname_id": 1793038, + "sub_districts": [] + }, + { + "code": "450403", + "name": "万秀", + "level": "THREE_LEVEL", + "geoname_id": 8021152, + "sub_districts": [] + } + ] + }, + { + "code": "450900", + "name": "玉林", + "level": "TWO_LEVEL", + "geoname_id": 1785781, + "sub_districts": [ + { + "code": "450923", + "name": "博白", + "level": "THREE_LEVEL", + "geoname_id": 1816302, + "sub_districts": [] + }, + { + "code": "450981", + "name": "北流", + "level": "THREE_LEVEL", + "geoname_id": 1816639, + "sub_districts": [] + }, + { + "code": "450903", + "name": "福绵", + "level": "THREE_LEVEL", + "geoname_id": 450903, + "sub_districts": [] + }, + { + "code": "450922", + "name": "陆川", + "level": "THREE_LEVEL", + "geoname_id": 1802163, + "sub_districts": [] + }, + { + "code": "450921", + "name": "容县", + "level": "THREE_LEVEL", + "geoname_id": 1797088, + "sub_districts": [] + }, + { + "code": "450924", + "name": "兴业", + "level": "THREE_LEVEL", + "geoname_id": 8021162, + "sub_districts": [] + }, + { + "code": "450902", + "name": "玉州", + "level": "THREE_LEVEL", + "geoname_id": 1785760, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "52", + "name": "贵州", + "level": "ONE_LEVEL", + "geoname_id": 1809445, + "sub_districts": [ + { + "code": "520400", + "name": "安顺", + "level": "TWO_LEVEL", + "geoname_id": 1817968, + "sub_districts": [ + { + "code": "520424", + "name": "关岭", + "level": "THREE_LEVEL", + "geoname_id": 1809822, + "sub_districts": [] + }, + { + "code": "520403", + "name": "平坝", + "level": "THREE_LEVEL", + "geoname_id": 1798857, + "sub_districts": [] + }, + { + "code": "520422", + "name": "普定", + "level": "THREE_LEVEL", + "geoname_id": 1798525, + "sub_districts": [] + }, + { + "code": "520402", + "name": "西秀", + "level": "THREE_LEVEL", + "geoname_id": 6642194, + "sub_districts": [] + }, + { + "code": "520423", + "name": "镇宁", + "level": "THREE_LEVEL", + "geoname_id": 1784619, + "sub_districts": [] + }, + { + "code": "520425", + "name": "紫云", + "level": "THREE_LEVEL", + "geoname_id": 1783673, + "sub_districts": [] + } + ] + }, + { + "code": "520500", + "name": "毕节", + "level": "TWO_LEVEL", + "geoname_id": 1816373, + "sub_districts": [ + { + "code": "520521", + "name": "大方", + "level": "THREE_LEVEL", + "geoname_id": 1814441, + "sub_districts": [] + }, + { + "code": "520527", + "name": "赫章", + "level": "THREE_LEVEL", + "geoname_id": 1808193, + "sub_districts": [] + }, + { + "code": "520523", + "name": "金沙", + "level": "THREE_LEVEL", + "geoname_id": 1805383, + "sub_districts": [] + }, + { + "code": "520525", + "name": "纳雍", + "level": "THREE_LEVEL", + "geoname_id": 1799500, + "sub_districts": [] + }, + { + "code": "520502", + "name": "七星关", + "level": "THREE_LEVEL", + "geoname_id": 10031873, + "sub_districts": [] + }, + { + "code": "5205810000001", + "name": "黔西", + "level": "THREE_LEVEL", + "geoname_id": 1798223, + "sub_districts": [] + }, + { + "code": "520526", + "name": "威宁", + "level": "THREE_LEVEL", + "geoname_id": 1791633, + "sub_districts": [] + }, + { + "code": "520524", + "name": "织金", + "level": "THREE_LEVEL", + "geoname_id": 1784519, + "sub_districts": [] + } + ] + }, + { + "code": "520100", + "name": "贵阳", + "level": "TWO_LEVEL", + "geoname_id": 1809461, + "sub_districts": [ + { + "code": "520113", + "name": "白云", + "level": "THREE_LEVEL", + "geoname_id": 6642049, + "sub_districts": [] + }, + { + "code": "520115", + "name": "观山湖", + "level": "THREE_LEVEL", + "geoname_id": 520115, + "sub_districts": [] + }, + { + "code": "520111", + "name": "花溪", + "level": "THREE_LEVEL", + "geoname_id": 6642048, + "sub_districts": [] + }, + { + "code": "520121", + "name": "开阳", + "level": "THREE_LEVEL", + "geoname_id": 1804851, + "sub_districts": [] + }, + { + "code": "520102", + "name": "南明", + "level": "THREE_LEVEL", + "geoname_id": 6642051, + "sub_districts": [] + }, + { + "code": "520181", + "name": "清镇", + "level": "THREE_LEVEL", + "geoname_id": 1797609, + "sub_districts": [] + }, + { + "code": "520112", + "name": "乌当", + "level": "THREE_LEVEL", + "geoname_id": 6642050, + "sub_districts": [] + }, + { + "code": "520122", + "name": "息烽", + "level": "THREE_LEVEL", + "geoname_id": 1789505, + "sub_districts": [] + }, + { + "code": "520123", + "name": "修文", + "level": "THREE_LEVEL", + "geoname_id": 1788250, + "sub_districts": [] + }, + { + "code": "520103", + "name": "云岩", + "level": "THREE_LEVEL", + "geoname_id": 6642052, + "sub_districts": [] + } + ] + }, + { + "code": "520200", + "name": "六盘水", + "level": "TWO_LEVEL", + "geoname_id": 8533133, + "sub_districts": [ + { + "code": "520203", + "name": "六枝", + "level": "THREE_LEVEL", + "geoname_id": 1801643, + "sub_districts": [] + }, + { + "code": "5202810000001", + "name": "盘州", + "level": "THREE_LEVEL", + "geoname_id": 520222, + "sub_districts": [] + }, + { + "code": "5202040000001", + "name": "水城", + "level": "THREE_LEVEL", + "geoname_id": 1794509, + "sub_districts": [] + }, + { + "code": "520201", + "name": "钟山", + "level": "THREE_LEVEL", + "geoname_id": 6642193, + "sub_districts": [] + } + ] + }, + { + "code": "522600", + "name": "黔东南", + "level": "TWO_LEVEL", + "geoname_id": 1798360, + "sub_districts": [ + { + "code": "522626", + "name": "岑巩", + "level": "THREE_LEVEL", + "geoname_id": 1815915, + "sub_districts": [] + }, + { + "code": "522633", + "name": "从江", + "level": "THREE_LEVEL", + "geoname_id": 1814708, + "sub_districts": [] + }, + { + "code": "522636", + "name": "丹寨", + "level": "THREE_LEVEL", + "geoname_id": 1813798, + "sub_districts": [] + }, + { + "code": "522622", + "name": "黄平", + "level": "THREE_LEVEL", + "geoname_id": 1807306, + "sub_districts": [] + }, + { + "code": "522629", + "name": "剑河", + "level": "THREE_LEVEL", + "geoname_id": 1806183, + "sub_districts": [] + }, + { + "code": "522628", + "name": "锦屏", + "level": "THREE_LEVEL", + "geoname_id": 1805426, + "sub_districts": [] + }, + { + "code": "522601", + "name": "凯里", + "level": "THREE_LEVEL", + "geoname_id": 1804865, + "sub_districts": [] + }, + { + "code": "522631", + "name": "黎平", + "level": "THREE_LEVEL", + "geoname_id": 1803292, + "sub_districts": [] + }, + { + "code": "522634", + "name": "雷山", + "level": "THREE_LEVEL", + "geoname_id": 1804215, + "sub_districts": [] + }, + { + "code": "522635", + "name": "麻江", + "level": "THREE_LEVEL", + "geoname_id": 1801433, + "sub_districts": [] + }, + { + "code": "522632", + "name": "榕江", + "level": "THREE_LEVEL", + "geoname_id": 1797103, + "sub_districts": [] + }, + { + "code": "522623", + "name": "施秉", + "level": "THREE_LEVEL", + "geoname_id": 1795478, + "sub_districts": [] + }, + { + "code": "522624", + "name": "三穗", + "level": "THREE_LEVEL", + "geoname_id": 1796605, + "sub_districts": [] + }, + { + "code": "522630", + "name": "台江", + "level": "THREE_LEVEL", + "geoname_id": 1793658, + "sub_districts": [] + }, + { + "code": "522627", + "name": "天柱", + "level": "THREE_LEVEL", + "geoname_id": 1792826, + "sub_districts": [] + }, + { + "code": "522625", + "name": "镇远", + "level": "THREE_LEVEL", + "geoname_id": 1784583, + "sub_districts": [] + } + ] + }, + { + "code": "522700", + "name": "黔南", + "level": "TWO_LEVEL", + "geoname_id": 1798280, + "sub_districts": [ + { + "code": "522729", + "name": "长顺", + "level": "THREE_LEVEL", + "geoname_id": 1815535, + "sub_districts": [] + }, + { + "code": "522726", + "name": "独山", + "level": "THREE_LEVEL", + "geoname_id": 1811789, + "sub_districts": [] + }, + { + "code": "522701", + "name": "都匀", + "level": "THREE_LEVEL", + "geoname_id": 1811763, + "sub_districts": [] + }, + { + "code": "522702", + "name": "福泉", + "level": "THREE_LEVEL", + "geoname_id": 1810938, + "sub_districts": [] + }, + { + "code": "522723", + "name": "贵定", + "level": "THREE_LEVEL", + "geoname_id": 1809523, + "sub_districts": [] + }, + { + "code": "522731", + "name": "惠水", + "level": "THREE_LEVEL", + "geoname_id": 1806803, + "sub_districts": [] + }, + { + "code": "522722", + "name": "荔波", + "level": "THREE_LEVEL", + "geoname_id": 1803801, + "sub_districts": [] + }, + { + "code": "522728", + "name": "罗甸", + "level": "THREE_LEVEL", + "geoname_id": 1801968, + "sub_districts": [] + }, + { + "code": "522730", + "name": "龙里", + "level": "THREE_LEVEL", + "geoname_id": 1802538, + "sub_districts": [] + }, + { + "code": "522727", + "name": "平塘", + "level": "THREE_LEVEL", + "geoname_id": 1798677, + "sub_districts": [] + }, + { + "code": "522732", + "name": "三都", + "level": "THREE_LEVEL", + "geoname_id": 1796904, + "sub_districts": [] + }, + { + "code": "522725", + "name": "瓮安", + "level": "THREE_LEVEL", + "geoname_id": 1791513, + "sub_districts": [] + } + ] + }, + { + "code": "522300", + "name": "黔西南", + "level": "TWO_LEVEL", + "geoname_id": 1798226, + "sub_districts": [ + { + "code": "522328", + "name": "安龙", + "level": "THREE_LEVEL", + "geoname_id": 1818017, + "sub_districts": [] + }, + { + "code": "522327", + "name": "册亨", + "level": "THREE_LEVEL", + "geoname_id": 1815920, + "sub_districts": [] + }, + { + "code": "522323", + "name": "普安", + "level": "THREE_LEVEL", + "geoname_id": 1798536, + "sub_districts": [] + }, + { + "code": "522324", + "name": "晴隆", + "level": "THREE_LEVEL", + "geoname_id": 1797818, + "sub_districts": [] + }, + { + "code": "522326", + "name": "望谟", + "level": "THREE_LEVEL", + "geoname_id": 1791936, + "sub_districts": [] + }, + { + "code": "5223020000001", + "name": "兴仁", + "level": "THREE_LEVEL", + "geoname_id": 1788939, + "sub_districts": [] + }, + { + "code": "522301", + "name": "兴义", + "level": "THREE_LEVEL", + "geoname_id": 1788906, + "sub_districts": [] + }, + { + "code": "522325", + "name": "贞丰", + "level": "THREE_LEVEL", + "geoname_id": 1784732, + "sub_districts": [] + } + ] + }, + { + "code": "520600", + "name": "铜仁", + "level": "TWO_LEVEL", + "geoname_id": 1792590, + "sub_districts": [ + { + "code": "520602", + "name": "碧江", + "level": "THREE_LEVEL", + "geoname_id": 520602, + "sub_districts": [] + }, + { + "code": "520626", + "name": "德江", + "level": "THREE_LEVEL", + "geoname_id": 1550506, + "sub_districts": [] + }, + { + "code": "520621", + "name": "江口", + "level": "THREE_LEVEL", + "geoname_id": 1806306, + "sub_districts": [] + }, + { + "code": "520624", + "name": "思南", + "level": "THREE_LEVEL", + "geoname_id": 1794188, + "sub_districts": [] + }, + { + "code": "520623", + "name": "石阡", + "level": "THREE_LEVEL", + "geoname_id": 1795056, + "sub_districts": [] + }, + { + "code": "520628", + "name": "松桃", + "level": "THREE_LEVEL", + "geoname_id": 1803829, + "sub_districts": [] + }, + { + "code": "520603", + "name": "万山", + "level": "THREE_LEVEL", + "geoname_id": 1791769, + "sub_districts": [] + }, + { + "code": "520627", + "name": "沿河", + "level": "THREE_LEVEL", + "geoname_id": 1808346, + "sub_districts": [] + }, + { + "code": "520625", + "name": "印江", + "level": "THREE_LEVEL", + "geoname_id": 1786526, + "sub_districts": [] + }, + { + "code": "520622", + "name": "玉屏", + "level": "THREE_LEVEL", + "geoname_id": 1785639, + "sub_districts": [] + } + ] + }, + { + "code": "520300", + "name": "遵义", + "level": "TWO_LEVEL", + "geoname_id": 1783621, + "sub_districts": [ + { + "code": "520304", + "name": "播州", + "level": "THREE_LEVEL", + "geoname_id": 520304, + "sub_districts": [] + }, + { + "code": "520381", + "name": "赤水", + "level": "THREE_LEVEL", + "geoname_id": 1814961, + "sub_districts": [] + }, + { + "code": "520325", + "name": "道真", + "level": "THREE_LEVEL", + "geoname_id": 1785578, + "sub_districts": [] + }, + { + "code": "520327", + "name": "凤冈", + "level": "THREE_LEVEL", + "geoname_id": 1811375, + "sub_districts": [] + }, + { + "code": "520303", + "name": "汇川", + "level": "THREE_LEVEL", + "geoname_id": 6642054, + "sub_districts": [] + }, + { + "code": "520302", + "name": "红花岗", + "level": "THREE_LEVEL", + "geoname_id": 6642055, + "sub_districts": [] + }, + { + "code": "520328", + "name": "湄潭", + "level": "THREE_LEVEL", + "geoname_id": 1800807, + "sub_districts": [] + }, + { + "code": "520382", + "name": "仁怀", + "level": "THREE_LEVEL", + "geoname_id": 1797194, + "sub_districts": [] + }, + { + "code": "520323", + "name": "绥阳", + "level": "THREE_LEVEL", + "geoname_id": 1793881, + "sub_districts": [] + }, + { + "code": "520322", + "name": "桐梓", + "level": "THREE_LEVEL", + "geoname_id": 1792510, + "sub_districts": [] + }, + { + "code": "520326", + "name": "务川", + "level": "THREE_LEVEL", + "geoname_id": 1791335, + "sub_districts": [] + }, + { + "code": "520330", + "name": "习水", + "level": "THREE_LEVEL", + "geoname_id": 1788315, + "sub_districts": [] + }, + { + "code": "520329", + "name": "余庆", + "level": "THREE_LEVEL", + "geoname_id": 1785635, + "sub_districts": [] + }, + { + "code": "520324", + "name": "正安", + "level": "THREE_LEVEL", + "geoname_id": 1784729, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "13", + "name": "河北", + "level": "ONE_LEVEL", + "geoname_id": 1808773, + "sub_districts": [ + { + "code": "130600", + "name": "保定", + "level": "TWO_LEVEL", + "geoname_id": 1816971, + "sub_districts": [ + { + "code": "130683", + "name": "安国", + "level": "THREE_LEVEL", + "geoname_id": 1818071, + "sub_districts": [] + }, + { + "code": "130632", + "name": "安新", + "level": "THREE_LEVEL", + "geoname_id": 1817949, + "sub_districts": [] + }, + { + "code": "130637", + "name": "博野", + "level": "THREE_LEVEL", + "geoname_id": 1816239, + "sub_districts": [] + }, + { + "code": "130626", + "name": "定兴", + "level": "THREE_LEVEL", + "geoname_id": 1812740, + "sub_districts": [] + }, + { + "code": "130682", + "name": "定州", + "level": "THREE_LEVEL", + "geoname_id": 1812727, + "sub_districts": [] + }, + { + "code": "130624", + "name": "阜平", + "level": "THREE_LEVEL", + "geoname_id": 1810944, + "sub_districts": [] + }, + { + "code": "130684", + "name": "高碑店", + "level": "THREE_LEVEL", + "geoname_id": 1789164, + "sub_districts": [] + }, + { + "code": "130628", + "name": "高阳", + "level": "THREE_LEVEL", + "geoname_id": 1810317, + "sub_districts": [] + }, + { + "code": "130602", + "name": "竞秀", + "level": "THREE_LEVEL", + "geoname_id": 130602, + "sub_districts": [] + }, + { + "code": "130606", + "name": "莲池", + "level": "THREE_LEVEL", + "geoname_id": 130606, + "sub_districts": [] + }, + { + "code": "130623", + "name": "涞水", + "level": "THREE_LEVEL", + "geoname_id": 1804594, + "sub_districts": [] + }, + { + "code": "130635", + "name": "蠡县", + "level": "THREE_LEVEL", + "geoname_id": 1802814, + "sub_districts": [] + }, + { + "code": "130630", + "name": "涞源", + "level": "THREE_LEVEL", + "geoname_id": 1804580, + "sub_districts": [] + }, + { + "code": "130607", + "name": "满城", + "level": "THREE_LEVEL", + "geoname_id": 1801311, + "sub_districts": [] + }, + { + "code": "130608", + "name": "清苑", + "level": "THREE_LEVEL", + "geoname_id": 1797624, + "sub_districts": [] + }, + { + "code": "130634", + "name": "曲阳", + "level": "THREE_LEVEL", + "geoname_id": 1797267, + "sub_districts": [] + }, + { + "code": "130629", + "name": "容城", + "level": "THREE_LEVEL", + "geoname_id": 1797112, + "sub_districts": [] + }, + { + "code": "130636", + "name": "顺平", + "level": "THREE_LEVEL", + "geoname_id": 1791749, + "sub_districts": [] + }, + { + "code": "130627", + "name": "唐县", + "level": "THREE_LEVEL", + "geoname_id": 1793307, + "sub_districts": [] + }, + { + "code": "130631", + "name": "望都", + "level": "THREE_LEVEL", + "geoname_id": 1792111, + "sub_districts": [] + }, + { + "code": "130609", + "name": "徐水", + "level": "THREE_LEVEL", + "geoname_id": 1787849, + "sub_districts": [] + }, + { + "code": "130638", + "name": "雄县", + "level": "THREE_LEVEL", + "geoname_id": 1788405, + "sub_districts": [] + }, + { + "code": "130633", + "name": "易县", + "level": "THREE_LEVEL", + "geoname_id": 1786428, + "sub_districts": [] + }, + { + "code": "130681", + "name": "涿州", + "level": "THREE_LEVEL", + "geoname_id": 1783850, + "sub_districts": [] + } + ] + }, + { + "code": "130800", + "name": "承德", + "level": "TWO_LEVEL", + "geoname_id": 2038085, + "sub_districts": [ + { + "code": "1308210000003", + "name": "承德", + "level": "THREE_LEVEL", + "geoname_id": 2038084, + "sub_districts": [] + }, + { + "code": "130826", + "name": "丰宁", + "level": "THREE_LEVEL", + "geoname_id": 2037400, + "sub_districts": [] + }, + { + "code": "130827", + "name": "宽城", + "level": "THREE_LEVEL", + "geoname_id": 2036284, + "sub_districts": [] + }, + { + "code": "130825", + "name": "隆化", + "level": "THREE_LEVEL", + "geoname_id": 2035971, + "sub_districts": [] + }, + { + "code": "130824", + "name": "滦平", + "level": "THREE_LEVEL", + "geoname_id": 2035935, + "sub_districts": [] + }, + { + "code": "1308810000001", + "name": "平泉", + "level": "THREE_LEVEL", + "geoname_id": 2035464, + "sub_districts": [] + }, + { + "code": "130803", + "name": "双滦", + "level": "THREE_LEVEL", + "geoname_id": 6586388, + "sub_districts": [] + }, + { + "code": "1308020000003", + "name": "双桥", + "level": "THREE_LEVEL", + "geoname_id": 6586389, + "sub_districts": [] + }, + { + "code": "130828", + "name": "围场", + "level": "THREE_LEVEL", + "geoname_id": 2034193, + "sub_districts": [] + }, + { + "code": "130822", + "name": "兴隆", + "level": "THREE_LEVEL", + "geoname_id": 2033736, + "sub_districts": [] + }, + { + "code": "130804", + "name": "鹰手营子", + "level": "THREE_LEVEL", + "geoname_id": 8029389, + "sub_districts": [] + } + ] + }, + { + "code": "130900", + "name": "沧州", + "level": "TWO_LEVEL", + "geoname_id": 1816080, + "sub_districts": [ + { + "code": "130981", + "name": "泊头", + "level": "THREE_LEVEL", + "geoname_id": 1816255, + "sub_districts": [] + }, + { + "code": "130921", + "name": "沧县", + "level": "THREE_LEVEL", + "geoname_id": 1816083, + "sub_districts": [] + }, + { + "code": "130923", + "name": "东光", + "level": "THREE_LEVEL", + "geoname_id": 1812535, + "sub_districts": [] + }, + { + "code": "130983", + "name": "黄骅", + "level": "THREE_LEVEL", + "geoname_id": 1807459, + "sub_districts": [] + }, + { + "code": "130984", + "name": "河间", + "level": "THREE_LEVEL", + "geoname_id": 1808608, + "sub_districts": [] + }, + { + "code": "130924", + "name": "海兴", + "level": "THREE_LEVEL", + "geoname_id": 1809027, + "sub_districts": [] + }, + { + "code": "130930", + "name": "孟村", + "level": "THREE_LEVEL", + "geoname_id": 1800757, + "sub_districts": [] + }, + { + "code": "130927", + "name": "南皮", + "level": "THREE_LEVEL", + "geoname_id": 1799835, + "sub_districts": [] + }, + { + "code": "130922", + "name": "青县", + "level": "THREE_LEVEL", + "geoname_id": 1797668, + "sub_districts": [] + }, + { + "code": "130982", + "name": "任丘", + "level": "THREE_LEVEL", + "geoname_id": 1797181, + "sub_districts": [] + }, + { + "code": "130926", + "name": "肃宁", + "level": "THREE_LEVEL", + "geoname_id": 1793839, + "sub_districts": [] + }, + { + "code": "130928", + "name": "吴桥", + "level": "THREE_LEVEL", + "geoname_id": 1791031, + "sub_districts": [] + }, + { + "code": "130902", + "name": "新华", + "level": "THREE_LEVEL", + "geoname_id": 130902, + "sub_districts": [] + }, + { + "code": "130929", + "name": "献县", + "level": "THREE_LEVEL", + "geoname_id": 1790360, + "sub_districts": [] + }, + { + "code": "130903", + "name": "运河", + "level": "THREE_LEVEL", + "geoname_id": 6586370, + "sub_districts": [] + }, + { + "code": "130925", + "name": "盐山", + "level": "THREE_LEVEL", + "geoname_id": 1787105, + "sub_districts": [] + } + ] + }, + { + "code": "130400", + "name": "邯郸", + "level": "TWO_LEVEL", + "geoname_id": 1808963, + "sub_districts": [ + { + "code": "130424", + "name": "成安", + "level": "THREE_LEVEL", + "geoname_id": 1815309, + "sub_districts": [] + }, + { + "code": "130403", + "name": "丛台", + "level": "THREE_LEVEL", + "geoname_id": 6586359, + "sub_districts": [] + }, + { + "code": "130427", + "name": "磁县", + "level": "THREE_LEVEL", + "geoname_id": 1814723, + "sub_districts": [] + }, + { + "code": "130425", + "name": "大名", + "level": "THREE_LEVEL", + "geoname_id": 1813911, + "sub_districts": [] + }, + { + "code": "130406", + "name": "峰峰矿区", + "level": "THREE_LEVEL", + "geoname_id": 6586357, + "sub_districts": [] + }, + { + "code": "130404", + "name": "复兴", + "level": "THREE_LEVEL", + "geoname_id": 6586360, + "sub_districts": [] + }, + { + "code": "1304070000001", + "name": "肥乡", + "level": "THREE_LEVEL", + "geoname_id": 1811438, + "sub_districts": [] + }, + { + "code": "130432", + "name": "广平", + "level": "THREE_LEVEL", + "geoname_id": 1809885, + "sub_districts": [] + }, + { + "code": "130433", + "name": "馆陶", + "level": "THREE_LEVEL", + "geoname_id": 1809760, + "sub_districts": [] + }, + { + "code": "130402", + "name": "邯山", + "level": "THREE_LEVEL", + "geoname_id": 6586358, + "sub_districts": [] + }, + { + "code": "130431", + "name": "鸡泽", + "level": "THREE_LEVEL", + "geoname_id": 1783575, + "sub_districts": [] + }, + { + "code": "130423", + "name": "临漳", + "level": "THREE_LEVEL", + "geoname_id": 1803305, + "sub_districts": [] + }, + { + "code": "130430", + "name": "邱县", + "level": "THREE_LEVEL", + "geoname_id": 1797450, + "sub_districts": [] + }, + { + "code": "130435", + "name": "曲周", + "level": "THREE_LEVEL", + "geoname_id": 1797261, + "sub_districts": [] + }, + { + "code": "130426", + "name": "涉县", + "level": "THREE_LEVEL", + "geoname_id": 1795533, + "sub_districts": [] + }, + { + "code": "130481", + "name": "武安", + "level": "THREE_LEVEL", + "geoname_id": 1791356, + "sub_districts": [] + }, + { + "code": "130434", + "name": "魏县", + "level": "THREE_LEVEL", + "geoname_id": 1791591, + "sub_districts": [] + }, + { + "code": "1304080000001", + "name": "永年", + "level": "THREE_LEVEL", + "geoname_id": 1786295, + "sub_districts": [] + } + ] + }, + { + "code": "131100", + "name": "衡水", + "level": "TWO_LEVEL", + "geoname_id": 1808392, + "sub_districts": [ + { + "code": "131125", + "name": "安平", + "level": "THREE_LEVEL", + "geoname_id": 1817996, + "sub_districts": [] + }, + { + "code": "131128", + "name": "阜城", + "level": "THREE_LEVEL", + "geoname_id": 1811070, + "sub_districts": [] + }, + { + "code": "131126", + "name": "故城", + "level": "THREE_LEVEL", + "geoname_id": 1809577, + "sub_districts": [] + }, + { + "code": "1311710000003", + "name": "河北衡水高新技术产业开发区", + "level": "THREE_LEVEL", + "geoname_id": 659010141, + "sub_districts": [] + }, + { + "code": "131127", + "name": "景县", + "level": "THREE_LEVEL", + "geoname_id": 1805569, + "sub_districts": [] + }, + { + "code": "131103", + "name": "冀州", + "level": "THREE_LEVEL", + "geoname_id": 1805033, + "sub_districts": [] + }, + { + "code": "131124", + "name": "饶阳", + "level": "THREE_LEVEL", + "geoname_id": 1797236, + "sub_districts": [] + }, + { + "code": "131182", + "name": "深州", + "level": "THREE_LEVEL", + "geoname_id": 1795580, + "sub_districts": [] + }, + { + "code": "1311020000003", + "name": "桃城", + "level": "THREE_LEVEL", + "geoname_id": 6586363, + "sub_districts": [] + }, + { + "code": "131123", + "name": "武强", + "level": "THREE_LEVEL", + "geoname_id": 1791039, + "sub_districts": [] + }, + { + "code": "1311220000003", + "name": "武邑", + "level": "THREE_LEVEL", + "geoname_id": 1790869, + "sub_districts": [] + }, + { + "code": "131121", + "name": "枣强", + "level": "THREE_LEVEL", + "geoname_id": 1785475, + "sub_districts": [] + } + ] + }, + { + "code": "131000", + "name": "廊坊", + "level": "TWO_LEVEL", + "geoname_id": 1804540, + "sub_districts": [ + { + "code": "131002", + "name": "安次", + "level": "THREE_LEVEL", + "geoname_id": 6586375, + "sub_districts": [] + }, + { + "code": "131081", + "name": "霸州", + "level": "THREE_LEVEL", + "geoname_id": 1816834, + "sub_districts": [] + }, + { + "code": "131028", + "name": "大厂", + "level": "THREE_LEVEL", + "geoname_id": 1814539, + "sub_districts": [] + }, + { + "code": "131025", + "name": "大城", + "level": "THREE_LEVEL", + "geoname_id": 1814254, + "sub_districts": [] + }, + { + "code": "131022", + "name": "固安", + "level": "THREE_LEVEL", + "geoname_id": 1809728, + "sub_districts": [] + }, + { + "code": "131003", + "name": "广阳", + "level": "THREE_LEVEL", + "geoname_id": 6586376, + "sub_districts": [] + }, + { + "code": "131082", + "name": "三河", + "level": "THREE_LEVEL", + "geoname_id": 1796810, + "sub_districts": [] + }, + { + "code": "131026", + "name": "文安", + "level": "THREE_LEVEL", + "geoname_id": 1791548, + "sub_districts": [] + }, + { + "code": "131024", + "name": "香河", + "level": "THREE_LEVEL", + "geoname_id": 1790572, + "sub_districts": [] + }, + { + "code": "131023", + "name": "永清", + "level": "THREE_LEVEL", + "geoname_id": 1786270, + "sub_districts": [] + } + ] + }, + { + "code": "130300", + "name": "秦皇岛", + "level": "TWO_LEVEL", + "geoname_id": 1797595, + "sub_districts": [ + { + "code": "130304", + "name": "北戴河区", + "level": "THREE_LEVEL", + "geoname_id": 6586383, + "sub_districts": [] + }, + { + "code": "1303720000003", + "name": "北戴河新区", + "level": "THREE_LEVEL", + "geoname_id": 659010032, + "sub_districts": [] + }, + { + "code": "1303220000003", + "name": "昌黎", + "level": "THREE_LEVEL", + "geoname_id": 1815634, + "sub_districts": [] + }, + { + "code": "1303060000003", + "name": "抚宁", + "level": "THREE_LEVEL", + "geoname_id": 1810948, + "sub_districts": [] + }, + { + "code": "130302", + "name": "海港", + "level": "THREE_LEVEL", + "geoname_id": 6586381, + "sub_districts": [] + }, + { + "code": "130324", + "name": "卢龙", + "level": "THREE_LEVEL", + "geoname_id": 1802021, + "sub_districts": [] + }, + { + "code": "130321", + "name": "青龙", + "level": "THREE_LEVEL", + "geoname_id": 2035303, + "sub_districts": [] + }, + { + "code": "130303", + "name": "山海关", + "level": "THREE_LEVEL", + "geoname_id": 6586382, + "sub_districts": [] + } + ] + }, + { + "code": "130100", + "name": "石家庄", + "level": "TWO_LEVEL", + "geoname_id": 1795266, + "sub_districts": [ + { + "code": "130102", + "name": "长安", + "level": "THREE_LEVEL", + "geoname_id": 6586367, + "sub_districts": [] + }, + { + "code": "130109", + "name": "藁城", + "level": "THREE_LEVEL", + "geoname_id": 1810596, + "sub_districts": [] + }, + { + "code": "130127", + "name": "高邑", + "level": "THREE_LEVEL", + "geoname_id": 1810311, + "sub_districts": [] + }, + { + "code": "130107", + "name": "井陉矿区", + "level": "THREE_LEVEL", + "geoname_id": 6586369, + "sub_districts": [] + }, + { + "code": "130121", + "name": "井陉县", + "level": "THREE_LEVEL", + "geoname_id": 1805562, + "sub_districts": [] + }, + { + "code": "130183", + "name": "晋州", + "level": "THREE_LEVEL", + "geoname_id": 1805338, + "sub_districts": [] + }, + { + "code": "130111", + "name": "栾城", + "level": "THREE_LEVEL", + "geoname_id": 1802203, + "sub_districts": [] + }, + { + "code": "130110", + "name": "鹿泉", + "level": "THREE_LEVEL", + "geoname_id": 1806654, + "sub_districts": [] + }, + { + "code": "130126", + "name": "灵寿", + "level": "THREE_LEVEL", + "geoname_id": 1803465, + "sub_districts": [] + }, + { + "code": "130131", + "name": "平山", + "level": "THREE_LEVEL", + "geoname_id": 1798698, + "sub_districts": [] + }, + { + "code": "130104", + "name": "桥西", + "level": "THREE_LEVEL", + "geoname_id": 130104, + "sub_districts": [] + }, + { + "code": "130128", + "name": "深泽", + "level": "THREE_LEVEL", + "geoname_id": 1795568, + "sub_districts": [] + }, + { + "code": "130130", + "name": "无极", + "level": "THREE_LEVEL", + "geoname_id": 1791157, + "sub_districts": [] + }, + { + "code": "130105", + "name": "新华", + "level": "THREE_LEVEL", + "geoname_id": 130105, + "sub_districts": [] + }, + { + "code": "130181", + "name": "辛集", + "level": "THREE_LEVEL", + "geoname_id": 1788766, + "sub_districts": [] + }, + { + "code": "130184", + "name": "新乐", + "level": "THREE_LEVEL", + "geoname_id": 1788751, + "sub_districts": [] + }, + { + "code": "130125", + "name": "行唐", + "level": "THREE_LEVEL", + "geoname_id": 1788920, + "sub_districts": [] + }, + { + "code": "130108", + "name": "裕华", + "level": "THREE_LEVEL", + "geoname_id": 6586364, + "sub_districts": [] + }, + { + "code": "130132", + "name": "元氏", + "level": "THREE_LEVEL", + "geoname_id": 1786041, + "sub_districts": [] + }, + { + "code": "130123", + "name": "正定", + "level": "THREE_LEVEL", + "geoname_id": 1784711, + "sub_districts": [] + }, + { + "code": "130129", + "name": "赞皇", + "level": "THREE_LEVEL", + "geoname_id": 1785499, + "sub_districts": [] + }, + { + "code": "130133", + "name": "赵县", + "level": "THREE_LEVEL", + "geoname_id": 1784829, + "sub_districts": [] + } + ] + }, + { + "code": "130200", + "name": "唐山", + "level": "TWO_LEVEL", + "geoname_id": 1793343, + "sub_districts": [ + { + "code": "130209", + "name": "曹妃甸", + "level": "THREE_LEVEL", + "geoname_id": 130209, + "sub_districts": [] + }, + { + "code": "130207", + "name": "丰南", + "level": "THREE_LEVEL", + "geoname_id": 1811270, + "sub_districts": [] + }, + { + "code": "1302080000003", + "name": "丰润", + "level": "THREE_LEVEL", + "geoname_id": 1811259, + "sub_districts": [] + }, + { + "code": "130204", + "name": "古冶", + "level": "THREE_LEVEL", + "geoname_id": 6586380, + "sub_districts": [] + }, + { + "code": "1302740000003", + "name": "河北唐山海港经济开发区", + "level": "THREE_LEVEL", + "geoname_id": 659010074, + "sub_districts": [] + }, + { + "code": "130205", + "name": "开平", + "level": "THREE_LEVEL", + "geoname_id": 6586379, + "sub_districts": [] + }, + { + "code": "1302030000003", + "name": "路北", + "level": "THREE_LEVEL", + "geoname_id": 6586378, + "sub_districts": [] + }, + { + "code": "130202", + "name": "路南", + "level": "THREE_LEVEL", + "geoname_id": 6586377, + "sub_districts": [] + }, + { + "code": "130224", + "name": "滦南", + "level": "THREE_LEVEL", + "geoname_id": 1802193, + "sub_districts": [] + }, + { + "code": "1302250000003", + "name": "乐亭", + "level": "THREE_LEVEL", + "geoname_id": 1804141, + "sub_districts": [] + }, + { + "code": "1302840000001", + "name": "滦州", + "level": "THREE_LEVEL", + "geoname_id": 1802187, + "sub_districts": [] + }, + { + "code": "130283", + "name": "迁安", + "level": "THREE_LEVEL", + "geoname_id": 2035409, + "sub_districts": [] + }, + { + "code": "130227", + "name": "迁西", + "level": "THREE_LEVEL", + "geoname_id": 2035377, + "sub_districts": [] + }, + { + "code": "130229", + "name": "玉田", + "level": "THREE_LEVEL", + "geoname_id": 1785594, + "sub_districts": [] + }, + { + "code": "130281", + "name": "遵化", + "level": "THREE_LEVEL", + "geoname_id": 2033057, + "sub_districts": [] + } + ] + }, + { + "code": "130500", + "name": "邢台", + "level": "TWO_LEVEL", + "geoname_id": 1788927, + "sub_districts": [ + { + "code": "130524", + "name": "柏乡", + "level": "THREE_LEVEL", + "geoname_id": 1817286, + "sub_districts": [] + }, + { + "code": "130531", + "name": "广宗", + "level": "THREE_LEVEL", + "geoname_id": 1783565, + "sub_districts": [] + }, + { + "code": "130529", + "name": "巨鹿", + "level": "THREE_LEVEL", + "geoname_id": 1804956, + "sub_districts": [] + }, + { + "code": "130522", + "name": "临城", + "level": "THREE_LEVEL", + "geoname_id": 1803580, + "sub_districts": [] + }, + { + "code": "130535", + "name": "临西", + "level": "THREE_LEVEL", + "geoname_id": 1803320, + "sub_districts": [] + }, + { + "code": "130525", + "name": "隆尧", + "level": "THREE_LEVEL", + "geoname_id": 1802265, + "sub_districts": [] + }, + { + "code": "130581", + "name": "南宫", + "level": "THREE_LEVEL", + "geoname_id": 1800063, + "sub_districts": [] + }, + { + "code": "1305060000001", + "name": "南和", + "level": "THREE_LEVEL", + "geoname_id": 1800015, + "sub_districts": [] + }, + { + "code": "130528", + "name": "宁晋", + "level": "THREE_LEVEL", + "geoname_id": 1799372, + "sub_districts": [] + }, + { + "code": "130523", + "name": "内丘", + "level": "THREE_LEVEL", + "geoname_id": 1799481, + "sub_districts": [] + }, + { + "code": "130532", + "name": "平乡", + "level": "THREE_LEVEL", + "geoname_id": 1798650, + "sub_districts": [] + }, + { + "code": "130534", + "name": "清河", + "level": "THREE_LEVEL", + "geoname_id": 1797892, + "sub_districts": [] + }, + { + "code": "1305050000001", + "name": "任泽", + "level": "THREE_LEVEL", + "geoname_id": 1797173, + "sub_districts": [] + }, + { + "code": "130582", + "name": "沙河", + "level": "THREE_LEVEL", + "geoname_id": 1796400, + "sub_districts": [] + }, + { + "code": "130533", + "name": "威县", + "level": "THREE_LEVEL", + "geoname_id": 1791590, + "sub_districts": [] + }, + { + "code": "130502", + "name": "襄都", + "level": "THREE_LEVEL", + "geoname_id": 130502, + "sub_districts": [] + }, + { + "code": "130503", + "name": "信都", + "level": "THREE_LEVEL", + "geoname_id": 130503, + "sub_districts": [] + }, + { + "code": "130530", + "name": "新河", + "level": "THREE_LEVEL", + "geoname_id": 1788881, + "sub_districts": [] + } + ] + }, + { + "code": "130700", + "name": "张家口", + "level": "TWO_LEVEL", + "geoname_id": 2033196, + "sub_districts": [ + { + "code": "130732", + "name": "赤城", + "level": "THREE_LEVEL", + "geoname_id": 2038068, + "sub_districts": [] + }, + { + "code": "130709", + "name": "崇礼", + "level": "THREE_LEVEL", + "geoname_id": 2038061, + "sub_districts": [] + }, + { + "code": "1307240000003", + "name": "沽源", + "level": "THREE_LEVEL", + "geoname_id": 2037105, + "sub_districts": [] + }, + { + "code": "130728", + "name": "怀安", + "level": "THREE_LEVEL", + "geoname_id": 2036770, + "sub_districts": [] + }, + { + "code": "130730", + "name": "怀来", + "level": "THREE_LEVEL", + "geoname_id": 2036767, + "sub_districts": [] + }, + { + "code": "130723", + "name": "康保", + "level": "THREE_LEVEL", + "geoname_id": 2036328, + "sub_districts": [] + }, + { + "code": "130702", + "name": "桥东", + "level": "THREE_LEVEL", + "geoname_id": 130702, + "sub_districts": [] + }, + { + "code": "130703", + "name": "桥西", + "level": "THREE_LEVEL", + "geoname_id": 130703, + "sub_districts": [] + }, + { + "code": "130725", + "name": "尚义", + "level": "THREE_LEVEL", + "geoname_id": 2035006, + "sub_districts": [] + }, + { + "code": "130708", + "name": "万全", + "level": "THREE_LEVEL", + "geoname_id": 2034205, + "sub_districts": [] + }, + { + "code": "130705", + "name": "宣化", + "level": "THREE_LEVEL", + "geoname_id": 6586385, + "sub_districts": [] + }, + { + "code": "130706", + "name": "下花园", + "level": "THREE_LEVEL", + "geoname_id": 6586384, + "sub_districts": [] + }, + { + "code": "130726", + "name": "蔚县", + "level": "THREE_LEVEL", + "geoname_id": 1785567, + "sub_districts": [] + }, + { + "code": "130727", + "name": "阳原", + "level": "THREE_LEVEL", + "geoname_id": 2033474, + "sub_districts": [] + }, + { + "code": "130722", + "name": "张北", + "level": "THREE_LEVEL", + "geoname_id": 2033210, + "sub_districts": [] + }, + { + "code": "1307730000003", + "name": "张家口市塞北管理区", + "level": "THREE_LEVEL", + "geoname_id": 659010006, + "sub_districts": [] + }, + { + "code": "130731", + "name": "涿鹿", + "level": "THREE_LEVEL", + "geoname_id": 2033068, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "42", + "name": "湖北", + "level": "ONE_LEVEL", + "geoname_id": 1806949, + "sub_districts": [ + { + "code": "422800", + "name": "恩施", + "level": "TWO_LEVEL", + "geoname_id": 1811624, + "sub_districts": [ + { + "code": "422823", + "name": "巴东", + "level": "THREE_LEVEL", + "geoname_id": 1817837, + "sub_districts": [] + }, + { + "code": "422801", + "name": "恩施", + "level": "THREE_LEVEL", + "geoname_id": 1811719, + "sub_districts": [] + }, + { + "code": "422828", + "name": "鹤峰", + "level": "THREE_LEVEL", + "geoname_id": 1808717, + "sub_districts": [] + }, + { + "code": "422822", + "name": "建始", + "level": "THREE_LEVEL", + "geoname_id": 1806147, + "sub_districts": [] + }, + { + "code": "422802", + "name": "利川", + "level": "THREE_LEVEL", + "geoname_id": 1803779, + "sub_districts": [] + }, + { + "code": "422827", + "name": "来凤", + "level": "THREE_LEVEL", + "geoname_id": 1804601, + "sub_districts": [] + }, + { + "code": "422825", + "name": "宣恩", + "level": "THREE_LEVEL", + "geoname_id": 1788076, + "sub_districts": [] + }, + { + "code": "422826", + "name": "咸丰", + "level": "THREE_LEVEL", + "geoname_id": 1790613, + "sub_districts": [] + } + ] + }, + { + "code": "420700", + "name": "鄂州", + "level": "TWO_LEVEL", + "geoname_id": 1811618, + "sub_districts": [ + { + "code": "420704", + "name": "鄂城", + "level": "THREE_LEVEL", + "geoname_id": 420704, + "sub_districts": [] + }, + { + "code": "420703", + "name": "华容", + "level": "THREE_LEVEL", + "geoname_id": 6642288, + "sub_districts": [] + }, + { + "code": "420702", + "name": "梁子湖", + "level": "THREE_LEVEL", + "geoname_id": 6642289, + "sub_districts": [] + } + ] + }, + { + "code": "421100", + "name": "黄冈", + "level": "TWO_LEVEL", + "geoname_id": 1807500, + "sub_districts": [ + { + "code": "421122", + "name": "红安", + "level": "THREE_LEVEL", + "geoname_id": 1808175, + "sub_districts": [] + }, + { + "code": "421127", + "name": "黄梅", + "level": "THREE_LEVEL", + "geoname_id": 1807337, + "sub_districts": [] + }, + { + "code": "421102", + "name": "黄州", + "level": "THREE_LEVEL", + "geoname_id": 1807493, + "sub_districts": [] + }, + { + "code": "421123", + "name": "罗田", + "level": "THREE_LEVEL", + "geoname_id": 1801828, + "sub_districts": [] + }, + { + "code": "421181", + "name": "麻城", + "level": "THREE_LEVEL", + "geoname_id": 1801578, + "sub_districts": [] + }, + { + "code": "421126", + "name": "蕲春", + "level": "THREE_LEVEL", + "geoname_id": 1798090, + "sub_districts": [] + }, + { + "code": "421121", + "name": "团风", + "level": "THREE_LEVEL", + "geoname_id": 6642460, + "sub_districts": [] + }, + { + "code": "421182", + "name": "武穴", + "level": "THREE_LEVEL", + "geoname_id": 1809913, + "sub_districts": [] + }, + { + "code": "421125", + "name": "浠水", + "level": "THREE_LEVEL", + "geoname_id": 1788314, + "sub_districts": [] + }, + { + "code": "421124", + "name": "英山", + "level": "THREE_LEVEL", + "geoname_id": 1786582, + "sub_districts": [] + } + ] + }, + { + "code": "420200", + "name": "黄石", + "level": "TWO_LEVEL", + "geoname_id": 1807225, + "sub_districts": [ + { + "code": "420281", + "name": "大冶", + "level": "THREE_LEVEL", + "geoname_id": 1813203, + "sub_districts": [] + }, + { + "code": "420202", + "name": "黄石港", + "level": "THREE_LEVEL", + "geoname_id": 6642292, + "sub_districts": [] + }, + { + "code": "420205", + "name": "铁山", + "level": "THREE_LEVEL", + "geoname_id": 6642290, + "sub_districts": [] + }, + { + "code": "420204", + "name": "下陆", + "level": "THREE_LEVEL", + "geoname_id": 6642291, + "sub_districts": [] + }, + { + "code": "420203", + "name": "西塞山", + "level": "THREE_LEVEL", + "geoname_id": 6642293, + "sub_districts": [] + }, + { + "code": "420222", + "name": "阳新", + "level": "THREE_LEVEL", + "geoname_id": 1787260, + "sub_districts": [] + } + ] + }, + { + "code": "420800", + "name": "荆门", + "level": "TWO_LEVEL", + "geoname_id": 1805610, + "sub_districts": [ + { + "code": "420802", + "name": "东宝", + "level": "THREE_LEVEL", + "geoname_id": 6642278, + "sub_districts": [] + }, + { + "code": "420804", + "name": "掇刀", + "level": "THREE_LEVEL", + "geoname_id": 6642279, + "sub_districts": [] + }, + { + "code": "4208820000001", + "name": "京山", + "level": "THREE_LEVEL", + "geoname_id": 1805591, + "sub_districts": [] + }, + { + "code": "420822", + "name": "沙洋", + "level": "THREE_LEVEL", + "geoname_id": 6642461, + "sub_districts": [] + }, + { + "code": "420881", + "name": "钟祥", + "level": "THREE_LEVEL", + "geoname_id": 1784277, + "sub_districts": [] + } + ] + }, + { + "code": "421000", + "name": "荆州", + "level": "TWO_LEVEL", + "geoname_id": 1805539, + "sub_districts": [ + { + "code": "421022", + "name": "公安", + "level": "THREE_LEVEL", + "geoname_id": 1810161, + "sub_districts": [] + }, + { + "code": "421083", + "name": "洪湖", + "level": "THREE_LEVEL", + "geoname_id": 1808115, + "sub_districts": [] + }, + { + "code": "421024", + "name": "江陵", + "level": "THREE_LEVEL", + "geoname_id": 1806303, + "sub_districts": [] + }, + { + "code": "4210880000001", + "name": "监利", + "level": "THREE_LEVEL", + "geoname_id": 1806172, + "sub_districts": [] + }, + { + "code": "421003", + "name": "荆州", + "level": "THREE_LEVEL", + "geoname_id": 6642294, + "sub_districts": [] + }, + { + "code": "421002", + "name": "沙市", + "level": "THREE_LEVEL", + "geoname_id": 1795813, + "sub_districts": [] + }, + { + "code": "421081", + "name": "石首", + "level": "THREE_LEVEL", + "geoname_id": 1795004, + "sub_districts": [] + }, + { + "code": "421087", + "name": "松滋", + "level": "THREE_LEVEL", + "geoname_id": 1793943, + "sub_districts": [] + } + ] + }, + { + "code": "429005", + "name": "潜江", + "level": "TWO_LEVEL", + "geoname_id": 1798313, + "sub_districts": [ + { + "code": "429005", + "name": "潜江", + "level": "THREE_LEVEL", + "geoname_id": 429005, + "sub_districts": [] + } + ] + }, + { + "code": "429021", + "name": "神农架", + "level": "TWO_LEVEL", + "geoname_id": 1795614, + "sub_districts": [ + { + "code": "429021", + "name": "神农架", + "level": "THREE_LEVEL", + "geoname_id": 429021, + "sub_districts": [] + } + ] + }, + { + "code": "420300", + "name": "十堰", + "level": "TWO_LEVEL", + "geoname_id": 1794903, + "sub_districts": [ + { + "code": "420381", + "name": "丹江口", + "level": "THREE_LEVEL", + "geoname_id": 1813827, + "sub_districts": [] + }, + { + "code": "420325", + "name": "房县", + "level": "THREE_LEVEL", + "geoname_id": 1811529, + "sub_districts": [] + }, + { + "code": "420302", + "name": "茅箭", + "level": "THREE_LEVEL", + "geoname_id": 6642270, + "sub_districts": [] + }, + { + "code": "420322", + "name": "郧西", + "level": "THREE_LEVEL", + "geoname_id": 1785659, + "sub_districts": [] + }, + { + "code": "420304", + "name": "郧阳", + "level": "THREE_LEVEL", + "geoname_id": 420304, + "sub_districts": [] + }, + { + "code": "420323", + "name": "竹山", + "level": "THREE_LEVEL", + "geoname_id": 1783823, + "sub_districts": [] + }, + { + "code": "420303", + "name": "张湾", + "level": "THREE_LEVEL", + "geoname_id": 6642267, + "sub_districts": [] + }, + { + "code": "420324", + "name": "竹溪", + "level": "THREE_LEVEL", + "geoname_id": 1783788, + "sub_districts": [] + } + ] + }, + { + "code": "421300", + "name": "随州", + "level": "TWO_LEVEL", + "geoname_id": 1793879, + "sub_districts": [ + { + "code": "421381", + "name": "广水", + "level": "THREE_LEVEL", + "geoname_id": 6642416, + "sub_districts": [] + }, + { + "code": "421321", + "name": "随县", + "level": "THREE_LEVEL", + "geoname_id": 421321, + "sub_districts": [] + }, + { + "code": "421303", + "name": "曾都", + "level": "THREE_LEVEL", + "geoname_id": 6642301, + "sub_districts": [] + } + ] + }, + { + "code": "429006", + "name": "天门", + "level": "TWO_LEVEL", + "geoname_id": 1792925, + "sub_districts": [ + { + "code": "429006", + "name": "天门", + "level": "THREE_LEVEL", + "geoname_id": 429006, + "sub_districts": [] + } + ] + }, + { + "code": "420100", + "name": "武汉", + "level": "TWO_LEVEL", + "geoname_id": 1791247, + "sub_districts": [ + { + "code": "420114", + "name": "蔡甸", + "level": "THREE_LEVEL", + "geoname_id": 1808866, + "sub_districts": [] + }, + { + "code": "420112", + "name": "东西湖", + "level": "THREE_LEVEL", + "geoname_id": 6642317, + "sub_districts": [] + }, + { + "code": "420113", + "name": "汉南", + "level": "THREE_LEVEL", + "geoname_id": 6642324, + "sub_districts": [] + }, + { + "code": "420116", + "name": "黄陂", + "level": "THREE_LEVEL", + "geoname_id": 1807304, + "sub_districts": [] + }, + { + "code": "420111", + "name": "洪山", + "level": "THREE_LEVEL", + "geoname_id": 6642321, + "sub_districts": [] + }, + { + "code": "420105", + "name": "汉阳", + "level": "THREE_LEVEL", + "geoname_id": 9166318, + "sub_districts": [] + }, + { + "code": "420102", + "name": "江岸", + "level": "THREE_LEVEL", + "geoname_id": 9166061, + "sub_districts": [] + }, + { + "code": "420103", + "name": "江汉", + "level": "THREE_LEVEL", + "geoname_id": 6642313, + "sub_districts": [] + }, + { + "code": "420115", + "name": "江夏", + "level": "THREE_LEVEL", + "geoname_id": 6642320, + "sub_districts": [] + }, + { + "code": "420104", + "name": "硚口", + "level": "THREE_LEVEL", + "geoname_id": 6642315, + "sub_districts": [] + }, + { + "code": "420107", + "name": "青山", + "level": "THREE_LEVEL", + "geoname_id": 6642178, + "sub_districts": [] + }, + { + "code": "420106", + "name": "武昌", + "level": "THREE_LEVEL", + "geoname_id": 1791349, + "sub_districts": [] + }, + { + "code": "420117", + "name": "新洲", + "level": "THREE_LEVEL", + "geoname_id": 1788446, + "sub_districts": [] + } + ] + }, + { + "code": "420900", + "name": "孝感", + "level": "TWO_LEVEL", + "geoname_id": 1790253, + "sub_districts": [ + { + "code": "420982", + "name": "安陆", + "level": "THREE_LEVEL", + "geoname_id": 1818014, + "sub_districts": [] + }, + { + "code": "420922", + "name": "大悟", + "level": "THREE_LEVEL", + "geoname_id": 1813339, + "sub_districts": [] + }, + { + "code": "420984", + "name": "汉川", + "level": "THREE_LEVEL", + "geoname_id": 1808975, + "sub_districts": [] + }, + { + "code": "420921", + "name": "孝昌", + "level": "THREE_LEVEL", + "geoname_id": 6642281, + "sub_districts": [] + }, + { + "code": "420902", + "name": "孝南", + "level": "THREE_LEVEL", + "geoname_id": 420902, + "sub_districts": [] + }, + { + "code": "420981", + "name": "应城", + "level": "THREE_LEVEL", + "geoname_id": 1786639, + "sub_districts": [] + }, + { + "code": "420923", + "name": "云梦", + "level": "THREE_LEVEL", + "geoname_id": 1785696, + "sub_districts": [] + } + ] + }, + { + "code": "421200", + "name": "咸宁", + "level": "TWO_LEVEL", + "geoname_id": 1790395, + "sub_districts": [ + { + "code": "421281", + "name": "赤壁", + "level": "THREE_LEVEL", + "geoname_id": 1798467, + "sub_districts": [] + }, + { + "code": "421223", + "name": "崇阳", + "level": "THREE_LEVEL", + "geoname_id": 1814876, + "sub_districts": [] + }, + { + "code": "421221", + "name": "嘉鱼", + "level": "THREE_LEVEL", + "geoname_id": 1805946, + "sub_districts": [] + }, + { + "code": "421222", + "name": "通城", + "level": "THREE_LEVEL", + "geoname_id": 1792697, + "sub_districts": [] + }, + { + "code": "421224", + "name": "通山", + "level": "THREE_LEVEL", + "geoname_id": 1792578, + "sub_districts": [] + }, + { + "code": "421202", + "name": "咸安", + "level": "THREE_LEVEL", + "geoname_id": 421202, + "sub_districts": [] + } + ] + }, + { + "code": "429004", + "name": "仙桃", + "level": "TWO_LEVEL", + "geoname_id": 1790370, + "sub_districts": [ + { + "code": "429004", + "name": "仙桃", + "level": "THREE_LEVEL", + "geoname_id": 429004, + "sub_districts": [] + } + ] + }, + { + "code": "420600", + "name": "襄阳", + "level": "TWO_LEVEL", + "geoname_id": 1790587, + "sub_districts": [ + { + "code": "420626", + "name": "保康", + "level": "THREE_LEVEL", + "geoname_id": 1816932, + "sub_districts": [] + }, + { + "code": "420606", + "name": "樊城", + "level": "THREE_LEVEL", + "geoname_id": 6642276, + "sub_districts": [] + }, + { + "code": "420625", + "name": "谷城", + "level": "THREE_LEVEL", + "geoname_id": 1809578, + "sub_districts": [] + }, + { + "code": "420682", + "name": "老河口", + "level": "THREE_LEVEL", + "geoname_id": 1804385, + "sub_districts": [] + }, + { + "code": "420624", + "name": "南漳", + "level": "THREE_LEVEL", + "geoname_id": 1799567, + "sub_districts": [] + }, + { + "code": "420602", + "name": "襄城", + "level": "THREE_LEVEL", + "geoname_id": 6642277, + "sub_districts": [] + }, + { + "code": "420607", + "name": "襄州", + "level": "THREE_LEVEL", + "geoname_id": 1790456, + "sub_districts": [] + }, + { + "code": "420684", + "name": "宜城", + "level": "THREE_LEVEL", + "geoname_id": 1786754, + "sub_districts": [] + }, + { + "code": "420683", + "name": "枣阳", + "level": "THREE_LEVEL", + "geoname_id": 1785461, + "sub_districts": [] + } + ] + }, + { + "code": "420500", + "name": "宜昌", + "level": "TWO_LEVEL", + "geoname_id": 1786764, + "sub_districts": [ + { + "code": "420528", + "name": "长阳", + "level": "THREE_LEVEL", + "geoname_id": 1815484, + "sub_districts": [] + }, + { + "code": "420504", + "name": "点军", + "level": "THREE_LEVEL", + "geoname_id": 6642272, + "sub_districts": [] + }, + { + "code": "420582", + "name": "当阳", + "level": "THREE_LEVEL", + "geoname_id": 1813848, + "sub_districts": [] + }, + { + "code": "420529", + "name": "五峰", + "level": "THREE_LEVEL", + "geoname_id": 1791282, + "sub_districts": [] + }, + { + "code": "420503", + "name": "伍家岗", + "level": "THREE_LEVEL", + "geoname_id": 6642295, + "sub_districts": [] + }, + { + "code": "420502", + "name": "西陵", + "level": "THREE_LEVEL", + "geoname_id": 6642273, + "sub_districts": [] + }, + { + "code": "420526", + "name": "兴山", + "level": "THREE_LEVEL", + "geoname_id": 1788934, + "sub_districts": [] + }, + { + "code": "420505", + "name": "猇亭", + "level": "THREE_LEVEL", + "geoname_id": 6642298, + "sub_districts": [] + }, + { + "code": "420525", + "name": "远安", + "level": "THREE_LEVEL", + "geoname_id": 1786121, + "sub_districts": [] + }, + { + "code": "420581", + "name": "宜都", + "level": "THREE_LEVEL", + "geoname_id": 1786728, + "sub_districts": [] + }, + { + "code": "420506", + "name": "夷陵", + "level": "THREE_LEVEL", + "geoname_id": 1783569, + "sub_districts": [] + }, + { + "code": "420527", + "name": "秭归", + "level": "THREE_LEVEL", + "geoname_id": 1783743, + "sub_districts": [] + }, + { + "code": "420583", + "name": "枝江", + "level": "THREE_LEVEL", + "geoname_id": 1784523, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "23", + "name": "黑龙江", + "level": "ONE_LEVEL", + "geoname_id": 2036965, + "sub_districts": [ + { + "code": "230600", + "name": "大庆", + "level": "TWO_LEVEL", + "geoname_id": 2037847, + "sub_districts": [ + { + "code": "230624", + "name": "杜尔伯特", + "level": "THREE_LEVEL", + "geoname_id": 2037557, + "sub_districts": [] + }, + { + "code": "230606", + "name": "大同", + "level": "THREE_LEVEL", + "geoname_id": 6643370, + "sub_districts": [] + }, + { + "code": "230605", + "name": "红岗", + "level": "THREE_LEVEL", + "geoname_id": 6643346, + "sub_districts": [] + }, + { + "code": "230623", + "name": "林甸", + "level": "THREE_LEVEL", + "geoname_id": 2036083, + "sub_districts": [] + }, + { + "code": "230603", + "name": "龙凤", + "level": "THREE_LEVEL", + "geoname_id": 6643350, + "sub_districts": [] + }, + { + "code": "230604", + "name": "让胡路", + "level": "THREE_LEVEL", + "geoname_id": 6643356, + "sub_districts": [] + }, + { + "code": "230602", + "name": "萨尔图", + "level": "THREE_LEVEL", + "geoname_id": 6643354, + "sub_districts": [] + }, + { + "code": "230622", + "name": "肇源", + "level": "THREE_LEVEL", + "geoname_id": 2033148, + "sub_districts": [] + }, + { + "code": "230621", + "name": "肇州", + "level": "THREE_LEVEL", + "geoname_id": 2033146, + "sub_districts": [] + } + ] + }, + { + "code": "232700", + "name": "大兴安岭", + "level": "TWO_LEVEL", + "geoname_id": 2037961, + "sub_districts": [ + { + "code": "232721", + "name": "呼玛", + "level": "THREE_LEVEL", + "geoname_id": 2036654, + "sub_districts": [] + }, + { + "code": "2327640000001", + "name": "呼中", + "level": "THREE_LEVEL", + "geoname_id": 60000916, + "sub_districts": [] + }, + { + "code": "2327610000001", + "name": "加格达奇", + "level": "THREE_LEVEL", + "geoname_id": 60000800, + "sub_districts": [] + }, + { + "code": "232701", + "name": "漠河", + "level": "THREE_LEVEL", + "geoname_id": 2035728, + "sub_districts": [] + }, + { + "code": "2327620000001", + "name": "松岭", + "level": "THREE_LEVEL", + "geoname_id": 60000558, + "sub_districts": [] + }, + { + "code": "232722", + "name": "塔河", + "level": "THREE_LEVEL", + "geoname_id": 2034613, + "sub_districts": [] + }, + { + "code": "2327630000001", + "name": "新林", + "level": "THREE_LEVEL", + "geoname_id": 60000149, + "sub_districts": [] + } + ] + }, + { + "code": "230100", + "name": "哈尔滨", + "level": "TWO_LEVEL", + "geoname_id": 2037013, + "sub_districts": [ + { + "code": "230112", + "name": "阿城", + "level": "THREE_LEVEL", + "geoname_id": 2038679, + "sub_districts": [] + }, + { + "code": "230125", + "name": "宾县", + "level": "THREE_LEVEL", + "geoname_id": 2038284, + "sub_districts": [] + }, + { + "code": "230126", + "name": "巴彦", + "level": "THREE_LEVEL", + "geoname_id": 2038370, + "sub_districts": [] + }, + { + "code": "230102", + "name": "道里", + "level": "THREE_LEVEL", + "geoname_id": 6643336, + "sub_districts": [] + }, + { + "code": "230104", + "name": "道外", + "level": "THREE_LEVEL", + "geoname_id": 6643342, + "sub_districts": [] + }, + { + "code": "230124", + "name": "方正", + "level": "THREE_LEVEL", + "geoname_id": 2037422, + "sub_districts": [] + }, + { + "code": "230111", + "name": "呼兰", + "level": "THREE_LEVEL", + "geoname_id": 2036667, + "sub_districts": [] + }, + { + "code": "230127", + "name": "木兰", + "level": "THREE_LEVEL", + "geoname_id": 2035704, + "sub_districts": [] + }, + { + "code": "230103", + "name": "南岗", + "level": "THREE_LEVEL", + "geoname_id": 6643344, + "sub_districts": [] + }, + { + "code": "230108", + "name": "平房", + "level": "THREE_LEVEL", + "geoname_id": 6643341, + "sub_districts": [] + }, + { + "code": "230109", + "name": "松北", + "level": "THREE_LEVEL", + "geoname_id": 6643335, + "sub_districts": [] + }, + { + "code": "230113", + "name": "双城", + "level": "THREE_LEVEL", + "geoname_id": 2034831, + "sub_districts": [] + }, + { + "code": "230183", + "name": "尚志", + "level": "THREE_LEVEL", + "geoname_id": 2035002, + "sub_districts": [] + }, + { + "code": "230128", + "name": "通河", + "level": "THREE_LEVEL", + "geoname_id": 2034415, + "sub_districts": [] + }, + { + "code": "230184", + "name": "五常", + "level": "THREE_LEVEL", + "geoname_id": 2034141, + "sub_districts": [] + }, + { + "code": "230110", + "name": "香坊", + "level": "THREE_LEVEL", + "geoname_id": 6643345, + "sub_districts": [] + }, + { + "code": "230123", + "name": "依兰", + "level": "THREE_LEVEL", + "geoname_id": 2033402, + "sub_districts": [] + }, + { + "code": "230129", + "name": "延寿", + "level": "THREE_LEVEL", + "geoname_id": 2033453, + "sub_districts": [] + } + ] + }, + { + "code": "230400", + "name": "鹤岗", + "level": "TWO_LEVEL", + "geoname_id": 2036986, + "sub_districts": [ + { + "code": "230406", + "name": "东山", + "level": "THREE_LEVEL", + "geoname_id": 6643252, + "sub_districts": [] + }, + { + "code": "230403", + "name": "工农", + "level": "THREE_LEVEL", + "geoname_id": 6643254, + "sub_districts": [] + }, + { + "code": "230421", + "name": "萝北", + "level": "THREE_LEVEL", + "geoname_id": 2035916, + "sub_districts": [] + }, + { + "code": "230404", + "name": "南山", + "level": "THREE_LEVEL", + "geoname_id": 6643253, + "sub_districts": [] + }, + { + "code": "230422", + "name": "绥滨", + "level": "THREE_LEVEL", + "geoname_id": 2034659, + "sub_districts": [] + }, + { + "code": "230405", + "name": "兴安", + "level": "THREE_LEVEL", + "geoname_id": 6643358, + "sub_districts": [] + }, + { + "code": "230407", + "name": "兴山", + "level": "THREE_LEVEL", + "geoname_id": 6643251, + "sub_districts": [] + }, + { + "code": "230402", + "name": "向阳", + "level": "THREE_LEVEL", + "geoname_id": 230402, + "sub_districts": [] + } + ] + }, + { + "code": "231100", + "name": "黑河", + "level": "TWO_LEVEL", + "geoname_id": 2036973, + "sub_districts": [ + { + "code": "231102", + "name": "爱辉", + "level": "THREE_LEVEL", + "geoname_id": 2036970, + "sub_districts": [] + }, + { + "code": "231181", + "name": "北安", + "level": "THREE_LEVEL", + "geoname_id": 2038362, + "sub_districts": [] + }, + { + "code": "2311830000001", + "name": "嫩江", + "level": "THREE_LEVEL", + "geoname_id": 2035598, + "sub_districts": [] + }, + { + "code": "231124", + "name": "孙吴", + "level": "THREE_LEVEL", + "geoname_id": 2034628, + "sub_districts": [] + }, + { + "code": "231182", + "name": "五大连池", + "level": "THREE_LEVEL", + "geoname_id": 2034136, + "sub_districts": [] + }, + { + "code": "231123", + "name": "逊克", + "level": "THREE_LEVEL", + "geoname_id": 2033549, + "sub_districts": [] + } + ] + }, + { + "code": "230800", + "name": "佳木斯", + "level": "TWO_LEVEL", + "geoname_id": 2036581, + "sub_districts": [ + { + "code": "230805", + "name": "东风", + "level": "THREE_LEVEL", + "geoname_id": 6643255, + "sub_districts": [] + }, + { + "code": "230882", + "name": "富锦", + "level": "THREE_LEVEL", + "geoname_id": 2037374, + "sub_districts": [] + }, + { + "code": "230883", + "name": "抚远", + "level": "THREE_LEVEL", + "geoname_id": 2037329, + "sub_districts": [] + }, + { + "code": "230826", + "name": "桦川", + "level": "THREE_LEVEL", + "geoname_id": 2036780, + "sub_districts": [] + }, + { + "code": "230822", + "name": "桦南", + "level": "THREE_LEVEL", + "geoname_id": 2036752, + "sub_districts": [] + }, + { + "code": "230811", + "name": "郊区", + "level": "THREE_LEVEL", + "geoname_id": 6643256, + "sub_districts": [] + }, + { + "code": "230804", + "name": "前进", + "level": "THREE_LEVEL", + "geoname_id": 6643260, + "sub_districts": [] + }, + { + "code": "230881", + "name": "同江", + "level": "THREE_LEVEL", + "geoname_id": 2034405, + "sub_districts": [] + }, + { + "code": "230828", + "name": "汤原", + "level": "THREE_LEVEL", + "geoname_id": 2034513, + "sub_districts": [] + }, + { + "code": "230803", + "name": "向阳", + "level": "THREE_LEVEL", + "geoname_id": 230803, + "sub_districts": [] + } + ] + }, + { + "code": "230300", + "name": "鸡西", + "level": "TWO_LEVEL", + "geoname_id": 2036389, + "sub_districts": [ + { + "code": "230306", + "name": "城子河", + "level": "THREE_LEVEL", + "geoname_id": 6643320, + "sub_districts": [] + }, + { + "code": "230304", + "name": "滴道", + "level": "THREE_LEVEL", + "geoname_id": 6643326, + "sub_districts": [] + }, + { + "code": "230381", + "name": "虎林", + "level": "THREE_LEVEL", + "geoname_id": 2036665, + "sub_districts": [] + }, + { + "code": "230303", + "name": "恒山", + "level": "THREE_LEVEL", + "geoname_id": 6643321, + "sub_districts": [] + }, + { + "code": "230321", + "name": "鸡东", + "level": "THREE_LEVEL", + "geoname_id": 2036518, + "sub_districts": [] + }, + { + "code": "230302", + "name": "鸡冠", + "level": "THREE_LEVEL", + "geoname_id": 6643323, + "sub_districts": [] + }, + { + "code": "230305", + "name": "梨树", + "level": "THREE_LEVEL", + "geoname_id": 6643319, + "sub_districts": [] + }, + { + "code": "230307", + "name": "麻山", + "level": "THREE_LEVEL", + "geoname_id": 6643317, + "sub_districts": [] + }, + { + "code": "230382", + "name": "密山", + "level": "THREE_LEVEL", + "geoname_id": 2035745, + "sub_districts": [] + } + ] + }, + { + "code": "231000", + "name": "牡丹江", + "level": "TWO_LEVEL", + "geoname_id": 2035715, + "sub_districts": [ + { + "code": "231004", + "name": "爱民", + "level": "THREE_LEVEL", + "geoname_id": 6643316, + "sub_districts": [] + }, + { + "code": "231002", + "name": "东安", + "level": "THREE_LEVEL", + "geoname_id": 6643313, + "sub_districts": [] + }, + { + "code": "231086", + "name": "东宁", + "level": "THREE_LEVEL", + "geoname_id": 2037610, + "sub_districts": [] + }, + { + "code": "231083", + "name": "海林", + "level": "THREE_LEVEL", + "geoname_id": 2037075, + "sub_districts": [] + }, + { + "code": "231025", + "name": "林口", + "level": "THREE_LEVEL", + "geoname_id": 2036065, + "sub_districts": [] + }, + { + "code": "231085", + "name": "穆棱", + "level": "THREE_LEVEL", + "geoname_id": 2038482, + "sub_districts": [] + }, + { + "code": "231084", + "name": "宁安", + "level": "THREE_LEVEL", + "geoname_id": 2035587, + "sub_districts": [] + }, + { + "code": "231081", + "name": "绥芬河", + "level": "THREE_LEVEL", + "geoname_id": 2034656, + "sub_districts": [] + }, + { + "code": "231005", + "name": "西安", + "level": "THREE_LEVEL", + "geoname_id": 6643309, + "sub_districts": [] + }, + { + "code": "231003", + "name": "阳明", + "level": "THREE_LEVEL", + "geoname_id": 6643311, + "sub_districts": [] + } + ] + }, + { + "code": "230200", + "name": "齐齐哈尔", + "level": "TWO_LEVEL", + "geoname_id": 2035265, + "sub_districts": [ + { + "code": "230205", + "name": "昂昂溪", + "level": "THREE_LEVEL", + "geoname_id": 6643287, + "sub_districts": [] + }, + { + "code": "230231", + "name": "拜泉", + "level": "THREE_LEVEL", + "geoname_id": 2038540, + "sub_districts": [] + }, + { + "code": "230206", + "name": "富拉尔基", + "level": "THREE_LEVEL", + "geoname_id": 6643301, + "sub_districts": [] + }, + { + "code": "230227", + "name": "富裕", + "level": "THREE_LEVEL", + "geoname_id": 2037327, + "sub_districts": [] + }, + { + "code": "230225", + "name": "甘南", + "level": "THREE_LEVEL", + "geoname_id": 2037310, + "sub_districts": [] + }, + { + "code": "230203", + "name": "建华", + "level": "THREE_LEVEL", + "geoname_id": 6643288, + "sub_districts": [] + }, + { + "code": "230230", + "name": "克东", + "level": "THREE_LEVEL", + "geoname_id": 2036311, + "sub_districts": [] + }, + { + "code": "230229", + "name": "克山", + "level": "THREE_LEVEL", + "geoname_id": 2036300, + "sub_districts": [] + }, + { + "code": "230221", + "name": "龙江", + "level": "THREE_LEVEL", + "geoname_id": 2035968, + "sub_districts": [] + }, + { + "code": "230202", + "name": "龙沙", + "level": "THREE_LEVEL", + "geoname_id": 6643285, + "sub_districts": [] + }, + { + "code": "230208", + "name": "梅里斯", + "level": "THREE_LEVEL", + "geoname_id": 6643304, + "sub_districts": [] + }, + { + "code": "230281", + "name": "讷河", + "level": "THREE_LEVEL", + "geoname_id": 2035609, + "sub_districts": [] + }, + { + "code": "230207", + "name": "碾子山", + "level": "THREE_LEVEL", + "geoname_id": 6643357, + "sub_districts": [] + }, + { + "code": "230204", + "name": "铁锋", + "level": "THREE_LEVEL", + "geoname_id": 6643307, + "sub_districts": [] + }, + { + "code": "230224", + "name": "泰来", + "level": "THREE_LEVEL", + "geoname_id": 2034598, + "sub_districts": [] + }, + { + "code": "230223", + "name": "依安", + "level": "THREE_LEVEL", + "geoname_id": 2033414, + "sub_districts": [] + } + ] + }, + { + "code": "230900", + "name": "七台河", + "level": "TWO_LEVEL", + "geoname_id": 2035260, + "sub_districts": [ + { + "code": "230921", + "name": "勃利", + "level": "THREE_LEVEL", + "geoname_id": 2038271, + "sub_districts": [] + }, + { + "code": "230904", + "name": "茄子河", + "level": "THREE_LEVEL", + "geoname_id": 6643267, + "sub_districts": [] + }, + { + "code": "230903", + "name": "桃山", + "level": "THREE_LEVEL", + "geoname_id": 6643268, + "sub_districts": [] + }, + { + "code": "230902", + "name": "新兴", + "level": "THREE_LEVEL", + "geoname_id": 6643266, + "sub_districts": [] + } + ] + }, + { + "code": "231200", + "name": "绥化", + "level": "TWO_LEVEL", + "geoname_id": 2034655, + "sub_districts": [ + { + "code": "231281", + "name": "安达", + "level": "THREE_LEVEL", + "geoname_id": 2038649, + "sub_districts": [] + }, + { + "code": "231202", + "name": "北林", + "level": "THREE_LEVEL", + "geoname_id": 2034653, + "sub_districts": [] + }, + { + "code": "231283", + "name": "海伦", + "level": "THREE_LEVEL", + "geoname_id": 2037067, + "sub_districts": [] + }, + { + "code": "231222", + "name": "兰西", + "level": "THREE_LEVEL", + "geoname_id": 2036225, + "sub_districts": [] + }, + { + "code": "231225", + "name": "明水", + "level": "THREE_LEVEL", + "geoname_id": 2035758, + "sub_districts": [] + }, + { + "code": "231224", + "name": "庆安", + "level": "THREE_LEVEL", + "geoname_id": 2035335, + "sub_districts": [] + }, + { + "code": "231223", + "name": "青冈", + "level": "THREE_LEVEL", + "geoname_id": 2035324, + "sub_districts": [] + }, + { + "code": "231226", + "name": "绥棱", + "level": "THREE_LEVEL", + "geoname_id": 2034650, + "sub_districts": [] + }, + { + "code": "231221", + "name": "望奎", + "level": "THREE_LEVEL", + "geoname_id": 2034227, + "sub_districts": [] + }, + { + "code": "231282", + "name": "肇东", + "level": "THREE_LEVEL", + "geoname_id": 2033168, + "sub_districts": [] + } + ] + }, + { + "code": "230500", + "name": "双鸭山", + "level": "TWO_LEVEL", + "geoname_id": 2034786, + "sub_districts": [ + { + "code": "230523", + "name": "宝清", + "level": "THREE_LEVEL", + "geoname_id": 2038445, + "sub_districts": [] + }, + { + "code": "230506", + "name": "宝山", + "level": "THREE_LEVEL", + "geoname_id": 6643262, + "sub_districts": [] + }, + { + "code": "230502", + "name": "尖山", + "level": "THREE_LEVEL", + "geoname_id": 6643263, + "sub_districts": [] + }, + { + "code": "230521", + "name": "集贤", + "level": "THREE_LEVEL", + "geoname_id": 2036384, + "sub_districts": [] + }, + { + "code": "230503", + "name": "岭东", + "level": "THREE_LEVEL", + "geoname_id": 6643265, + "sub_districts": [] + }, + { + "code": "230524", + "name": "饶河", + "level": "THREE_LEVEL", + "geoname_id": 2035222, + "sub_districts": [] + }, + { + "code": "230505", + "name": "四方台", + "level": "THREE_LEVEL", + "geoname_id": 2034739, + "sub_districts": [] + }, + { + "code": "230522", + "name": "友谊", + "level": "THREE_LEVEL", + "geoname_id": 2033296, + "sub_districts": [] + } + ] + }, + { + "code": "230700", + "name": "伊春", + "level": "TWO_LEVEL", + "geoname_id": 2033413, + "sub_districts": [ + { + "code": "230725", + "name": "大箐山", + "level": "THREE_LEVEL", + "geoname_id": 230725, + "sub_districts": [] + }, + { + "code": "230724", + "name": "丰林", + "level": "THREE_LEVEL", + "geoname_id": 230724, + "sub_districts": [] + }, + { + "code": "230751", + "name": "金林", + "level": "THREE_LEVEL", + "geoname_id": 230751, + "sub_districts": [] + }, + { + "code": "230722", + "name": "嘉荫", + "level": "THREE_LEVEL", + "geoname_id": 2036522, + "sub_districts": [] + }, + { + "code": "2307260000001", + "name": "南岔", + "level": "THREE_LEVEL", + "geoname_id": 6643279, + "sub_districts": [] + }, + { + "code": "230781", + "name": "铁力", + "level": "THREE_LEVEL", + "geoname_id": 2034440, + "sub_districts": [] + }, + { + "code": "230723", + "name": "汤旺", + "level": "THREE_LEVEL", + "geoname_id": 203341301, + "sub_districts": [] + }, + { + "code": "230718", + "name": "乌翠", + "level": "THREE_LEVEL", + "geoname_id": 230718, + "sub_districts": [] + }, + { + "code": "2307190000001", + "name": "友好", + "level": "THREE_LEVEL", + "geoname_id": 6643269, + "sub_districts": [] + }, + { + "code": "230717", + "name": "伊美", + "level": "THREE_LEVEL", + "geoname_id": 230717, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "41", + "name": "河南", + "level": "ONE_LEVEL", + "geoname_id": 1808520, + "sub_districts": [ + { + "code": "410500", + "name": "安阳", + "level": "TWO_LEVEL", + "geoname_id": 1785294, + "sub_districts": [ + { + "code": "410522", + "name": "安阳", + "level": "THREE_LEVEL", + "geoname_id": 1817941, + "sub_districts": [] + }, + { + "code": "410503", + "name": "北关", + "level": "THREE_LEVEL", + "geoname_id": 6602265, + "sub_districts": [] + }, + { + "code": "410526", + "name": "滑县", + "level": "THREE_LEVEL", + "geoname_id": 1807006, + "sub_districts": [] + }, + { + "code": "410506", + "name": "龙安", + "level": "THREE_LEVEL", + "geoname_id": 6602286, + "sub_districts": [] + }, + { + "code": "410581", + "name": "林州", + "level": "THREE_LEVEL", + "geoname_id": 1803329, + "sub_districts": [] + }, + { + "code": "410527", + "name": "内黄", + "level": "THREE_LEVEL", + "geoname_id": 1799493, + "sub_districts": [] + }, + { + "code": "410523", + "name": "汤阴", + "level": "THREE_LEVEL", + "geoname_id": 1793293, + "sub_districts": [] + }, + { + "code": "410502", + "name": "文峰", + "level": "THREE_LEVEL", + "geoname_id": 6602263, + "sub_districts": [] + }, + { + "code": "410505", + "name": "殷都", + "level": "THREE_LEVEL", + "geoname_id": 6602264, + "sub_districts": [] + } + ] + }, + { + "code": "410600", + "name": "鹤壁", + "level": "TWO_LEVEL", + "geoname_id": 1808770, + "sub_districts": [ + { + "code": "410602", + "name": "鹤山", + "level": "THREE_LEVEL", + "geoname_id": 6602261, + "sub_districts": [] + }, + { + "code": "410611", + "name": "淇滨", + "level": "THREE_LEVEL", + "geoname_id": 6602294, + "sub_districts": [] + }, + { + "code": "410622", + "name": "淇县", + "level": "THREE_LEVEL", + "geoname_id": 1797436, + "sub_districts": [] + }, + { + "code": "410603", + "name": "山城", + "level": "THREE_LEVEL", + "geoname_id": 6602260, + "sub_districts": [] + }, + { + "code": "410621", + "name": "浚县", + "level": "THREE_LEVEL", + "geoname_id": 1787875, + "sub_districts": [] + } + ] + }, + { + "code": "419001", + "name": "济源", + "level": "TWO_LEVEL", + "geoname_id": 1805012, + "sub_districts": [ + { + "code": "419001", + "name": "济源", + "level": "THREE_LEVEL", + "geoname_id": 1805010, + "sub_districts": [] + } + ] + }, + { + "code": "410800", + "name": "焦作", + "level": "TWO_LEVEL", + "geoname_id": 1805987, + "sub_districts": [ + { + "code": "410822", + "name": "博爱", + "level": "THREE_LEVEL", + "geoname_id": 1816305, + "sub_districts": [] + }, + { + "code": "410802", + "name": "解放", + "level": "THREE_LEVEL", + "geoname_id": 6602290, + "sub_districts": [] + }, + { + "code": "410804", + "name": "马村", + "level": "THREE_LEVEL", + "geoname_id": 6602271, + "sub_districts": [] + }, + { + "code": "410883", + "name": "孟州", + "level": "THREE_LEVEL", + "geoname_id": 1800685, + "sub_districts": [] + }, + { + "code": "410882", + "name": "沁阳", + "level": "THREE_LEVEL", + "geoname_id": 1797556, + "sub_districts": [] + }, + { + "code": "410811", + "name": "山阳", + "level": "THREE_LEVEL", + "geoname_id": 6602293, + "sub_districts": [] + }, + { + "code": "410825", + "name": "温县", + "level": "THREE_LEVEL", + "geoname_id": 1791407, + "sub_districts": [] + }, + { + "code": "410823", + "name": "武陟", + "level": "THREE_LEVEL", + "geoname_id": 1790843, + "sub_districts": [] + }, + { + "code": "410821", + "name": "修武", + "level": "THREE_LEVEL", + "geoname_id": 1788248, + "sub_districts": [] + }, + { + "code": "410803", + "name": "中站", + "level": "THREE_LEVEL", + "geoname_id": 6602272, + "sub_districts": [] + } + ] + }, + { + "code": "410200", + "name": "开封", + "level": "TWO_LEVEL", + "geoname_id": 1804879, + "sub_districts": [ + { + "code": "410204", + "name": "鼓楼", + "level": "THREE_LEVEL", + "geoname_id": 6602280, + "sub_districts": [] + }, + { + "code": "410225", + "name": "兰考", + "level": "THREE_LEVEL", + "geoname_id": 1804474, + "sub_districts": [] + }, + { + "code": "410202", + "name": "龙亭", + "level": "THREE_LEVEL", + "geoname_id": 6602279, + "sub_districts": [] + }, + { + "code": "410221", + "name": "杞县", + "level": "THREE_LEVEL", + "geoname_id": 1797437, + "sub_districts": [] + }, + { + "code": "410203", + "name": "顺河", + "level": "THREE_LEVEL", + "geoname_id": 6602278, + "sub_districts": [] + }, + { + "code": "410222", + "name": "通许", + "level": "THREE_LEVEL", + "geoname_id": 1792540, + "sub_districts": [] + }, + { + "code": "410223", + "name": "尉氏", + "level": "THREE_LEVEL", + "geoname_id": 1791609, + "sub_districts": [] + }, + { + "code": "410212", + "name": "祥符", + "level": "THREE_LEVEL", + "geoname_id": 410212, + "sub_districts": [] + }, + { + "code": "410205", + "name": "禹王台", + "level": "THREE_LEVEL", + "geoname_id": 6602281, + "sub_districts": [] + } + ] + }, + { + "code": "411100", + "name": "漯河", + "level": "TWO_LEVEL", + "geoname_id": 1801934, + "sub_districts": [ + { + "code": "411122", + "name": "临颍", + "level": "THREE_LEVEL", + "geoname_id": 1803314, + "sub_districts": [] + }, + { + "code": "411121", + "name": "舞阳", + "level": "THREE_LEVEL", + "geoname_id": 1790881, + "sub_districts": [] + }, + { + "code": "411103", + "name": "郾城", + "level": "THREE_LEVEL", + "geoname_id": 1787742, + "sub_districts": [] + }, + { + "code": "411102", + "name": "源汇", + "level": "THREE_LEVEL", + "geoname_id": 6602251, + "sub_districts": [] + }, + { + "code": "411104", + "name": "召陵", + "level": "THREE_LEVEL", + "geoname_id": 6602250, + "sub_districts": [] + } + ] + }, + { + "code": "410300", + "name": "洛阳", + "level": "TWO_LEVEL", + "geoname_id": 1801792, + "sub_districts": [ + { + "code": "410304", + "name": "瀍河", + "level": "THREE_LEVEL", + "geoname_id": 6602262, + "sub_districts": [] + }, + { + "code": "410305", + "name": "涧西", + "level": "THREE_LEVEL", + "geoname_id": 6602287, + "sub_districts": [] + }, + { + "code": "410302", + "name": "老城", + "level": "THREE_LEVEL", + "geoname_id": 6602296, + "sub_districts": [] + }, + { + "code": "410324", + "name": "栾川", + "level": "THREE_LEVEL", + "geoname_id": 1802201, + "sub_districts": [] + }, + { + "code": "410311", + "name": "洛龙", + "level": "THREE_LEVEL", + "geoname_id": 6602285, + "sub_districts": [] + }, + { + "code": "410328", + "name": "洛宁", + "level": "THREE_LEVEL", + "geoname_id": 1801867, + "sub_districts": [] + }, + { + "code": "4103080000000", + "name": "孟津", + "level": "THREE_LEVEL", + "geoname_id": 1800717, + "sub_districts": [] + }, + { + "code": "410326", + "name": "汝阳", + "level": "THREE_LEVEL", + "geoname_id": 1797013, + "sub_districts": [] + }, + { + "code": "410325", + "name": "嵩县", + "level": "THREE_LEVEL", + "geoname_id": 1793967, + "sub_districts": [] + }, + { + "code": "410323", + "name": "新安", + "level": "THREE_LEVEL", + "geoname_id": 1789239, + "sub_districts": [] + }, + { + "code": "410303", + "name": "西工", + "level": "THREE_LEVEL", + "geoname_id": 6602288, + "sub_districts": [] + }, + { + "code": "410329", + "name": "伊川", + "level": "THREE_LEVEL", + "geoname_id": 1786749, + "sub_districts": [] + }, + { + "code": "4103070000001", + "name": "偃师", + "level": "THREE_LEVEL", + "geoname_id": 1787098, + "sub_districts": [] + }, + { + "code": "410327", + "name": "宜阳", + "level": "THREE_LEVEL", + "geoname_id": 1786415, + "sub_districts": [] + } + ] + }, + { + "code": "411300", + "name": "南阳", + "level": "TWO_LEVEL", + "geoname_id": 1799629, + "sub_districts": [ + { + "code": "411381", + "name": "邓州", + "level": "THREE_LEVEL", + "geoname_id": 1812991, + "sub_districts": [] + }, + { + "code": "411322", + "name": "方城", + "level": "THREE_LEVEL", + "geoname_id": 1811590, + "sub_districts": [] + }, + { + "code": "411325", + "name": "内乡", + "level": "THREE_LEVEL", + "geoname_id": 1799475, + "sub_districts": [] + }, + { + "code": "411321", + "name": "南召", + "level": "THREE_LEVEL", + "geoname_id": 1799561, + "sub_districts": [] + }, + { + "code": "411327", + "name": "社旗", + "level": "THREE_LEVEL", + "geoname_id": 1795552, + "sub_districts": [] + }, + { + "code": "411330", + "name": "桐柏", + "level": "THREE_LEVEL", + "geoname_id": 1792711, + "sub_districts": [] + }, + { + "code": "411328", + "name": "唐河", + "level": "THREE_LEVEL", + "geoname_id": 1793414, + "sub_districts": [] + }, + { + "code": "411302", + "name": "宛城", + "level": "THREE_LEVEL", + "geoname_id": 6602248, + "sub_districts": [] + }, + { + "code": "411303", + "name": "卧龙", + "level": "THREE_LEVEL", + "geoname_id": 6602247, + "sub_districts": [] + }, + { + "code": "411326", + "name": "淅川", + "level": "THREE_LEVEL", + "geoname_id": 1789623, + "sub_districts": [] + }, + { + "code": "411323", + "name": "西峡", + "level": "THREE_LEVEL", + "geoname_id": 1788197, + "sub_districts": [] + }, + { + "code": "411329", + "name": "新野", + "level": "THREE_LEVEL", + "geoname_id": 1788521, + "sub_districts": [] + }, + { + "code": "411324", + "name": "镇平", + "level": "THREE_LEVEL", + "geoname_id": 1784615, + "sub_districts": [] + } + ] + }, + { + "code": "410400", + "name": "平顶山", + "level": "TWO_LEVEL", + "geoname_id": 1798827, + "sub_districts": [ + { + "code": "410421", + "name": "宝丰", + "level": "THREE_LEVEL", + "geoname_id": 1816962, + "sub_districts": [] + }, + { + "code": "410425", + "name": "郏县", + "level": "THREE_LEVEL", + "geoname_id": 1805959, + "sub_districts": [] + }, + { + "code": "410423", + "name": "鲁山", + "level": "THREE_LEVEL", + "geoname_id": 1801736, + "sub_districts": [] + }, + { + "code": "410482", + "name": "汝州", + "level": "THREE_LEVEL", + "geoname_id": 1803358, + "sub_districts": [] + }, + { + "code": "410404", + "name": "石龙", + "level": "THREE_LEVEL", + "geoname_id": 6602255, + "sub_districts": [] + }, + { + "code": "410403", + "name": "卫东", + "level": "THREE_LEVEL", + "geoname_id": 6602252, + "sub_districts": [] + }, + { + "code": "410481", + "name": "舞钢", + "level": "THREE_LEVEL", + "geoname_id": 1910201, + "sub_districts": [] + }, + { + "code": "410402", + "name": "新华", + "level": "THREE_LEVEL", + "geoname_id": 6602253, + "sub_districts": [] + }, + { + "code": "410422", + "name": "叶县", + "level": "THREE_LEVEL", + "geoname_id": 1786792, + "sub_districts": [] + }, + { + "code": "410411", + "name": "湛河", + "level": "THREE_LEVEL", + "geoname_id": 6602254, + "sub_districts": [] + } + ] + }, + { + "code": "410900", + "name": "濮阳", + "level": "TWO_LEVEL", + "geoname_id": 1941243, + "sub_districts": [ + { + "code": "410926", + "name": "范县", + "level": "THREE_LEVEL", + "geoname_id": 1811471, + "sub_districts": [] + }, + { + "code": "4109020000003", + "name": "华龙", + "level": "THREE_LEVEL", + "geoname_id": 6602266, + "sub_districts": [] + }, + { + "code": "410923", + "name": "南乐", + "level": "THREE_LEVEL", + "geoname_id": 1799927, + "sub_districts": [] + }, + { + "code": "4109280000003", + "name": "濮阳", + "level": "THREE_LEVEL", + "geoname_id": 1798420, + "sub_districts": [] + }, + { + "code": "410922", + "name": "清丰", + "level": "THREE_LEVEL", + "geoname_id": 1797916, + "sub_districts": [] + }, + { + "code": "410927", + "name": "台前", + "level": "THREE_LEVEL", + "geoname_id": 1793556, + "sub_districts": [] + } + ] + }, + { + "code": "411200", + "name": "三门峡", + "level": "TWO_LEVEL", + "geoname_id": 1796669, + "sub_districts": [ + { + "code": "411202", + "name": "湖滨", + "level": "THREE_LEVEL", + "geoname_id": 6602282, + "sub_districts": [] + }, + { + "code": "411282", + "name": "灵宝", + "level": "THREE_LEVEL", + "geoname_id": 1803556, + "sub_districts": [] + }, + { + "code": "411224", + "name": "卢氏", + "level": "THREE_LEVEL", + "geoname_id": 1801729, + "sub_districts": [] + }, + { + "code": "411221", + "name": "渑池", + "level": "THREE_LEVEL", + "geoname_id": 1800646, + "sub_districts": [] + }, + { + "code": "411203", + "name": "陕州", + "level": "THREE_LEVEL", + "geoname_id": 411203, + "sub_districts": [] + }, + { + "code": "411281", + "name": "义马", + "level": "THREE_LEVEL", + "geoname_id": 1786672, + "sub_districts": [] + } + ] + }, + { + "code": "411400", + "name": "商丘", + "level": "TWO_LEVEL", + "geoname_id": 1783934, + "sub_districts": [ + { + "code": "411402", + "name": "梁园", + "level": "THREE_LEVEL", + "geoname_id": 6602259, + "sub_districts": [] + }, + { + "code": "411421", + "name": "民权", + "level": "THREE_LEVEL", + "geoname_id": 1800458, + "sub_districts": [] + }, + { + "code": "411423", + "name": "宁陵", + "level": "THREE_LEVEL", + "geoname_id": 1799365, + "sub_districts": [] + }, + { + "code": "411422", + "name": "睢县", + "level": "THREE_LEVEL", + "geoname_id": 1793888, + "sub_districts": [] + }, + { + "code": "411403", + "name": "睢阳", + "level": "THREE_LEVEL", + "geoname_id": 6602284, + "sub_districts": [] + }, + { + "code": "411426", + "name": "夏邑", + "level": "THREE_LEVEL", + "geoname_id": 1789729, + "sub_districts": [] + }, + { + "code": "411481", + "name": "永城", + "level": "THREE_LEVEL", + "geoname_id": 1786372, + "sub_districts": [] + }, + { + "code": "411425", + "name": "虞城", + "level": "THREE_LEVEL", + "geoname_id": 1785978, + "sub_districts": [] + }, + { + "code": "411424", + "name": "柘城", + "level": "THREE_LEVEL", + "geoname_id": 1784779, + "sub_districts": [] + } + ] + }, + { + "code": "411000", + "name": "许昌", + "level": "TWO_LEVEL", + "geoname_id": 1788045, + "sub_districts": [ + { + "code": "411082", + "name": "长葛", + "level": "THREE_LEVEL", + "geoname_id": 1815737, + "sub_districts": [] + }, + { + "code": "4110030000001", + "name": "建安", + "level": "THREE_LEVEL", + "geoname_id": 1788044, + "sub_districts": [] + }, + { + "code": "411002", + "name": "魏都", + "level": "THREE_LEVEL", + "geoname_id": 6602258, + "sub_districts": [] + }, + { + "code": "411025", + "name": "襄城", + "level": "THREE_LEVEL", + "geoname_id": 1790595, + "sub_districts": [] + }, + { + "code": "411024", + "name": "鄢陵", + "level": "THREE_LEVEL", + "geoname_id": 1787140, + "sub_districts": [] + }, + { + "code": "411081", + "name": "禹州", + "level": "THREE_LEVEL", + "geoname_id": 1785569, + "sub_districts": [] + } + ] + }, + { + "code": "410700", + "name": "新乡", + "level": "TWO_LEVEL", + "geoname_id": 1788571, + "sub_districts": [ + { + "code": "4107830000001", + "name": "长垣", + "level": "THREE_LEVEL", + "geoname_id": 1815474, + "sub_districts": [] + }, + { + "code": "410704", + "name": "凤泉", + "level": "THREE_LEVEL", + "geoname_id": 6602267, + "sub_districts": [] + }, + { + "code": "410727", + "name": "封丘", + "level": "THREE_LEVEL", + "geoname_id": 1811263, + "sub_districts": [] + }, + { + "code": "410724", + "name": "获嘉", + "level": "THREE_LEVEL", + "geoname_id": 1806668, + "sub_districts": [] + }, + { + "code": "410702", + "name": "红旗", + "level": "THREE_LEVEL", + "geoname_id": 6602269, + "sub_districts": [] + }, + { + "code": "410782", + "name": "辉县", + "level": "THREE_LEVEL", + "geoname_id": 1806790, + "sub_districts": [] + }, + { + "code": "410711", + "name": "牧野", + "level": "THREE_LEVEL", + "geoname_id": 6602268, + "sub_districts": [] + }, + { + "code": "410703", + "name": "卫滨", + "level": "THREE_LEVEL", + "geoname_id": 6602270, + "sub_districts": [] + }, + { + "code": "410781", + "name": "卫辉", + "level": "THREE_LEVEL", + "geoname_id": 1805035, + "sub_districts": [] + }, + { + "code": "410721", + "name": "新乡", + "level": "THREE_LEVEL", + "geoname_id": 1788570, + "sub_districts": [] + }, + { + "code": "410726", + "name": "延津", + "level": "THREE_LEVEL", + "geoname_id": 1787156, + "sub_districts": [] + }, + { + "code": "410725", + "name": "原阳", + "level": "THREE_LEVEL", + "geoname_id": 1786014, + "sub_districts": [] + } + ] + }, + { + "code": "411500", + "name": "信阳", + "level": "TWO_LEVEL", + "geoname_id": 1788527, + "sub_districts": [ + { + "code": "411522", + "name": "光山", + "level": "THREE_LEVEL", + "geoname_id": 1809880, + "sub_districts": [] + }, + { + "code": "411525", + "name": "固始", + "level": "THREE_LEVEL", + "geoname_id": 1809216, + "sub_districts": [] + }, + { + "code": "411527", + "name": "淮滨", + "level": "THREE_LEVEL", + "geoname_id": 1807698, + "sub_districts": [] + }, + { + "code": "411526", + "name": "潢川", + "level": "THREE_LEVEL", + "geoname_id": 1807551, + "sub_districts": [] + }, + { + "code": "411521", + "name": "罗山", + "level": "THREE_LEVEL", + "geoname_id": 1801844, + "sub_districts": [] + }, + { + "code": "411503", + "name": "平桥", + "level": "THREE_LEVEL", + "geoname_id": 1788526, + "sub_districts": [] + }, + { + "code": "411524", + "name": "商城", + "level": "THREE_LEVEL", + "geoname_id": 1796295, + "sub_districts": [] + }, + { + "code": "411502", + "name": "浉河", + "level": "THREE_LEVEL", + "geoname_id": 6602256, + "sub_districts": [] + }, + { + "code": "411523", + "name": "新县", + "level": "THREE_LEVEL", + "geoname_id": 1788577, + "sub_districts": [] + }, + { + "code": "411528", + "name": "息县", + "level": "THREE_LEVEL", + "geoname_id": 1788212, + "sub_districts": [] + } + ] + }, + { + "code": "411600", + "name": "周口", + "level": "TWO_LEVEL", + "geoname_id": 1784130, + "sub_districts": [ + { + "code": "411602", + "name": "川汇", + "level": "THREE_LEVEL", + "geoname_id": 6602291, + "sub_districts": [] + }, + { + "code": "411625", + "name": "郸城", + "level": "THREE_LEVEL", + "geoname_id": 1813890, + "sub_districts": [] + }, + { + "code": "411621", + "name": "扶沟", + "level": "THREE_LEVEL", + "geoname_id": 1811040, + "sub_districts": [] + }, + { + "code": "4116030000001", + "name": "淮阳", + "level": "THREE_LEVEL", + "geoname_id": 1807650, + "sub_districts": [] + }, + { + "code": "411628", + "name": "鹿邑", + "level": "THREE_LEVEL", + "geoname_id": 1801658, + "sub_districts": [] + }, + { + "code": "411624", + "name": "沈丘", + "level": "THREE_LEVEL", + "geoname_id": 1795610, + "sub_districts": [] + }, + { + "code": "411623", + "name": "商水", + "level": "THREE_LEVEL", + "geoname_id": 1796109, + "sub_districts": [] + }, + { + "code": "411627", + "name": "太康", + "level": "THREE_LEVEL", + "geoname_id": 1793655, + "sub_districts": [] + }, + { + "code": "411681", + "name": "项城", + "level": "THREE_LEVEL", + "geoname_id": 1790596, + "sub_districts": [] + }, + { + "code": "411622", + "name": "西华", + "level": "THREE_LEVEL", + "geoname_id": 1789419, + "sub_districts": [] + } + ] + }, + { + "code": "411700", + "name": "驻马店", + "level": "TWO_LEVEL", + "geoname_id": 1783873, + "sub_districts": [ + { + "code": "411726", + "name": "泌阳", + "level": "THREE_LEVEL", + "geoname_id": 1816313, + "sub_districts": [] + }, + { + "code": "411723", + "name": "平舆", + "level": "THREE_LEVEL", + "geoname_id": 1798618, + "sub_districts": [] + }, + { + "code": "411725", + "name": "确山", + "level": "THREE_LEVEL", + "geoname_id": 1797335, + "sub_districts": [] + }, + { + "code": "411727", + "name": "汝南", + "level": "THREE_LEVEL", + "geoname_id": 1797036, + "sub_districts": [] + }, + { + "code": "411722", + "name": "上蔡", + "level": "THREE_LEVEL", + "geoname_id": 1796301, + "sub_districts": [] + }, + { + "code": "411728", + "name": "遂平", + "level": "THREE_LEVEL", + "geoname_id": 1793894, + "sub_districts": [] + }, + { + "code": "411729", + "name": "新蔡", + "level": "THREE_LEVEL", + "geoname_id": 1789216, + "sub_districts": [] + }, + { + "code": "411721", + "name": "西平", + "level": "THREE_LEVEL", + "geoname_id": 1788388, + "sub_districts": [] + }, + { + "code": "411702", + "name": "驿城", + "level": "THREE_LEVEL", + "geoname_id": 6602249, + "sub_districts": [] + }, + { + "code": "411724", + "name": "正阳", + "level": "THREE_LEVEL", + "geoname_id": 1784665, + "sub_districts": [] + } + ] + }, + { + "code": "410100", + "name": "郑州", + "level": "TWO_LEVEL", + "geoname_id": 1784658, + "sub_districts": [ + { + "code": "410185", + "name": "登封", + "level": "THREE_LEVEL", + "geoname_id": 1813015, + "sub_districts": [] + }, + { + "code": "410103", + "name": "二七", + "level": "THREE_LEVEL", + "geoname_id": 6602273, + "sub_districts": [] + }, + { + "code": "410104", + "name": "管城", + "level": "THREE_LEVEL", + "geoname_id": 6602274, + "sub_districts": [] + }, + { + "code": "410181", + "name": "巩义", + "level": "THREE_LEVEL", + "geoname_id": 1810078, + "sub_districts": [] + }, + { + "code": "410108", + "name": "惠济", + "level": "THREE_LEVEL", + "geoname_id": 6602276, + "sub_districts": [] + }, + { + "code": "410105", + "name": "金水", + "level": "THREE_LEVEL", + "geoname_id": 6602275, + "sub_districts": [] + }, + { + "code": "410106", + "name": "上街", + "level": "THREE_LEVEL", + "geoname_id": 6602283, + "sub_districts": [] + }, + { + "code": "410183", + "name": "新密", + "level": "THREE_LEVEL", + "geoname_id": 1800434, + "sub_districts": [] + }, + { + "code": "410182", + "name": "荥阳", + "level": "THREE_LEVEL", + "geoname_id": 1788910, + "sub_districts": [] + }, + { + "code": "410184", + "name": "新郑", + "level": "THREE_LEVEL", + "geoname_id": 1788465, + "sub_districts": [] + }, + { + "code": "410122", + "name": "中牟", + "level": "THREE_LEVEL", + "geoname_id": 1784348, + "sub_districts": [] + }, + { + "code": "410102", + "name": "中原", + "level": "THREE_LEVEL", + "geoname_id": 6602289, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "43", + "name": "湖南", + "level": "ONE_LEVEL", + "geoname_id": 1806691, + "sub_districts": [ + { + "code": "430700", + "name": "常德", + "level": "TWO_LEVEL", + "geoname_id": 1791121, + "sub_districts": [ + { + "code": "430721", + "name": "安乡", + "level": "THREE_LEVEL", + "geoname_id": 1817951, + "sub_districts": [] + }, + { + "code": "430703", + "name": "鼎城", + "level": "THREE_LEVEL", + "geoname_id": 6642687, + "sub_districts": [] + }, + { + "code": "430722", + "name": "汉寿", + "level": "THREE_LEVEL", + "geoname_id": 1808887, + "sub_districts": [] + }, + { + "code": "430781", + "name": "津市", + "level": "THREE_LEVEL", + "geoname_id": 1805374, + "sub_districts": [] + }, + { + "code": "430724", + "name": "临澧", + "level": "THREE_LEVEL", + "geoname_id": 1803381, + "sub_districts": [] + }, + { + "code": "430723", + "name": "澧县", + "level": "THREE_LEVEL", + "geoname_id": 1802817, + "sub_districts": [] + }, + { + "code": "430726", + "name": "石门", + "level": "THREE_LEVEL", + "geoname_id": 1795106, + "sub_districts": [] + }, + { + "code": "430725", + "name": "桃源", + "level": "THREE_LEVEL", + "geoname_id": 1793095, + "sub_districts": [] + }, + { + "code": "430702", + "name": "武陵", + "level": "THREE_LEVEL", + "geoname_id": 6642678, + "sub_districts": [] + } + ] + }, + { + "code": "430100", + "name": "长沙", + "level": "TWO_LEVEL", + "geoname_id": 1815577, + "sub_districts": [ + { + "code": "430121", + "name": "长沙", + "level": "THREE_LEVEL", + "geoname_id": 1815550, + "sub_districts": [] + }, + { + "code": "430102", + "name": "芙蓉", + "level": "THREE_LEVEL", + "geoname_id": 6642850, + "sub_districts": [] + }, + { + "code": "430105", + "name": "开福", + "level": "THREE_LEVEL", + "geoname_id": 6642603, + "sub_districts": [] + }, + { + "code": "430181", + "name": "浏阳", + "level": "THREE_LEVEL", + "geoname_id": 1802872, + "sub_districts": [] + }, + { + "code": "4301820000001", + "name": "宁乡", + "level": "THREE_LEVEL", + "geoname_id": 1799351, + "sub_districts": [] + }, + { + "code": "430103", + "name": "天心", + "level": "THREE_LEVEL", + "geoname_id": 6642599, + "sub_districts": [] + }, + { + "code": "430112", + "name": "望城", + "level": "THREE_LEVEL", + "geoname_id": 1792154, + "sub_districts": [] + }, + { + "code": "430111", + "name": "雨花", + "level": "THREE_LEVEL", + "geoname_id": 6642606, + "sub_districts": [] + }, + { + "code": "430104", + "name": "岳麓", + "level": "THREE_LEVEL", + "geoname_id": 6642849, + "sub_districts": [] + } + ] + }, + { + "code": "431000", + "name": "郴州", + "level": "TWO_LEVEL", + "geoname_id": 1815056, + "sub_districts": [ + { + "code": "431028", + "name": "安仁", + "level": "THREE_LEVEL", + "geoname_id": 1817978, + "sub_districts": [] + }, + { + "code": "431002", + "name": "北湖", + "level": "THREE_LEVEL", + "geoname_id": 6642729, + "sub_districts": [] + }, + { + "code": "431027", + "name": "桂东", + "level": "THREE_LEVEL", + "geoname_id": 1809520, + "sub_districts": [] + }, + { + "code": "431021", + "name": "桂阳", + "level": "THREE_LEVEL", + "geoname_id": 1809457, + "sub_districts": [] + }, + { + "code": "431024", + "name": "嘉禾", + "level": "THREE_LEVEL", + "geoname_id": 1806493, + "sub_districts": [] + }, + { + "code": "431025", + "name": "临武", + "level": "THREE_LEVEL", + "geoname_id": 1803338, + "sub_districts": [] + }, + { + "code": "431026", + "name": "汝城", + "level": "THREE_LEVEL", + "geoname_id": 1797075, + "sub_districts": [] + }, + { + "code": "431003", + "name": "苏仙", + "level": "THREE_LEVEL", + "geoname_id": 6642730, + "sub_districts": [] + }, + { + "code": "431023", + "name": "永兴", + "level": "THREE_LEVEL", + "geoname_id": 1786225, + "sub_districts": [] + }, + { + "code": "431022", + "name": "宜章", + "level": "THREE_LEVEL", + "geoname_id": 1786411, + "sub_districts": [] + }, + { + "code": "431081", + "name": "资兴", + "level": "THREE_LEVEL", + "geoname_id": 1783687, + "sub_districts": [] + } + ] + }, + { + "code": "431200", + "name": "怀化", + "level": "TWO_LEVEL", + "geoname_id": 1807689, + "sub_districts": [ + { + "code": "431223", + "name": "辰溪", + "level": "THREE_LEVEL", + "geoname_id": 1815070, + "sub_districts": [] + }, + { + "code": "431202", + "name": "鹤城", + "level": "THREE_LEVEL", + "geoname_id": 6642853, + "sub_districts": [] + }, + { + "code": "431281", + "name": "洪江", + "level": "THREE_LEVEL", + "geoname_id": 1808102, + "sub_districts": [] + }, + { + "code": "431225", + "name": "会同", + "level": "THREE_LEVEL", + "geoname_id": 1806796, + "sub_districts": [] + }, + { + "code": "431229", + "name": "靖州", + "level": "THREE_LEVEL", + "geoname_id": 1928653, + "sub_districts": [] + }, + { + "code": "431226", + "name": "麻阳", + "level": "THREE_LEVEL", + "geoname_id": 1800946, + "sub_districts": [] + }, + { + "code": "431230", + "name": "通道", + "level": "THREE_LEVEL", + "geoname_id": 1792689, + "sub_districts": [] + }, + { + "code": "431227", + "name": "新晃", + "level": "THREE_LEVEL", + "geoname_id": 1788861, + "sub_districts": [] + }, + { + "code": "431224", + "name": "溆浦", + "level": "THREE_LEVEL", + "geoname_id": 1787860, + "sub_districts": [] + }, + { + "code": "431222", + "name": "沅陵", + "level": "THREE_LEVEL", + "geoname_id": 1786065, + "sub_districts": [] + }, + { + "code": "431221", + "name": "中方", + "level": "THREE_LEVEL", + "geoname_id": 1928654, + "sub_districts": [] + }, + { + "code": "431228", + "name": "芷江", + "level": "THREE_LEVEL", + "geoname_id": 1784524, + "sub_districts": [] + } + ] + }, + { + "code": "430400", + "name": "衡阳", + "level": "TWO_LEVEL", + "geoname_id": 1808370, + "sub_districts": [ + { + "code": "430482", + "name": "常宁", + "level": "THREE_LEVEL", + "geoname_id": 1815608, + "sub_districts": [] + }, + { + "code": "430424", + "name": "衡东", + "level": "THREE_LEVEL", + "geoname_id": 1808500, + "sub_districts": [] + }, + { + "code": "430422", + "name": "衡南", + "level": "THREE_LEVEL", + "geoname_id": 1808436, + "sub_districts": [] + }, + { + "code": "430423", + "name": "衡山", + "level": "THREE_LEVEL", + "geoname_id": 1808408, + "sub_districts": [] + }, + { + "code": "430421", + "name": "衡阳", + "level": "THREE_LEVEL", + "geoname_id": 1808368, + "sub_districts": [] + }, + { + "code": "430481", + "name": "耒阳", + "level": "THREE_LEVEL", + "geoname_id": 1804207, + "sub_districts": [] + }, + { + "code": "430412", + "name": "南岳", + "level": "THREE_LEVEL", + "geoname_id": 6642728, + "sub_districts": [] + }, + { + "code": "430426", + "name": "祁东", + "level": "THREE_LEVEL", + "geoname_id": 1798080, + "sub_districts": [] + }, + { + "code": "430407", + "name": "石鼓", + "level": "THREE_LEVEL", + "geoname_id": 6642726, + "sub_districts": [] + }, + { + "code": "430406", + "name": "雁峰", + "level": "THREE_LEVEL", + "geoname_id": 6642725, + "sub_districts": [] + }, + { + "code": "430405", + "name": "珠晖", + "level": "THREE_LEVEL", + "geoname_id": 6642852, + "sub_districts": [] + }, + { + "code": "430408", + "name": "蒸湘", + "level": "THREE_LEVEL", + "geoname_id": 6642727, + "sub_districts": [] + } + ] + }, + { + "code": "431300", + "name": "娄底", + "level": "TWO_LEVEL", + "geoname_id": 1802238, + "sub_districts": [ + { + "code": "431381", + "name": "冷水江", + "level": "THREE_LEVEL", + "geoname_id": 1804168, + "sub_districts": [] + }, + { + "code": "431302", + "name": "娄星", + "level": "THREE_LEVEL", + "geoname_id": 6642856, + "sub_districts": [] + }, + { + "code": "431382", + "name": "涟源", + "level": "THREE_LEVEL", + "geoname_id": 1803850, + "sub_districts": [] + }, + { + "code": "431321", + "name": "双峰", + "level": "THREE_LEVEL", + "geoname_id": 1794742, + "sub_districts": [] + }, + { + "code": "431322", + "name": "新化", + "level": "THREE_LEVEL", + "geoname_id": 1788859, + "sub_districts": [] + } + ] + }, + { + "code": "430500", + "name": "邵阳", + "level": "TWO_LEVEL", + "geoname_id": 1795852, + "sub_districts": [ + { + "code": "430511", + "name": "北塔", + "level": "THREE_LEVEL", + "geoname_id": 6642733, + "sub_districts": [] + }, + { + "code": "430529", + "name": "城步", + "level": "THREE_LEVEL", + "geoname_id": 1815304, + "sub_districts": [] + }, + { + "code": "430525", + "name": "洞口", + "level": "THREE_LEVEL", + "geoname_id": 1812416, + "sub_districts": [] + }, + { + "code": "430503", + "name": "大祥", + "level": "THREE_LEVEL", + "geoname_id": 6642732, + "sub_districts": [] + }, + { + "code": "430524", + "name": "隆回", + "level": "THREE_LEVEL", + "geoname_id": 1802604, + "sub_districts": [] + }, + { + "code": "4305820000001", + "name": "邵东", + "level": "THREE_LEVEL", + "geoname_id": 1795879, + "sub_districts": [] + }, + { + "code": "430527", + "name": "绥宁", + "level": "THREE_LEVEL", + "geoname_id": 1793897, + "sub_districts": [] + }, + { + "code": "430502", + "name": "双清", + "level": "THREE_LEVEL", + "geoname_id": 6642731, + "sub_districts": [] + }, + { + "code": "430523", + "name": "邵阳", + "level": "THREE_LEVEL", + "geoname_id": 1795851, + "sub_districts": [] + }, + { + "code": "430581", + "name": "武冈", + "level": "THREE_LEVEL", + "geoname_id": 1791269, + "sub_districts": [] + }, + { + "code": "430528", + "name": "新宁", + "level": "THREE_LEVEL", + "geoname_id": 1788706, + "sub_districts": [] + }, + { + "code": "430522", + "name": "新邵", + "level": "THREE_LEVEL", + "geoname_id": 1788649, + "sub_districts": [] + } + ] + }, + { + "code": "430300", + "name": "湘潭", + "level": "TWO_LEVEL", + "geoname_id": 1790484, + "sub_districts": [ + { + "code": "430382", + "name": "韶山", + "level": "THREE_LEVEL", + "geoname_id": 1795860, + "sub_districts": [] + }, + { + "code": "430321", + "name": "湘潭", + "level": "THREE_LEVEL", + "geoname_id": 1790483, + "sub_districts": [] + }, + { + "code": "430381", + "name": "湘乡", + "level": "THREE_LEVEL", + "geoname_id": 1790470, + "sub_districts": [] + }, + { + "code": "4303020000003", + "name": "雨湖", + "level": "THREE_LEVEL", + "geoname_id": 6642711, + "sub_districts": [] + }, + { + "code": "4303040000003", + "name": "岳塘", + "level": "THREE_LEVEL", + "geoname_id": 6642724, + "sub_districts": [] + } + ] + }, + { + "code": "433100", + "name": "湘西", + "level": "TWO_LEVEL", + "geoname_id": 1790468, + "sub_districts": [ + { + "code": "433125", + "name": "保靖", + "level": "THREE_LEVEL", + "geoname_id": 1816937, + "sub_districts": [] + }, + { + "code": "433123", + "name": "凤凰", + "level": "THREE_LEVEL", + "geoname_id": 1811336, + "sub_districts": [] + }, + { + "code": "433126", + "name": "古丈", + "level": "THREE_LEVEL", + "geoname_id": 1809141, + "sub_districts": [] + }, + { + "code": "433124", + "name": "花垣", + "level": "THREE_LEVEL", + "geoname_id": 1806969, + "sub_districts": [] + }, + { + "code": "433101", + "name": "吉首", + "level": "THREE_LEVEL", + "geoname_id": 1805269, + "sub_districts": [] + }, + { + "code": "433130", + "name": "龙山", + "level": "THREE_LEVEL", + "geoname_id": 7007063, + "sub_districts": [] + }, + { + "code": "433122", + "name": "泸溪", + "level": "THREE_LEVEL", + "geoname_id": 1801676, + "sub_districts": [] + }, + { + "code": "433127", + "name": "永顺", + "level": "THREE_LEVEL", + "geoname_id": 1786261, + "sub_districts": [] + } + ] + }, + { + "code": "430600", + "name": "岳阳", + "level": "TWO_LEVEL", + "geoname_id": 1785881, + "sub_districts": [ + { + "code": "430623", + "name": "华容", + "level": "THREE_LEVEL", + "geoname_id": 1807039, + "sub_districts": [] + }, + { + "code": "430611", + "name": "君山", + "level": "THREE_LEVEL", + "geoname_id": 6642692, + "sub_districts": [] + }, + { + "code": "430682", + "name": "临湘", + "level": "THREE_LEVEL", + "geoname_id": 1803324, + "sub_districts": [] + }, + { + "code": "430681", + "name": "汨罗", + "level": "THREE_LEVEL", + "geoname_id": 1800529, + "sub_districts": [] + }, + { + "code": "430626", + "name": "平江", + "level": "THREE_LEVEL", + "geoname_id": 1798781, + "sub_districts": [] + }, + { + "code": "430624", + "name": "湘阴", + "level": "THREE_LEVEL", + "geoname_id": 1790450, + "sub_districts": [] + }, + { + "code": "430603", + "name": "云溪", + "level": "THREE_LEVEL", + "geoname_id": 6642700, + "sub_districts": [] + }, + { + "code": "430602", + "name": "岳阳楼", + "level": "THREE_LEVEL", + "geoname_id": 6642690, + "sub_districts": [] + }, + { + "code": "430621", + "name": "岳阳", + "level": "THREE_LEVEL", + "geoname_id": 1785880, + "sub_districts": [] + } + ] + }, + { + "code": "430900", + "name": "益阳", + "level": "TWO_LEVEL", + "geoname_id": 1786419, + "sub_districts": [ + { + "code": "430923", + "name": "安化", + "level": "THREE_LEVEL", + "geoname_id": 1818059, + "sub_districts": [] + }, + { + "code": "430903", + "name": "赫山", + "level": "THREE_LEVEL", + "geoname_id": 6642688, + "sub_districts": [] + }, + { + "code": "430921", + "name": "南县", + "level": "THREE_LEVEL", + "geoname_id": 1799678, + "sub_districts": [] + }, + { + "code": "430922", + "name": "桃江", + "level": "THREE_LEVEL", + "geoname_id": 1793154, + "sub_districts": [] + }, + { + "code": "430981", + "name": "沅江", + "level": "THREE_LEVEL", + "geoname_id": 1786080, + "sub_districts": [] + }, + { + "code": "430902", + "name": "资阳", + "level": "THREE_LEVEL", + "geoname_id": 1786416, + "sub_districts": [] + } + ] + }, + { + "code": "431100", + "name": "永州", + "level": "TWO_LEVEL", + "geoname_id": 1786217, + "sub_districts": [ + { + "code": "431122", + "name": "东安", + "level": "THREE_LEVEL", + "geoname_id": 1812684, + "sub_districts": [] + }, + { + "code": "431124", + "name": "道县", + "level": "THREE_LEVEL", + "geoname_id": 1813747, + "sub_districts": [] + }, + { + "code": "431129", + "name": "江华", + "level": "THREE_LEVEL", + "geoname_id": 1806373, + "sub_districts": [] + }, + { + "code": "431125", + "name": "江永", + "level": "THREE_LEVEL", + "geoname_id": 1806208, + "sub_districts": [] + }, + { + "code": "431102", + "name": "零陵", + "level": "THREE_LEVEL", + "geoname_id": 1803495, + "sub_districts": [] + }, + { + "code": "431103", + "name": "冷水滩", + "level": "THREE_LEVEL", + "geoname_id": 1804161, + "sub_districts": [] + }, + { + "code": "431127", + "name": "蓝山", + "level": "THREE_LEVEL", + "geoname_id": 1804460, + "sub_districts": [] + }, + { + "code": "431126", + "name": "宁远", + "level": "THREE_LEVEL", + "geoname_id": 1799344, + "sub_districts": [] + }, + { + "code": "4311810000001", + "name": "祁阳", + "level": "THREE_LEVEL", + "geoname_id": 1797416, + "sub_districts": [] + }, + { + "code": "431123", + "name": "双牌", + "level": "THREE_LEVEL", + "geoname_id": 1794622, + "sub_districts": [] + }, + { + "code": "431128", + "name": "新田", + "level": "THREE_LEVEL", + "geoname_id": 1788592, + "sub_districts": [] + } + ] + }, + { + "code": "430800", + "name": "张家界", + "level": "TWO_LEVEL", + "geoname_id": 1813171, + "sub_districts": [ + { + "code": "430821", + "name": "慈利", + "level": "THREE_LEVEL", + "geoname_id": 1814734, + "sub_districts": [] + }, + { + "code": "430822", + "name": "桑植", + "level": "THREE_LEVEL", + "geoname_id": 1796840, + "sub_districts": [] + }, + { + "code": "430811", + "name": "武陵源", + "level": "THREE_LEVEL", + "geoname_id": 6642676, + "sub_districts": [] + }, + { + "code": "430802", + "name": "永定", + "level": "THREE_LEVEL", + "geoname_id": 6642611, + "sub_districts": [] + } + ] + }, + { + "code": "430200", + "name": "株洲", + "level": "TWO_LEVEL", + "geoname_id": 1783763, + "sub_districts": [ + { + "code": "430224", + "name": "茶陵", + "level": "THREE_LEVEL", + "geoname_id": 1815818, + "sub_districts": [] + }, + { + "code": "430202", + "name": "荷塘", + "level": "THREE_LEVEL", + "geoname_id": 6642851, + "sub_districts": [] + }, + { + "code": "4302120000001", + "name": "渌口", + "level": "THREE_LEVEL", + "geoname_id": 1802040, + "sub_districts": [] + }, + { + "code": "430281", + "name": "醴陵", + "level": "THREE_LEVEL", + "geoname_id": 1803615, + "sub_districts": [] + }, + { + "code": "430203", + "name": "芦淞", + "level": "THREE_LEVEL", + "geoname_id": 6642707, + "sub_districts": [] + }, + { + "code": "430204", + "name": "石峰", + "level": "THREE_LEVEL", + "geoname_id": 6642710, + "sub_districts": [] + }, + { + "code": "430211", + "name": "天元", + "level": "THREE_LEVEL", + "geoname_id": 6642702, + "sub_districts": [] + }, + { + "code": "430225", + "name": "炎陵", + "level": "THREE_LEVEL", + "geoname_id": 1803440, + "sub_districts": [] + }, + { + "code": "430223", + "name": "攸县", + "level": "THREE_LEVEL", + "geoname_id": 1786142, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "46", + "name": "海南", + "level": "ONE_LEVEL", + "geoname_id": 1809054, + "sub_districts": [ + { + "code": "469025", + "name": "白沙", + "level": "TWO_LEVEL", + "geoname_id": 1817425, + "sub_districts": [ + { + "code": "469025", + "name": "白沙", + "level": "THREE_LEVEL", + "geoname_id": 1787808, + "sub_districts": [] + } + ] + }, + { + "code": "469029", + "name": "保亭", + "level": "TWO_LEVEL", + "geoname_id": 1816903, + "sub_districts": [ + { + "code": "469029", + "name": "保亭", + "level": "THREE_LEVEL", + "geoname_id": 1816904, + "sub_districts": [] + } + ] + }, + { + "code": "469026", + "name": "昌江", + "level": "TWO_LEVEL", + "geoname_id": 1815692, + "sub_districts": [ + { + "code": "469026", + "name": "昌江", + "level": "THREE_LEVEL", + "geoname_id": 1795192, + "sub_districts": [] + } + ] + }, + { + "code": "469023", + "name": "澄迈", + "level": "TWO_LEVEL", + "geoname_id": 1805505, + "sub_districts": [ + { + "code": "469023", + "name": "澄迈", + "level": "THREE_LEVEL", + "geoname_id": 1815226, + "sub_districts": [] + } + ] + }, + { + "code": "469021", + "name": "定安", + "level": "TWO_LEVEL", + "geoname_id": 1812824, + "sub_districts": [ + { + "code": "469021", + "name": "定安", + "level": "THREE_LEVEL", + "geoname_id": 1812826, + "sub_districts": [] + } + ] + }, + { + "code": "469007", + "name": "东方", + "level": "TWO_LEVEL", + "geoname_id": 1812589, + "sub_districts": [ + { + "code": "469007", + "name": "东方", + "level": "THREE_LEVEL", + "geoname_id": 1816858, + "sub_districts": [] + } + ] + }, + { + "code": "460400", + "name": "儋州", + "level": "TWO_LEVEL", + "geoname_id": 1813805, + "sub_districts": [ + { + "code": "460400", + "name": "儋州", + "level": "THREE_LEVEL", + "geoname_id": 1800234, + "sub_districts": [] + } + ] + }, + { + "code": "460100", + "name": "海口", + "level": "TWO_LEVEL", + "geoname_id": 1809078, + "sub_districts": [ + { + "code": "460106", + "name": "龙华", + "level": "THREE_LEVEL", + "geoname_id": 6282940, + "sub_districts": [] + }, + { + "code": "460108", + "name": "美兰", + "level": "THREE_LEVEL", + "geoname_id": 6282939, + "sub_districts": [] + }, + { + "code": "460107", + "name": "琼山", + "level": "THREE_LEVEL", + "geoname_id": 1797538, + "sub_districts": [] + }, + { + "code": "460105", + "name": "秀英", + "level": "THREE_LEVEL", + "geoname_id": 6282941, + "sub_districts": [] + } + ] + }, + { + "code": "469027", + "name": "乐东", + "level": "TWO_LEVEL", + "geoname_id": 1804250, + "sub_districts": [ + { + "code": "469027", + "name": "乐东", + "level": "THREE_LEVEL", + "geoname_id": 1816887, + "sub_districts": [] + } + ] + }, + { + "code": "469024", + "name": "临高", + "level": "TWO_LEVEL", + "geoname_id": 1803557, + "sub_districts": [ + { + "code": "469024", + "name": "临高", + "level": "THREE_LEVEL", + "geoname_id": 1803560, + "sub_districts": [] + } + ] + }, + { + "code": "469028", + "name": "陵水", + "level": "TWO_LEVEL", + "geoname_id": 1803461, + "sub_districts": [ + { + "code": "469028", + "name": "陵水", + "level": "THREE_LEVEL", + "geoname_id": 7635189, + "sub_districts": [] + } + ] + }, + { + "code": "469002", + "name": "琼海", + "level": "TWO_LEVEL", + "geoname_id": 1806488, + "sub_districts": [ + { + "code": "469002", + "name": "琼海", + "level": "THREE_LEVEL", + "geoname_id": 1797544, + "sub_districts": [] + } + ] + }, + { + "code": "469030", + "name": "琼中", + "level": "TWO_LEVEL", + "geoname_id": 1797536, + "sub_districts": [ + { + "code": "469030", + "name": "琼中", + "level": "THREE_LEVEL", + "geoname_id": 1786620, + "sub_districts": [] + } + ] + }, + { + "code": "460300", + "name": "三沙", + "level": "TWO_LEVEL", + "geoname_id": 8402317, + "sub_districts": [ + { + "code": "4603020009001", + "name": "南沙", + "level": "THREE_LEVEL", + "geoname_id": 460322, + "sub_districts": [] + }, + { + "code": "4603010009001", + "name": "西沙", + "level": "THREE_LEVEL", + "geoname_id": 460321, + "sub_districts": [] + } + ] + }, + { + "code": "460200", + "name": "三亚", + "level": "TWO_LEVEL", + "geoname_id": 1796539, + "sub_districts": [ + { + "code": "460202", + "name": "海棠", + "level": "THREE_LEVEL", + "geoname_id": 7632521, + "sub_districts": [] + }, + { + "code": "460203", + "name": "吉阳", + "level": "THREE_LEVEL", + "geoname_id": 460203, + "sub_districts": [] + }, + { + "code": "460204", + "name": "天涯", + "level": "THREE_LEVEL", + "geoname_id": 1801350, + "sub_districts": [] + }, + { + "code": "460205", + "name": "崖州", + "level": "THREE_LEVEL", + "geoname_id": 460205, + "sub_districts": [] + } + ] + }, + { + "code": "469022", + "name": "屯昌", + "level": "TWO_LEVEL", + "geoname_id": 1792374, + "sub_districts": [ + { + "code": "469022", + "name": "屯昌", + "level": "THREE_LEVEL", + "geoname_id": 8536151, + "sub_districts": [] + } + ] + }, + { + "code": "469005", + "name": "文昌", + "level": "TWO_LEVEL", + "geoname_id": 1791540, + "sub_districts": [ + { + "code": "469005", + "name": "文昌", + "level": "THREE_LEVEL", + "geoname_id": 1791544, + "sub_districts": [] + } + ] + }, + { + "code": "469006", + "name": "万宁", + "level": "TWO_LEVEL", + "geoname_id": 1791778, + "sub_districts": [ + { + "code": "469006", + "name": "万宁", + "level": "THREE_LEVEL", + "geoname_id": 1791779, + "sub_districts": [] + } + ] + }, + { + "code": "469001", + "name": "五指山", + "level": "TWO_LEVEL", + "geoname_id": 1792571, + "sub_districts": [ + { + "code": "469001", + "name": "五指山", + "level": "THREE_LEVEL", + "geoname_id": 1916012, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "22", + "name": "吉林", + "level": "ONE_LEVEL", + "geoname_id": 2036500, + "sub_districts": [ + { + "code": "220800", + "name": "白城", + "level": "TWO_LEVEL", + "geoname_id": 2038569, + "sub_districts": [ + { + "code": "220882", + "name": "大安", + "level": "THREE_LEVEL", + "geoname_id": 2038032, + "sub_districts": [] + }, + { + "code": "220802", + "name": "洮北", + "level": "THREE_LEVEL", + "geoname_id": 6587791, + "sub_districts": [] + }, + { + "code": "220881", + "name": "洮南", + "level": "THREE_LEVEL", + "geoname_id": 2034497, + "sub_districts": [] + }, + { + "code": "220822", + "name": "通榆", + "level": "THREE_LEVEL", + "geoname_id": 2034392, + "sub_districts": [] + }, + { + "code": "220821", + "name": "镇赉", + "level": "THREE_LEVEL", + "geoname_id": 2033127, + "sub_districts": [] + } + ] + }, + { + "code": "220600", + "name": "白山", + "level": "TWO_LEVEL", + "geoname_id": 2036646, + "sub_districts": [ + { + "code": "220623", + "name": "长白", + "level": "THREE_LEVEL", + "geoname_id": 2038184, + "sub_districts": [] + }, + { + "code": "220621", + "name": "抚松", + "level": "THREE_LEVEL", + "geoname_id": 2037350, + "sub_districts": [] + }, + { + "code": "220602", + "name": "浑江", + "level": "THREE_LEVEL", + "geoname_id": 6587810, + "sub_districts": [] + }, + { + "code": "220605", + "name": "江源", + "level": "THREE_LEVEL", + "geoname_id": 2053059, + "sub_districts": [] + }, + { + "code": "220622", + "name": "靖宇", + "level": "THREE_LEVEL", + "geoname_id": 2036461, + "sub_districts": [] + }, + { + "code": "220681", + "name": "临江", + "level": "THREE_LEVEL", + "geoname_id": 6587809, + "sub_districts": [] + } + ] + }, + { + "code": "220100", + "name": "长春", + "level": "TWO_LEVEL", + "geoname_id": 2038180, + "sub_districts": [ + { + "code": "220104", + "name": "朝阳", + "level": "THREE_LEVEL", + "geoname_id": 6587793, + "sub_districts": [] + }, + { + "code": "220183", + "name": "德惠", + "level": "THREE_LEVEL", + "geoname_id": 2037711, + "sub_districts": [] + }, + { + "code": "220105", + "name": "二道", + "level": "THREE_LEVEL", + "geoname_id": 6587796, + "sub_districts": [] + }, + { + "code": "2201840000001", + "name": "公主岭", + "level": "THREE_LEVEL", + "geoname_id": 2037221, + "sub_districts": [] + }, + { + "code": "220113", + "name": "九台", + "level": "THREE_LEVEL", + "geoname_id": 2036400, + "sub_districts": [] + }, + { + "code": "220103", + "name": "宽城", + "level": "THREE_LEVEL", + "geoname_id": 6587795, + "sub_districts": [] + }, + { + "code": "220106", + "name": "绿园", + "level": "THREE_LEVEL", + "geoname_id": 6587797, + "sub_districts": [] + }, + { + "code": "220122", + "name": "农安", + "level": "THREE_LEVEL", + "geoname_id": 2035564, + "sub_districts": [] + }, + { + "code": "220102", + "name": "南关", + "level": "THREE_LEVEL", + "geoname_id": 6587794, + "sub_districts": [] + }, + { + "code": "220112", + "name": "双阳", + "level": "THREE_LEVEL", + "geoname_id": 2034787, + "sub_districts": [] + }, + { + "code": "220182", + "name": "榆树", + "level": "THREE_LEVEL", + "geoname_id": 2033230, + "sub_districts": [] + } + ] + }, + { + "code": "220200", + "name": "吉林", + "level": "TWO_LEVEL", + "geoname_id": 2036502, + "sub_districts": [ + { + "code": "220202", + "name": "昌邑", + "level": "THREE_LEVEL", + "geoname_id": 6587800, + "sub_districts": [] + }, + { + "code": "220204", + "name": "船营", + "level": "THREE_LEVEL", + "geoname_id": 6587801, + "sub_districts": [] + }, + { + "code": "220211", + "name": "丰满", + "level": "THREE_LEVEL", + "geoname_id": 6587802, + "sub_districts": [] + }, + { + "code": "220282", + "name": "桦甸", + "level": "THREE_LEVEL", + "geoname_id": 2036775, + "sub_districts": [] + }, + { + "code": "220281", + "name": "蛟河", + "level": "THREE_LEVEL", + "geoname_id": 2036534, + "sub_districts": [] + }, + { + "code": "220203", + "name": "龙潭", + "level": "THREE_LEVEL", + "geoname_id": 6587799, + "sub_districts": [] + }, + { + "code": "220284", + "name": "磐石", + "level": "THREE_LEVEL", + "geoname_id": 2035510, + "sub_districts": [] + }, + { + "code": "220283", + "name": "舒兰", + "level": "THREE_LEVEL", + "geoname_id": 2034760, + "sub_districts": [] + }, + { + "code": "220221", + "name": "永吉", + "level": "THREE_LEVEL", + "geoname_id": 2033317, + "sub_districts": [] + } + ] + }, + { + "code": "220400", + "name": "辽源", + "level": "TWO_LEVEL", + "geoname_id": 2036107, + "sub_districts": [ + { + "code": "220421", + "name": "东丰", + "level": "THREE_LEVEL", + "geoname_id": 2037651, + "sub_districts": [] + }, + { + "code": "220422", + "name": "东辽", + "level": "THREE_LEVEL", + "geoname_id": 2037621, + "sub_districts": [] + }, + { + "code": "220402", + "name": "龙山", + "level": "THREE_LEVEL", + "geoname_id": 6587806, + "sub_districts": [] + }, + { + "code": "220403", + "name": "西安", + "level": "THREE_LEVEL", + "geoname_id": 6587805, + "sub_districts": [] + } + ] + }, + { + "code": "220300", + "name": "四平", + "level": "TWO_LEVEL", + "geoname_id": 2034711, + "sub_districts": [ + { + "code": "220322", + "name": "梨树", + "level": "THREE_LEVEL", + "geoname_id": 2036051, + "sub_districts": [] + }, + { + "code": "220382", + "name": "双辽", + "level": "THREE_LEVEL", + "geoname_id": 2034813, + "sub_districts": [] + }, + { + "code": "220303", + "name": "铁东", + "level": "THREE_LEVEL", + "geoname_id": 6587803, + "sub_districts": [] + }, + { + "code": "220302", + "name": "铁西", + "level": "THREE_LEVEL", + "geoname_id": 6587804, + "sub_districts": [] + }, + { + "code": "220323", + "name": "伊通", + "level": "THREE_LEVEL", + "geoname_id": 2033343, + "sub_districts": [] + } + ] + }, + { + "code": "220700", + "name": "松原", + "level": "TWO_LEVEL", + "geoname_id": 6587798, + "sub_districts": [ + { + "code": "220722", + "name": "长岭", + "level": "THREE_LEVEL", + "geoname_id": 2038157, + "sub_districts": [] + }, + { + "code": "220781", + "name": "扶余", + "level": "THREE_LEVEL", + "geoname_id": 2037328, + "sub_districts": [] + }, + { + "code": "220702", + "name": "宁江", + "level": "THREE_LEVEL", + "geoname_id": 6587792, + "sub_districts": [] + }, + { + "code": "220723", + "name": "乾安", + "level": "THREE_LEVEL", + "geoname_id": 2035408, + "sub_districts": [] + }, + { + "code": "220721", + "name": "前郭尔罗斯", + "level": "THREE_LEVEL", + "geoname_id": 2035401, + "sub_districts": [] + } + ] + }, + { + "code": "220500", + "name": "通化", + "level": "TWO_LEVEL", + "geoname_id": 2034414, + "sub_districts": [ + { + "code": "220502", + "name": "东昌", + "level": "THREE_LEVEL", + "geoname_id": 6587807, + "sub_districts": [] + }, + { + "code": "220503", + "name": "二道江", + "level": "THREE_LEVEL", + "geoname_id": 6587808, + "sub_districts": [] + }, + { + "code": "220523", + "name": "辉南", + "level": "THREE_LEVEL", + "geoname_id": 2036684, + "sub_districts": [] + }, + { + "code": "220582", + "name": "集安", + "level": "THREE_LEVEL", + "geoname_id": 2036579, + "sub_districts": [] + }, + { + "code": "220524", + "name": "柳河", + "level": "THREE_LEVEL", + "geoname_id": 2036023, + "sub_districts": [] + }, + { + "code": "220581", + "name": "梅河口", + "level": "THREE_LEVEL", + "geoname_id": 2035800, + "sub_districts": [] + }, + { + "code": "220521", + "name": "通化", + "level": "THREE_LEVEL", + "geoname_id": 2034412, + "sub_districts": [] + } + ] + }, + { + "code": "222400", + "name": "延边", + "level": "TWO_LEVEL", + "geoname_id": 2033525, + "sub_districts": [ + { + "code": "222426", + "name": "安图", + "level": "THREE_LEVEL", + "geoname_id": 2038627, + "sub_districts": [] + }, + { + "code": "222403", + "name": "敦化", + "level": "THREE_LEVEL", + "geoname_id": 2037533, + "sub_districts": [] + }, + { + "code": "222404", + "name": "珲春", + "level": "THREE_LEVEL", + "geoname_id": 2036651, + "sub_districts": [] + }, + { + "code": "222406", + "name": "和龙", + "level": "THREE_LEVEL", + "geoname_id": 2036931, + "sub_districts": [] + }, + { + "code": "222405", + "name": "龙井", + "level": "THREE_LEVEL", + "geoname_id": 2035964, + "sub_districts": [] + }, + { + "code": "222402", + "name": "图们", + "level": "THREE_LEVEL", + "geoname_id": 2034337, + "sub_districts": [] + }, + { + "code": "222424", + "name": "汪清", + "level": "THREE_LEVEL", + "geoname_id": 2034219, + "sub_districts": [] + }, + { + "code": "222401", + "name": "延吉", + "level": "THREE_LEVEL", + "geoname_id": 2033460, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "32", + "name": "江苏", + "level": "ONE_LEVEL", + "geoname_id": 1806260, + "sub_districts": [ + { + "code": "320400", + "name": "常州", + "level": "TWO_LEVEL", + "geoname_id": 1815456, + "sub_districts": [ + { + "code": "320413", + "name": "金坛", + "level": "THREE_LEVEL", + "geoname_id": 1805351, + "sub_districts": [] + }, + { + "code": "320481", + "name": "溧阳", + "level": "THREE_LEVEL", + "geoname_id": 1802788, + "sub_districts": [] + }, + { + "code": "320402", + "name": "天宁", + "level": "THREE_LEVEL", + "geoname_id": 6567653, + "sub_districts": [] + }, + { + "code": "320412", + "name": "武进", + "level": "THREE_LEVEL", + "geoname_id": 1791159, + "sub_districts": [] + }, + { + "code": "320411", + "name": "新北", + "level": "THREE_LEVEL", + "geoname_id": 6567655, + "sub_districts": [] + }, + { + "code": "320404", + "name": "钟楼", + "level": "THREE_LEVEL", + "geoname_id": 6567652, + "sub_districts": [] + } + ] + }, + { + "code": "320800", + "name": "淮安", + "level": "TWO_LEVEL", + "geoname_id": 1807649, + "sub_districts": [ + { + "code": "3208030000003", + "name": "淮安", + "level": "THREE_LEVEL", + "geoname_id": 320803, + "sub_districts": [] + }, + { + "code": "320804", + "name": "淮阴", + "level": "THREE_LEVEL", + "geoname_id": 1807648, + "sub_districts": [] + }, + { + "code": "3208130000003", + "name": "洪泽", + "level": "THREE_LEVEL", + "geoname_id": 1783570, + "sub_districts": [] + }, + { + "code": "320831", + "name": "金湖", + "level": "THREE_LEVEL", + "geoname_id": 1805519, + "sub_districts": [] + }, + { + "code": "320826", + "name": "涟水", + "level": "THREE_LEVEL", + "geoname_id": 320826, + "sub_districts": [] + }, + { + "code": "3208120000003", + "name": "清江浦", + "level": "THREE_LEVEL", + "geoname_id": 11535094, + "sub_districts": [] + }, + { + "code": "320830", + "name": "盱眙", + "level": "THREE_LEVEL", + "geoname_id": 1787829, + "sub_districts": [] + } + ] + }, + { + "code": "320700", + "name": "连云港", + "level": "TWO_LEVEL", + "geoname_id": 1788694, + "sub_districts": [ + { + "code": "320722", + "name": "东海", + "level": "THREE_LEVEL", + "geoname_id": 1812516, + "sub_districts": [] + }, + { + "code": "320724", + "name": "灌南", + "level": "THREE_LEVEL", + "geoname_id": 1809810, + "sub_districts": [] + }, + { + "code": "320707", + "name": "赣榆", + "level": "THREE_LEVEL", + "geoname_id": 1810641, + "sub_districts": [] + }, + { + "code": "320723", + "name": "灌云", + "level": "THREE_LEVEL", + "geoname_id": 1809671, + "sub_districts": [] + }, + { + "code": "320706", + "name": "海州", + "level": "THREE_LEVEL", + "geoname_id": 6567636, + "sub_districts": [] + }, + { + "code": "320703", + "name": "连云", + "level": "THREE_LEVEL", + "geoname_id": 6567635, + "sub_districts": [] + } + ] + }, + { + "code": "320100", + "name": "南京", + "level": "TWO_LEVEL", + "geoname_id": 1799962, + "sub_districts": [ + { + "code": "320118", + "name": "高淳", + "level": "THREE_LEVEL", + "geoname_id": 1810594, + "sub_districts": [] + }, + { + "code": "320106", + "name": "鼓楼", + "level": "THREE_LEVEL", + "geoname_id": 320106, + "sub_districts": [] + }, + { + "code": "320115", + "name": "江宁", + "level": "THREE_LEVEL", + "geoname_id": 1806288, + "sub_districts": [] + }, + { + "code": "320105", + "name": "建邺", + "level": "THREE_LEVEL", + "geoname_id": 6567623, + "sub_districts": [] + }, + { + "code": "320116", + "name": "六合", + "level": "THREE_LEVEL", + "geoname_id": 1802102, + "sub_districts": [] + }, + { + "code": "320117", + "name": "溧水", + "level": "THREE_LEVEL", + "geoname_id": 1803242, + "sub_districts": [] + }, + { + "code": "320111", + "name": "浦口", + "level": "THREE_LEVEL", + "geoname_id": 1806279, + "sub_districts": [] + }, + { + "code": "320104", + "name": "秦淮", + "level": "THREE_LEVEL", + "geoname_id": 6567622, + "sub_districts": [] + }, + { + "code": "320113", + "name": "栖霞", + "level": "THREE_LEVEL", + "geoname_id": 6567627, + "sub_districts": [] + }, + { + "code": "320102", + "name": "玄武", + "level": "THREE_LEVEL", + "geoname_id": 6567620, + "sub_districts": [] + }, + { + "code": "320114", + "name": "雨花台", + "level": "THREE_LEVEL", + "geoname_id": 6567628, + "sub_districts": [] + } + ] + }, + { + "code": "320600", + "name": "南通", + "level": "TWO_LEVEL", + "geoname_id": 1799722, + "sub_districts": [ + { + "code": "3206130000003", + "name": "崇川", + "level": "THREE_LEVEL", + "geoname_id": 6567648, + "sub_districts": [] + }, + { + "code": "3206850000001", + "name": "海安", + "level": "THREE_LEVEL", + "geoname_id": 1809116, + "sub_districts": [] + }, + { + "code": "3206140000001", + "name": "海门", + "level": "THREE_LEVEL", + "geoname_id": 1801200, + "sub_districts": [] + }, + { + "code": "3206710000003", + "name": "南通经济技术开发区", + "level": "THREE_LEVEL", + "geoname_id": 659010215, + "sub_districts": [] + }, + { + "code": "320681", + "name": "启东", + "level": "THREE_LEVEL", + "geoname_id": 1798079, + "sub_districts": [] + }, + { + "code": "320623", + "name": "如东", + "level": "THREE_LEVEL", + "geoname_id": 1797070, + "sub_districts": [] + }, + { + "code": "320682", + "name": "如皋", + "level": "THREE_LEVEL", + "geoname_id": 1797068, + "sub_districts": [] + }, + { + "code": "320612", + "name": "通州", + "level": "THREE_LEVEL", + "geoname_id": 6567618, + "sub_districts": [] + } + ] + }, + { + "code": "321300", + "name": "宿迁", + "level": "TWO_LEVEL", + "geoname_id": 1793770, + "sub_districts": [ + { + "code": "321302", + "name": "宿城", + "level": "THREE_LEVEL", + "geoname_id": 6567637, + "sub_districts": [] + }, + { + "code": "321324", + "name": "泗洪", + "level": "THREE_LEVEL", + "geoname_id": 1794255, + "sub_districts": [] + }, + { + "code": "321311", + "name": "宿豫", + "level": "THREE_LEVEL", + "geoname_id": 6567638, + "sub_districts": [] + }, + { + "code": "321322", + "name": "沭阳", + "level": "THREE_LEVEL", + "geoname_id": 1794313, + "sub_districts": [] + }, + { + "code": "321323", + "name": "泗阳", + "level": "THREE_LEVEL", + "geoname_id": 1794101, + "sub_districts": [] + } + ] + }, + { + "code": "320500", + "name": "苏州", + "level": "TWO_LEVEL", + "geoname_id": 1886760, + "sub_districts": [ + { + "code": "320581", + "name": "常熟", + "level": "THREE_LEVEL", + "geoname_id": 6685841, + "sub_districts": [] + }, + { + "code": "320508", + "name": "姑苏", + "level": "THREE_LEVEL", + "geoname_id": 320508, + "sub_districts": [] + }, + { + "code": "320505", + "name": "虎丘", + "level": "THREE_LEVEL", + "geoname_id": 6567665, + "sub_districts": [] + }, + { + "code": "320583", + "name": "昆山", + "level": "THREE_LEVEL", + "geoname_id": 1785623, + "sub_districts": [] + }, + { + "code": "3205710000000", + "name": "苏州工业园区", + "level": "THREE_LEVEL", + "geoname_id": 320571, + "sub_districts": [] + }, + { + "code": "320585", + "name": "太仓", + "level": "THREE_LEVEL", + "geoname_id": 1793703, + "sub_districts": [] + }, + { + "code": "320509", + "name": "吴江", + "level": "THREE_LEVEL", + "geoname_id": 1791194, + "sub_districts": [] + }, + { + "code": "3205060000000", + "name": "吴中", + "level": "THREE_LEVEL", + "geoname_id": 1881768, + "sub_districts": [] + }, + { + "code": "320507", + "name": "相城", + "level": "THREE_LEVEL", + "geoname_id": 7925575, + "sub_districts": [] + }, + { + "code": "320582", + "name": "张家港", + "level": "THREE_LEVEL", + "geoname_id": 320582, + "sub_districts": [] + } + ] + }, + { + "code": "321200", + "name": "泰州", + "level": "TWO_LEVEL", + "geoname_id": 1793505, + "sub_districts": [ + { + "code": "321203", + "name": "高港", + "level": "THREE_LEVEL", + "geoname_id": 6567647, + "sub_districts": [] + }, + { + "code": "321202", + "name": "海陵", + "level": "THREE_LEVEL", + "geoname_id": 6567646, + "sub_districts": [] + }, + { + "code": "321282", + "name": "靖江", + "level": "THREE_LEVEL", + "geoname_id": 1805636, + "sub_districts": [] + }, + { + "code": "321204", + "name": "姜堰", + "level": "THREE_LEVEL", + "geoname_id": 1793534, + "sub_districts": [] + }, + { + "code": "321283", + "name": "泰兴", + "level": "THREE_LEVEL", + "geoname_id": 1793533, + "sub_districts": [] + }, + { + "code": "321281", + "name": "兴化", + "level": "THREE_LEVEL", + "geoname_id": 1789017, + "sub_districts": [] + } + ] + }, + { + "code": "320200", + "name": "无锡", + "level": "TWO_LEVEL", + "geoname_id": 1790923, + "sub_districts": [ + { + "code": "320211", + "name": "滨湖", + "level": "THREE_LEVEL", + "geoname_id": 6567659, + "sub_districts": [] + }, + { + "code": "320206", + "name": "惠山", + "level": "THREE_LEVEL", + "geoname_id": 6567660, + "sub_districts": [] + }, + { + "code": "320281", + "name": "江阴", + "level": "THREE_LEVEL", + "geoname_id": 1815251, + "sub_districts": [] + }, + { + "code": "320213", + "name": "梁溪", + "level": "THREE_LEVEL", + "geoname_id": 320213, + "sub_districts": [] + }, + { + "code": "320205", + "name": "锡山", + "level": "THREE_LEVEL", + "geoname_id": 6567661, + "sub_districts": [] + }, + { + "code": "320214", + "name": "新吴", + "level": "THREE_LEVEL", + "geoname_id": 320214, + "sub_districts": [] + }, + { + "code": "320282", + "name": "宜兴", + "level": "THREE_LEVEL", + "geoname_id": 1786760, + "sub_districts": [] + } + ] + }, + { + "code": "320300", + "name": "徐州", + "level": "TWO_LEVEL", + "geoname_id": 1787824, + "sub_districts": [ + { + "code": "320321", + "name": "丰县", + "level": "THREE_LEVEL", + "geoname_id": 1811201, + "sub_districts": [] + }, + { + "code": "3203020000000", + "name": "鼓楼", + "level": "THREE_LEVEL", + "geoname_id": 320302, + "sub_districts": [] + }, + { + "code": "320305", + "name": "贾汪", + "level": "THREE_LEVEL", + "geoname_id": 6567632, + "sub_districts": [] + }, + { + "code": "320322", + "name": "沛县", + "level": "THREE_LEVEL", + "geoname_id": 1798954, + "sub_districts": [] + }, + { + "code": "320382", + "name": "邳州", + "level": "THREE_LEVEL", + "geoname_id": 1798595, + "sub_districts": [] + }, + { + "code": "320311", + "name": "泉山", + "level": "THREE_LEVEL", + "geoname_id": 6567633, + "sub_districts": [] + }, + { + "code": "320324", + "name": "睢宁", + "level": "THREE_LEVEL", + "geoname_id": 1793896, + "sub_districts": [] + }, + { + "code": "3203120000000", + "name": "铜山", + "level": "THREE_LEVEL", + "geoname_id": 1548718, + "sub_districts": [] + }, + { + "code": "320381", + "name": "新沂", + "level": "THREE_LEVEL", + "geoname_id": 1788510, + "sub_districts": [] + }, + { + "code": "320303", + "name": "云龙", + "level": "THREE_LEVEL", + "geoname_id": 6567629, + "sub_districts": [] + } + ] + }, + { + "code": "320900", + "name": "盐城", + "level": "TWO_LEVEL", + "geoname_id": 1787746, + "sub_districts": [ + { + "code": "320922", + "name": "滨海", + "level": "THREE_LEVEL", + "geoname_id": 1816349, + "sub_districts": [] + }, + { + "code": "320904", + "name": "大丰", + "level": "THREE_LEVEL", + "geoname_id": 1814428, + "sub_districts": [] + }, + { + "code": "320981", + "name": "东台", + "level": "THREE_LEVEL", + "geoname_id": 1812228, + "sub_districts": [] + }, + { + "code": "320923", + "name": "阜宁", + "level": "THREE_LEVEL", + "geoname_id": 1810949, + "sub_districts": [] + }, + { + "code": "320925", + "name": "建湖", + "level": "THREE_LEVEL", + "geoname_id": 1806181, + "sub_districts": [] + }, + { + "code": "320924", + "name": "射阳", + "level": "THREE_LEVEL", + "geoname_id": 1795526, + "sub_districts": [] + }, + { + "code": "320902", + "name": "亭湖", + "level": "THREE_LEVEL", + "geoname_id": 6567642, + "sub_districts": [] + }, + { + "code": "320921", + "name": "响水", + "level": "THREE_LEVEL", + "geoname_id": 1790495, + "sub_districts": [] + }, + { + "code": "320903", + "name": "盐都", + "level": "THREE_LEVEL", + "geoname_id": 6567643, + "sub_districts": [] + } + ] + }, + { + "code": "321000", + "name": "扬州", + "level": "TWO_LEVEL", + "geoname_id": 1787227, + "sub_districts": [ + { + "code": "321023", + "name": "宝应", + "level": "THREE_LEVEL", + "geoname_id": 1816888, + "sub_districts": [] + }, + { + "code": "321002", + "name": "广陵", + "level": "THREE_LEVEL", + "geoname_id": 6567644, + "sub_districts": [] + }, + { + "code": "321084", + "name": "高邮", + "level": "THREE_LEVEL", + "geoname_id": 1810309, + "sub_districts": [] + }, + { + "code": "321003", + "name": "邗江", + "level": "THREE_LEVEL", + "geoname_id": 1808903, + "sub_districts": [] + }, + { + "code": "321012", + "name": "江都", + "level": "THREE_LEVEL", + "geoname_id": 1806387, + "sub_districts": [] + }, + { + "code": "321081", + "name": "仪征", + "level": "THREE_LEVEL", + "geoname_id": 1784580, + "sub_districts": [] + } + ] + }, + { + "code": "321100", + "name": "镇江", + "level": "TWO_LEVEL", + "geoname_id": 1784642, + "sub_districts": [ + { + "code": "321112", + "name": "丹徒", + "level": "THREE_LEVEL", + "geoname_id": 1813808, + "sub_districts": [] + }, + { + "code": "321181", + "name": "丹阳", + "level": "THREE_LEVEL", + "geoname_id": 1813801, + "sub_districts": [] + }, + { + "code": "321102", + "name": "京口", + "level": "THREE_LEVEL", + "geoname_id": 6567650, + "sub_districts": [] + }, + { + "code": "321183", + "name": "句容", + "level": "THREE_LEVEL", + "geoname_id": 1804907, + "sub_districts": [] + }, + { + "code": "321111", + "name": "润州", + "level": "THREE_LEVEL", + "geoname_id": 6567651, + "sub_districts": [] + }, + { + "code": "321182", + "name": "扬中", + "level": "THREE_LEVEL", + "geoname_id": 1787229, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "36", + "name": "江西", + "level": "ONE_LEVEL", + "geoname_id": 1806222, + "sub_districts": [ + { + "code": "361000", + "name": "抚州", + "level": "TWO_LEVEL", + "geoname_id": 7739108, + "sub_districts": [ + { + "code": "361024", + "name": "崇仁", + "level": "THREE_LEVEL", + "geoname_id": 1814897, + "sub_districts": [] + }, + { + "code": "3610030000001", + "name": "东乡", + "level": "THREE_LEVEL", + "geoname_id": 1812153, + "sub_districts": [] + }, + { + "code": "361030", + "name": "广昌", + "level": "THREE_LEVEL", + "geoname_id": 1809943, + "sub_districts": [] + }, + { + "code": "361027", + "name": "金溪", + "level": "THREE_LEVEL", + "geoname_id": 1805321, + "sub_districts": [] + }, + { + "code": "361025", + "name": "乐安", + "level": "THREE_LEVEL", + "geoname_id": 1804257, + "sub_districts": [] + }, + { + "code": "361002", + "name": "临川", + "level": "THREE_LEVEL", + "geoname_id": 1803577, + "sub_districts": [] + }, + { + "code": "361022", + "name": "黎川", + "level": "THREE_LEVEL", + "geoname_id": 1803778, + "sub_districts": [] + }, + { + "code": "361021", + "name": "南城", + "level": "THREE_LEVEL", + "geoname_id": 1800151, + "sub_districts": [] + }, + { + "code": "361023", + "name": "南丰", + "level": "THREE_LEVEL", + "geoname_id": 1800084, + "sub_districts": [] + }, + { + "code": "361026", + "name": "宜黄", + "level": "THREE_LEVEL", + "geoname_id": 1786711, + "sub_districts": [] + }, + { + "code": "361028", + "name": "资溪", + "level": "THREE_LEVEL", + "geoname_id": 1783685, + "sub_districts": [] + } + ] + }, + { + "code": "360700", + "name": "赣州", + "level": "TWO_LEVEL", + "geoname_id": 1810638, + "sub_districts": [ + { + "code": "360726", + "name": "安远", + "level": "THREE_LEVEL", + "geoname_id": 1817930, + "sub_districts": [] + }, + { + "code": "360725", + "name": "崇义", + "level": "THREE_LEVEL", + "geoname_id": 1814873, + "sub_districts": [] + }, + { + "code": "360728", + "name": "定南", + "level": "THREE_LEVEL", + "geoname_id": 1812771, + "sub_districts": [] + }, + { + "code": "360723", + "name": "大余", + "level": "THREE_LEVEL", + "geoname_id": 1813124, + "sub_districts": [] + }, + { + "code": "3607040000001", + "name": "赣县", + "level": "THREE_LEVEL", + "geoname_id": 1810652, + "sub_districts": [] + }, + { + "code": "360733", + "name": "会昌", + "level": "THREE_LEVEL", + "geoname_id": 1806884, + "sub_districts": [] + }, + { + "code": "3607830000001", + "name": "龙南", + "level": "THREE_LEVEL", + "geoname_id": 1802495, + "sub_districts": [] + }, + { + "code": "360730", + "name": "宁都", + "level": "THREE_LEVEL", + "geoname_id": 1799390, + "sub_districts": [] + }, + { + "code": "360703", + "name": "南康", + "level": "THREE_LEVEL", + "geoname_id": 1799945, + "sub_districts": [] + }, + { + "code": "360729", + "name": "全南", + "level": "THREE_LEVEL", + "geoname_id": 1797370, + "sub_districts": [] + }, + { + "code": "360781", + "name": "瑞金", + "level": "THREE_LEVEL", + "geoname_id": 1797053, + "sub_districts": [] + }, + { + "code": "360735", + "name": "石城", + "level": "THREE_LEVEL", + "geoname_id": 1795448, + "sub_districts": [] + }, + { + "code": "360724", + "name": "上犹", + "level": "THREE_LEVEL", + "geoname_id": 1812284, + "sub_districts": [] + }, + { + "code": "360722", + "name": "信丰", + "level": "THREE_LEVEL", + "geoname_id": 1806509, + "sub_districts": [] + }, + { + "code": "360732", + "name": "兴国", + "level": "THREE_LEVEL", + "geoname_id": 1789029, + "sub_districts": [] + }, + { + "code": "360734", + "name": "寻乌", + "level": "THREE_LEVEL", + "geoname_id": 1815619, + "sub_districts": [] + }, + { + "code": "360731", + "name": "于都", + "level": "THREE_LEVEL", + "geoname_id": 1810124, + "sub_districts": [] + }, + { + "code": "360702", + "name": "章贡", + "level": "THREE_LEVEL", + "geoname_id": 6567600, + "sub_districts": [] + } + ] + }, + { + "code": "360800", + "name": "吉安", + "level": "TWO_LEVEL", + "geoname_id": 1806445, + "sub_districts": [ + { + "code": "360829", + "name": "安福", + "level": "THREE_LEVEL", + "geoname_id": 1818084, + "sub_districts": [] + }, + { + "code": "360821", + "name": "吉安", + "level": "THREE_LEVEL", + "geoname_id": 1806126, + "sub_districts": [] + }, + { + "code": "360881", + "name": "井冈山", + "level": "THREE_LEVEL", + "geoname_id": 1805666, + "sub_districts": [] + }, + { + "code": "360822", + "name": "吉水", + "level": "THREE_LEVEL", + "geoname_id": 1805266, + "sub_districts": [] + }, + { + "code": "360802", + "name": "吉州", + "level": "THREE_LEVEL", + "geoname_id": 6567602, + "sub_districts": [] + }, + { + "code": "360803", + "name": "青原", + "level": "THREE_LEVEL", + "geoname_id": 6567601, + "sub_districts": [] + }, + { + "code": "360827", + "name": "遂川", + "level": "THREE_LEVEL", + "geoname_id": 1793905, + "sub_districts": [] + }, + { + "code": "360826", + "name": "泰和", + "level": "THREE_LEVEL", + "geoname_id": 1793676, + "sub_districts": [] + }, + { + "code": "360828", + "name": "万安", + "level": "THREE_LEVEL", + "geoname_id": 1792192, + "sub_districts": [] + }, + { + "code": "360824", + "name": "新干", + "level": "THREE_LEVEL", + "geoname_id": 1789054, + "sub_districts": [] + }, + { + "code": "360823", + "name": "峡江", + "level": "THREE_LEVEL", + "geoname_id": 1790695, + "sub_districts": [] + }, + { + "code": "360825", + "name": "永丰", + "level": "THREE_LEVEL", + "geoname_id": 1786352, + "sub_districts": [] + }, + { + "code": "360830", + "name": "永新", + "level": "THREE_LEVEL", + "geoname_id": 1786224, + "sub_districts": [] + } + ] + }, + { + "code": "360200", + "name": "景德镇", + "level": "TWO_LEVEL", + "geoname_id": 1805680, + "sub_districts": [ + { + "code": "360202", + "name": "昌江", + "level": "THREE_LEVEL", + "geoname_id": 1924524, + "sub_districts": [] + }, + { + "code": "360222", + "name": "浮梁", + "level": "THREE_LEVEL", + "geoname_id": 1909612, + "sub_districts": [] + }, + { + "code": "360281", + "name": "乐平", + "level": "THREE_LEVEL", + "geoname_id": 1804156, + "sub_districts": [] + }, + { + "code": "360203", + "name": "珠山", + "level": "THREE_LEVEL", + "geoname_id": 6567610, + "sub_districts": [] + } + ] + }, + { + "code": "360400", + "name": "九江", + "level": "TWO_LEVEL", + "geoname_id": 1805179, + "sub_districts": [ + { + "code": "360404", + "name": "柴桑", + "level": "THREE_LEVEL", + "geoname_id": 360404, + "sub_districts": [] + }, + { + "code": "360426", + "name": "德安", + "level": "THREE_LEVEL", + "geoname_id": 1813040, + "sub_districts": [] + }, + { + "code": "360428", + "name": "都昌", + "level": "THREE_LEVEL", + "geoname_id": 1811930, + "sub_districts": [] + }, + { + "code": "360482", + "name": "共青城", + "level": "THREE_LEVEL", + "geoname_id": 360482, + "sub_districts": [] + }, + { + "code": "360429", + "name": "湖口", + "level": "THREE_LEVEL", + "geoname_id": 1806720, + "sub_districts": [] + }, + { + "code": "360483", + "name": "庐山", + "level": "THREE_LEVEL", + "geoname_id": 6567603, + "sub_districts": [] + }, + { + "code": "360402", + "name": "濂溪", + "level": "THREE_LEVEL", + "geoname_id": 360402, + "sub_districts": [] + }, + { + "code": "360430", + "name": "彭泽", + "level": "THREE_LEVEL", + "geoname_id": 1798899, + "sub_districts": [] + }, + { + "code": "360481", + "name": "瑞昌", + "level": "THREE_LEVEL", + "geoname_id": 7643679, + "sub_districts": [] + }, + { + "code": "360423", + "name": "武宁", + "level": "THREE_LEVEL", + "geoname_id": 1791053, + "sub_districts": [] + }, + { + "code": "360424", + "name": "修水", + "level": "THREE_LEVEL", + "geoname_id": 1788256, + "sub_districts": [] + }, + { + "code": "360403", + "name": "浔阳", + "level": "THREE_LEVEL", + "geoname_id": 6567604, + "sub_districts": [] + }, + { + "code": "360425", + "name": "永修", + "level": "THREE_LEVEL", + "geoname_id": 1786223, + "sub_districts": [] + } + ] + }, + { + "code": "360100", + "name": "南昌", + "level": "TWO_LEVEL", + "geoname_id": 1800163, + "sub_districts": [ + { + "code": "360123", + "name": "安义", + "level": "THREE_LEVEL", + "geoname_id": 1817936, + "sub_districts": [] + }, + { + "code": "360102", + "name": "东湖", + "level": "THREE_LEVEL", + "geoname_id": 6567609, + "sub_districts": [] + }, + { + "code": "360113", + "name": "红谷滩", + "level": "THREE_LEVEL", + "geoname_id": 360113, + "sub_districts": [] + }, + { + "code": "360124", + "name": "进贤", + "level": "THREE_LEVEL", + "geoname_id": 1805328, + "sub_districts": [] + }, + { + "code": "360121", + "name": "南昌", + "level": "THREE_LEVEL", + "geoname_id": 1800158, + "sub_districts": [] + }, + { + "code": "3601110000003", + "name": "青山湖", + "level": "THREE_LEVEL", + "geoname_id": 6567608, + "sub_districts": [] + }, + { + "code": "360104", + "name": "青云谱", + "level": "THREE_LEVEL", + "geoname_id": 6567606, + "sub_districts": [] + }, + { + "code": "360103", + "name": "西湖", + "level": "THREE_LEVEL", + "geoname_id": 6567607, + "sub_districts": [] + }, + { + "code": "3601120000003", + "name": "新建", + "level": "THREE_LEVEL", + "geoname_id": 1788795, + "sub_districts": [] + } + ] + }, + { + "code": "360300", + "name": "萍乡", + "level": "TWO_LEVEL", + "geoname_id": 1798654, + "sub_districts": [ + { + "code": "360302", + "name": "安源", + "level": "THREE_LEVEL", + "geoname_id": 6567614, + "sub_districts": [] + }, + { + "code": "360321", + "name": "莲花", + "level": "THREE_LEVEL", + "geoname_id": 1803904, + "sub_districts": [] + }, + { + "code": "360323", + "name": "芦溪", + "level": "THREE_LEVEL", + "geoname_id": 6567616, + "sub_districts": [] + }, + { + "code": "360322", + "name": "上栗", + "level": "THREE_LEVEL", + "geoname_id": 6567613, + "sub_districts": [] + }, + { + "code": "360313", + "name": "湘东", + "level": "THREE_LEVEL", + "geoname_id": 6567615, + "sub_districts": [] + } + ] + }, + { + "code": "361100", + "name": "上饶", + "level": "TWO_LEVEL", + "geoname_id": 1787858, + "sub_districts": [ + { + "code": "361181", + "name": "德兴", + "level": "THREE_LEVEL", + "geoname_id": 1812962, + "sub_districts": [] + }, + { + "code": "361103", + "name": "广丰", + "level": "THREE_LEVEL", + "geoname_id": 1809931, + "sub_districts": [] + }, + { + "code": "3611040000001", + "name": "广信", + "level": "THREE_LEVEL", + "geoname_id": 1796127, + "sub_districts": [] + }, + { + "code": "361125", + "name": "横峰", + "level": "THREE_LEVEL", + "geoname_id": 1808497, + "sub_districts": [] + }, + { + "code": "361128", + "name": "鄱阳", + "level": "THREE_LEVEL", + "geoname_id": 1816242, + "sub_districts": [] + }, + { + "code": "361129", + "name": "万年", + "level": "THREE_LEVEL", + "geoname_id": 1815063, + "sub_districts": [] + }, + { + "code": "361130", + "name": "婺源", + "level": "THREE_LEVEL", + "geoname_id": 1790859, + "sub_districts": [] + }, + { + "code": "361102", + "name": "信州", + "level": "THREE_LEVEL", + "geoname_id": 6567605, + "sub_districts": [] + }, + { + "code": "361127", + "name": "余干", + "level": "THREE_LEVEL", + "geoname_id": 1785865, + "sub_districts": [] + }, + { + "code": "361123", + "name": "玉山", + "level": "THREE_LEVEL", + "geoname_id": 1785617, + "sub_districts": [] + }, + { + "code": "361124", + "name": "铅山", + "level": "THREE_LEVEL", + "geoname_id": 1787106, + "sub_districts": [] + }, + { + "code": "361126", + "name": "弋阳", + "level": "THREE_LEVEL", + "geoname_id": 1786417, + "sub_districts": [] + } + ] + }, + { + "code": "360500", + "name": "新余", + "level": "TWO_LEVEL", + "geoname_id": 1788508, + "sub_districts": [ + { + "code": "360521", + "name": "分宜", + "level": "THREE_LEVEL", + "geoname_id": 1811113, + "sub_districts": [] + }, + { + "code": "360502", + "name": "渝水", + "level": "THREE_LEVEL", + "geoname_id": 6567611, + "sub_districts": [] + } + ] + }, + { + "code": "360900", + "name": "宜春", + "level": "TWO_LEVEL", + "geoname_id": 1786746, + "sub_districts": [ + { + "code": "360981", + "name": "丰城", + "level": "THREE_LEVEL", + "geoname_id": 1806248, + "sub_districts": [] + }, + { + "code": "360921", + "name": "奉新", + "level": "THREE_LEVEL", + "geoname_id": 1811191, + "sub_districts": [] + }, + { + "code": "360983", + "name": "高安", + "level": "THREE_LEVEL", + "geoname_id": 1810624, + "sub_districts": [] + }, + { + "code": "360925", + "name": "靖安", + "level": "THREE_LEVEL", + "geoname_id": 1805694, + "sub_districts": [] + }, + { + "code": "360923", + "name": "上高", + "level": "THREE_LEVEL", + "geoname_id": 1796252, + "sub_districts": [] + }, + { + "code": "360926", + "name": "铜鼓", + "level": "THREE_LEVEL", + "geoname_id": 1792667, + "sub_districts": [] + }, + { + "code": "360922", + "name": "万载", + "level": "THREE_LEVEL", + "geoname_id": 1804826, + "sub_districts": [] + }, + { + "code": "360924", + "name": "宜丰", + "level": "THREE_LEVEL", + "geoname_id": 1786726, + "sub_districts": [] + }, + { + "code": "360902", + "name": "袁州", + "level": "THREE_LEVEL", + "geoname_id": 6567612, + "sub_districts": [] + }, + { + "code": "360982", + "name": "樟树", + "level": "THREE_LEVEL", + "geoname_id": 1797869, + "sub_districts": [] + } + ] + }, + { + "code": "360600", + "name": "鹰潭", + "level": "TWO_LEVEL", + "geoname_id": 1786577, + "sub_districts": [ + { + "code": "360681", + "name": "贵溪", + "level": "THREE_LEVEL", + "geoname_id": 1788406, + "sub_districts": [] + }, + { + "code": "360602", + "name": "月湖", + "level": "THREE_LEVEL", + "geoname_id": 6567617, + "sub_districts": [] + }, + { + "code": "3606030000001", + "name": "余江", + "level": "THREE_LEVEL", + "geoname_id": 1785819, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "21", + "name": "辽宁", + "level": "ONE_LEVEL", + "geoname_id": 2036115, + "sub_districts": [ + { + "code": "210300", + "name": "鞍山", + "level": "TWO_LEVEL", + "geoname_id": 2038632, + "sub_districts": [ + { + "code": "210381", + "name": "海城", + "level": "THREE_LEVEL", + "geoname_id": 2037084, + "sub_districts": [] + }, + { + "code": "210304", + "name": "立山", + "level": "THREE_LEVEL", + "geoname_id": 6599878, + "sub_districts": [] + }, + { + "code": "210311", + "name": "千山", + "level": "THREE_LEVEL", + "geoname_id": 6599881, + "sub_districts": [] + }, + { + "code": "210321", + "name": "台安", + "level": "THREE_LEVEL", + "geoname_id": 2034609, + "sub_districts": [] + }, + { + "code": "210302", + "name": "铁东", + "level": "THREE_LEVEL", + "geoname_id": 6599879, + "sub_districts": [] + }, + { + "code": "210303", + "name": "铁西", + "level": "THREE_LEVEL", + "geoname_id": 6599880, + "sub_districts": [] + }, + { + "code": "210323", + "name": "岫岩", + "level": "THREE_LEVEL", + "geoname_id": 2033601, + "sub_districts": [] + } + ] + }, + { + "code": "210500", + "name": "本溪", + "level": "TWO_LEVEL", + "geoname_id": 2038300, + "sub_districts": [ + { + "code": "210521", + "name": "本溪", + "level": "THREE_LEVEL", + "geoname_id": 2038298, + "sub_districts": [] + }, + { + "code": "210522", + "name": "桓仁", + "level": "THREE_LEVEL", + "geoname_id": 2036711, + "sub_districts": [] + }, + { + "code": "210504", + "name": "明山", + "level": "THREE_LEVEL", + "geoname_id": 6599904, + "sub_districts": [] + }, + { + "code": "210505", + "name": "南芬", + "level": "THREE_LEVEL", + "geoname_id": 2054303, + "sub_districts": [] + }, + { + "code": "210502", + "name": "平山", + "level": "THREE_LEVEL", + "geoname_id": 6599902, + "sub_districts": [] + }, + { + "code": "210503", + "name": "溪湖", + "level": "THREE_LEVEL", + "geoname_id": 6599903, + "sub_districts": [] + } + ] + }, + { + "code": "211300", + "name": "朝阳", + "level": "TWO_LEVEL", + "geoname_id": 2038101, + "sub_districts": [ + { + "code": "211381", + "name": "北票", + "level": "THREE_LEVEL", + "geoname_id": 2038341, + "sub_districts": [] + }, + { + "code": "211321", + "name": "朝阳", + "level": "THREE_LEVEL", + "geoname_id": 2038099, + "sub_districts": [] + }, + { + "code": "211322", + "name": "建平", + "level": "THREE_LEVEL", + "geoname_id": 2036545, + "sub_districts": [] + }, + { + "code": "211324", + "name": "喀喇沁左翼", + "level": "THREE_LEVEL", + "geoname_id": 2036999, + "sub_districts": [] + }, + { + "code": "211303", + "name": "龙城", + "level": "THREE_LEVEL", + "geoname_id": 6599866, + "sub_districts": [] + }, + { + "code": "211382", + "name": "凌源", + "level": "THREE_LEVEL", + "geoname_id": 2036074, + "sub_districts": [] + }, + { + "code": "211302", + "name": "双塔", + "level": "THREE_LEVEL", + "geoname_id": 6599867, + "sub_districts": [] + } + ] + }, + { + "code": "210600", + "name": "丹东", + "level": "TWO_LEVEL", + "geoname_id": 2037886, + "sub_districts": [ + { + "code": "210681", + "name": "东港", + "level": "THREE_LEVEL", + "geoname_id": 1812547, + "sub_districts": [] + }, + { + "code": "210682", + "name": "凤城", + "level": "THREE_LEVEL", + "geoname_id": 2037410, + "sub_districts": [] + }, + { + "code": "210624", + "name": "宽甸", + "level": "THREE_LEVEL", + "geoname_id": 2036282, + "sub_districts": [] + }, + { + "code": "210602", + "name": "元宝", + "level": "THREE_LEVEL", + "geoname_id": 6599886, + "sub_districts": [] + }, + { + "code": "210604", + "name": "振安", + "level": "THREE_LEVEL", + "geoname_id": 6599885, + "sub_districts": [] + }, + { + "code": "210603", + "name": "振兴", + "level": "THREE_LEVEL", + "geoname_id": 6599887, + "sub_districts": [] + } + ] + }, + { + "code": "210200", + "name": "大连", + "level": "TWO_LEVEL", + "geoname_id": 1814087, + "sub_districts": [ + { + "code": "210224", + "name": "长海", + "level": "THREE_LEVEL", + "geoname_id": 1815726, + "sub_districts": [] + }, + { + "code": "210211", + "name": "甘井子", + "level": "THREE_LEVEL", + "geoname_id": 1922818, + "sub_districts": [] + }, + { + "code": "210213", + "name": "金州", + "level": "THREE_LEVEL", + "geoname_id": 1805337, + "sub_districts": [] + }, + { + "code": "210212", + "name": "旅顺口", + "level": "THREE_LEVEL", + "geoname_id": 1922819, + "sub_districts": [] + }, + { + "code": "210214", + "name": "普兰店", + "level": "THREE_LEVEL", + "geoname_id": 1788767, + "sub_districts": [] + }, + { + "code": "210204", + "name": "沙河口", + "level": "THREE_LEVEL", + "geoname_id": 6599877, + "sub_districts": [] + }, + { + "code": "210281", + "name": "瓦房店", + "level": "THREE_LEVEL", + "geoname_id": 1792259, + "sub_districts": [] + }, + { + "code": "210203", + "name": "西岗", + "level": "THREE_LEVEL", + "geoname_id": 6599876, + "sub_districts": [] + }, + { + "code": "210283", + "name": "庄河", + "level": "THREE_LEVEL", + "geoname_id": 1784054, + "sub_districts": [] + }, + { + "code": "210202", + "name": "中山", + "level": "THREE_LEVEL", + "geoname_id": 6599875, + "sub_districts": [] + } + ] + }, + { + "code": "210400", + "name": "抚顺", + "level": "TWO_LEVEL", + "geoname_id": 2037355, + "sub_districts": [ + { + "code": "210403", + "name": "东洲", + "level": "THREE_LEVEL", + "geoname_id": 6599896, + "sub_districts": [] + }, + { + "code": "210421", + "name": "抚顺", + "level": "THREE_LEVEL", + "geoname_id": 2037352, + "sub_districts": [] + }, + { + "code": "210423", + "name": "清原", + "level": "THREE_LEVEL", + "geoname_id": 2035273, + "sub_districts": [] + }, + { + "code": "210411", + "name": "顺城", + "level": "THREE_LEVEL", + "geoname_id": 6599894, + "sub_districts": [] + }, + { + "code": "210404", + "name": "望花", + "level": "THREE_LEVEL", + "geoname_id": 6599897, + "sub_districts": [] + }, + { + "code": "210422", + "name": "新宾", + "level": "THREE_LEVEL", + "geoname_id": 2033794, + "sub_districts": [] + }, + { + "code": "210402", + "name": "新抚", + "level": "THREE_LEVEL", + "geoname_id": 6599895, + "sub_districts": [] + } + ] + }, + { + "code": "210900", + "name": "阜新", + "level": "TWO_LEVEL", + "geoname_id": 2037346, + "sub_districts": [ + { + "code": "210921", + "name": "阜新", + "level": "THREE_LEVEL", + "geoname_id": 2037338, + "sub_districts": [] + }, + { + "code": "210902", + "name": "海州", + "level": "THREE_LEVEL", + "geoname_id": 6599898, + "sub_districts": [] + }, + { + "code": "210905", + "name": "清河门", + "level": "THREE_LEVEL", + "geoname_id": 2054307, + "sub_districts": [] + }, + { + "code": "210904", + "name": "太平", + "level": "THREE_LEVEL", + "geoname_id": 6599899, + "sub_districts": [] + }, + { + "code": "210911", + "name": "细河", + "level": "THREE_LEVEL", + "geoname_id": 6599900, + "sub_districts": [] + }, + { + "code": "210903", + "name": "新邱", + "level": "THREE_LEVEL", + "geoname_id": 2054308, + "sub_districts": [] + }, + { + "code": "210922", + "name": "彰武", + "level": "THREE_LEVEL", + "geoname_id": 2033178, + "sub_districts": [] + } + ] + }, + { + "code": "211400", + "name": "葫芦岛", + "level": "TWO_LEVEL", + "geoname_id": 2036430, + "sub_districts": [ + { + "code": "211422", + "name": "建昌", + "level": "THREE_LEVEL", + "geoname_id": 2036573, + "sub_districts": [] + }, + { + "code": "211403", + "name": "龙港", + "level": "THREE_LEVEL", + "geoname_id": 2054309, + "sub_districts": [] + }, + { + "code": "211402", + "name": "连山", + "level": "THREE_LEVEL", + "geoname_id": 6599868, + "sub_districts": [] + }, + { + "code": "211404", + "name": "南票", + "level": "THREE_LEVEL", + "geoname_id": 2054310, + "sub_districts": [] + }, + { + "code": "211421", + "name": "绥中", + "level": "THREE_LEVEL", + "geoname_id": 2034646, + "sub_districts": [] + }, + { + "code": "211481", + "name": "兴城", + "level": "THREE_LEVEL", + "geoname_id": 2033763, + "sub_districts": [] + } + ] + }, + { + "code": "210700", + "name": "锦州", + "level": "TWO_LEVEL", + "geoname_id": 2036427, + "sub_districts": [ + { + "code": "210782", + "name": "北镇", + "level": "THREE_LEVEL", + "geoname_id": 2038305, + "sub_districts": [] + }, + { + "code": "210702", + "name": "古塔", + "level": "THREE_LEVEL", + "geoname_id": 6599869, + "sub_districts": [] + }, + { + "code": "210726", + "name": "黑山", + "level": "THREE_LEVEL", + "geoname_id": 2036954, + "sub_districts": [] + }, + { + "code": "210703", + "name": "凌河", + "level": "THREE_LEVEL", + "geoname_id": 6599870, + "sub_districts": [] + }, + { + "code": "210781", + "name": "凌海", + "level": "THREE_LEVEL", + "geoname_id": 2036433, + "sub_districts": [] + }, + { + "code": "210711", + "name": "太和", + "level": "THREE_LEVEL", + "geoname_id": 6599871, + "sub_districts": [] + }, + { + "code": "210727", + "name": "义县", + "level": "THREE_LEVEL", + "geoname_id": 2033340, + "sub_districts": [] + } + ] + }, + { + "code": "211000", + "name": "辽阳", + "level": "TWO_LEVEL", + "geoname_id": 2036113, + "sub_districts": [ + { + "code": "211002", + "name": "白塔", + "level": "THREE_LEVEL", + "geoname_id": 6599882, + "sub_districts": [] + }, + { + "code": "211081", + "name": "灯塔", + "level": "THREE_LEVEL", + "geoname_id": 2037704, + "sub_districts": [] + }, + { + "code": "211005", + "name": "弓长岭", + "level": "THREE_LEVEL", + "geoname_id": 2054302, + "sub_districts": [] + }, + { + "code": "211004", + "name": "宏伟", + "level": "THREE_LEVEL", + "geoname_id": 2054301, + "sub_districts": [] + }, + { + "code": "211021", + "name": "辽阳", + "level": "THREE_LEVEL", + "geoname_id": 2036110, + "sub_districts": [] + }, + { + "code": "211011", + "name": "太子河", + "level": "THREE_LEVEL", + "geoname_id": 6599884, + "sub_districts": [] + }, + { + "code": "211003", + "name": "文圣", + "level": "THREE_LEVEL", + "geoname_id": 6599883, + "sub_districts": [] + } + ] + }, + { + "code": "211100", + "name": "盘锦", + "level": "TWO_LEVEL", + "geoname_id": 2035516, + "sub_districts": [ + { + "code": "211104", + "name": "大洼", + "level": "THREE_LEVEL", + "geoname_id": 2037770, + "sub_districts": [] + }, + { + "code": "211122", + "name": "盘山", + "level": "THREE_LEVEL", + "geoname_id": 2035512, + "sub_districts": [] + }, + { + "code": "211102", + "name": "双台子", + "level": "THREE_LEVEL", + "geoname_id": 2054306, + "sub_districts": [] + }, + { + "code": "211103", + "name": "兴隆台", + "level": "THREE_LEVEL", + "geoname_id": 6599872, + "sub_districts": [] + } + ] + }, + { + "code": "210100", + "name": "沈阳", + "level": "TWO_LEVEL", + "geoname_id": 2034937, + "sub_districts": [ + { + "code": "210104", + "name": "大东", + "level": "THREE_LEVEL", + "geoname_id": 6599890, + "sub_districts": [] + }, + { + "code": "210124", + "name": "法库", + "level": "THREE_LEVEL", + "geoname_id": 2037432, + "sub_districts": [] + }, + { + "code": "210105", + "name": "皇姑", + "level": "THREE_LEVEL", + "geoname_id": 6599891, + "sub_districts": [] + }, + { + "code": "210112", + "name": "浑南", + "level": "THREE_LEVEL", + "geoname_id": 210112, + "sub_districts": [] + }, + { + "code": "210102", + "name": "和平", + "level": "THREE_LEVEL", + "geoname_id": 6599889, + "sub_districts": [] + }, + { + "code": "210123", + "name": "康平", + "level": "THREE_LEVEL", + "geoname_id": 2036324, + "sub_districts": [] + }, + { + "code": "210115", + "name": "辽中", + "level": "THREE_LEVEL", + "geoname_id": 2036105, + "sub_districts": [] + }, + { + "code": "210113", + "name": "沈北", + "level": "THREE_LEVEL", + "geoname_id": 2054311, + "sub_districts": [] + }, + { + "code": "210103", + "name": "沈河", + "level": "THREE_LEVEL", + "geoname_id": 6599888, + "sub_districts": [] + }, + { + "code": "210111", + "name": "苏家屯", + "level": "THREE_LEVEL", + "geoname_id": 2054300, + "sub_districts": [] + }, + { + "code": "210106", + "name": "铁西", + "level": "THREE_LEVEL", + "geoname_id": 6599892, + "sub_districts": [] + }, + { + "code": "210181", + "name": "新民", + "level": "THREE_LEVEL", + "geoname_id": 2033670, + "sub_districts": [] + }, + { + "code": "210114", + "name": "于洪", + "level": "THREE_LEVEL", + "geoname_id": 6599893, + "sub_districts": [] + } + ] + }, + { + "code": "211200", + "name": "铁岭", + "level": "TWO_LEVEL", + "geoname_id": 2034437, + "sub_districts": [ + { + "code": "211224", + "name": "昌图", + "level": "THREE_LEVEL", + "geoname_id": 2038137, + "sub_districts": [] + }, + { + "code": "211281", + "name": "调兵山", + "level": "THREE_LEVEL", + "geoname_id": 2034444, + "sub_districts": [] + }, + { + "code": "211282", + "name": "开原", + "level": "THREE_LEVEL", + "geoname_id": 2036335, + "sub_districts": [] + }, + { + "code": "211204", + "name": "清河", + "level": "THREE_LEVEL", + "geoname_id": 2054298, + "sub_districts": [] + }, + { + "code": "211221", + "name": "铁岭", + "level": "THREE_LEVEL", + "geoname_id": 2034436, + "sub_districts": [] + }, + { + "code": "211223", + "name": "西丰", + "level": "THREE_LEVEL", + "geoname_id": 2033862, + "sub_districts": [] + }, + { + "code": "211202", + "name": "银州", + "level": "THREE_LEVEL", + "geoname_id": 6599901, + "sub_districts": [] + } + ] + }, + { + "code": "210800", + "name": "营口", + "level": "TWO_LEVEL", + "geoname_id": 2033369, + "sub_districts": [ + { + "code": "210804", + "name": "鲅鱼圈", + "level": "THREE_LEVEL", + "geoname_id": 210804, + "sub_districts": [] + }, + { + "code": "210882", + "name": "大石桥", + "level": "THREE_LEVEL", + "geoname_id": 2033368, + "sub_districts": [] + }, + { + "code": "210881", + "name": "盖州", + "level": "THREE_LEVEL", + "geoname_id": 2037326, + "sub_districts": [] + }, + { + "code": "210811", + "name": "老边", + "level": "THREE_LEVEL", + "geoname_id": 2054304, + "sub_districts": [] + }, + { + "code": "210803", + "name": "西市", + "level": "THREE_LEVEL", + "geoname_id": 6599874, + "sub_districts": [] + }, + { + "code": "210802", + "name": "站前", + "level": "THREE_LEVEL", + "geoname_id": 6599873, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "15", + "name": "内蒙古", + "level": "ONE_LEVEL", + "geoname_id": 2035607, + "sub_districts": [ + { + "code": "152900", + "name": "阿拉善", + "level": "TWO_LEVEL", + "geoname_id": 1818128, + "sub_districts": [ + { + "code": "152922", + "name": "阿拉善右", + "level": "THREE_LEVEL", + "geoname_id": 1818127, + "sub_districts": [] + }, + { + "code": "152921", + "name": "阿拉善左", + "level": "THREE_LEVEL", + "geoname_id": 1818126, + "sub_districts": [] + }, + { + "code": "152923", + "name": "额济纳", + "level": "THREE_LEVEL", + "geoname_id": 2037525, + "sub_districts": [] + } + ] + }, + { + "code": "150200", + "name": "包头", + "level": "TWO_LEVEL", + "geoname_id": 2038432, + "sub_districts": [ + { + "code": "150206", + "name": "白云鄂博矿区", + "level": "THREE_LEVEL", + "geoname_id": 8054542, + "sub_districts": [] + }, + { + "code": "150223", + "name": "达尔罕茂明安", + "level": "THREE_LEVEL", + "geoname_id": 2037840, + "sub_districts": [] + }, + { + "code": "150202", + "name": "东河", + "level": "THREE_LEVEL", + "geoname_id": 150202, + "sub_districts": [] + }, + { + "code": "150222", + "name": "固阳", + "level": "THREE_LEVEL", + "geoname_id": 2037108, + "sub_districts": [] + }, + { + "code": "150207", + "name": "九原", + "level": "THREE_LEVEL", + "geoname_id": 6643405, + "sub_districts": [] + }, + { + "code": "150203", + "name": "昆都仑", + "level": "THREE_LEVEL", + "geoname_id": 6643406, + "sub_districts": [] + }, + { + "code": "150204", + "name": "青山", + "level": "THREE_LEVEL", + "geoname_id": 6643403, + "sub_districts": [] + }, + { + "code": "150205", + "name": "石拐", + "level": "THREE_LEVEL", + "geoname_id": 6643445, + "sub_districts": [] + }, + { + "code": "150221", + "name": "土默特右", + "level": "THREE_LEVEL", + "geoname_id": 2034342, + "sub_districts": [] + } + ] + }, + { + "code": "150800", + "name": "巴彦淖尔", + "level": "TWO_LEVEL", + "geoname_id": 2038392, + "sub_districts": [ + { + "code": "150822", + "name": "磴口", + "level": "THREE_LEVEL", + "geoname_id": 2037707, + "sub_districts": [] + }, + { + "code": "150826", + "name": "杭锦后", + "level": "THREE_LEVEL", + "geoname_id": 2034062, + "sub_districts": [] + }, + { + "code": "150802", + "name": "临河", + "level": "THREE_LEVEL", + "geoname_id": 2036070, + "sub_districts": [] + }, + { + "code": "150825", + "name": "乌拉特后", + "level": "THREE_LEVEL", + "geoname_id": 2034286, + "sub_districts": [] + }, + { + "code": "150823", + "name": "乌拉特前", + "level": "THREE_LEVEL", + "geoname_id": 2034285, + "sub_districts": [] + }, + { + "code": "150824", + "name": "乌拉特中", + "level": "THREE_LEVEL", + "geoname_id": 2034284, + "sub_districts": [] + }, + { + "code": "150821", + "name": "五原", + "level": "THREE_LEVEL", + "geoname_id": 2034070, + "sub_districts": [] + } + ] + }, + { + "code": "150400", + "name": "赤峰", + "level": "TWO_LEVEL", + "geoname_id": 2038067, + "sub_districts": [ + { + "code": "150430", + "name": "敖汉", + "level": "THREE_LEVEL", + "geoname_id": 2038622, + "sub_districts": [] + }, + { + "code": "150421", + "name": "阿鲁科尔沁", + "level": "THREE_LEVEL", + "geoname_id": 2038617, + "sub_districts": [] + }, + { + "code": "150423", + "name": "巴林右", + "level": "THREE_LEVEL", + "geoname_id": 2038538, + "sub_districts": [] + }, + { + "code": "150422", + "name": "巴林左", + "level": "THREE_LEVEL", + "geoname_id": 2038537, + "sub_districts": [] + }, + { + "code": "150402", + "name": "红山", + "level": "THREE_LEVEL", + "geoname_id": 6643409, + "sub_districts": [] + }, + { + "code": "150428", + "name": "喀喇沁", + "level": "THREE_LEVEL", + "geoname_id": 2037000, + "sub_districts": [] + }, + { + "code": "150425", + "name": "克什克腾", + "level": "THREE_LEVEL", + "geoname_id": 2036901, + "sub_districts": [] + }, + { + "code": "150424", + "name": "林西", + "level": "THREE_LEVEL", + "geoname_id": 2036061, + "sub_districts": [] + }, + { + "code": "150429", + "name": "宁城", + "level": "THREE_LEVEL", + "geoname_id": 2035586, + "sub_districts": [] + }, + { + "code": "150404", + "name": "松山", + "level": "THREE_LEVEL", + "geoname_id": 6643408, + "sub_districts": [] + }, + { + "code": "150426", + "name": "翁牛特", + "level": "THREE_LEVEL", + "geoname_id": 2035537, + "sub_districts": [] + }, + { + "code": "150403", + "name": "元宝山", + "level": "THREE_LEVEL", + "geoname_id": 6643416, + "sub_districts": [] + } + ] + }, + { + "code": "150600", + "name": "鄂尔多斯", + "level": "TWO_LEVEL", + "geoname_id": 8347664, + "sub_districts": [ + { + "code": "150621", + "name": "达拉特", + "level": "THREE_LEVEL", + "geoname_id": 2037932, + "sub_districts": [] + }, + { + "code": "150602", + "name": "东胜", + "level": "THREE_LEVEL", + "geoname_id": 1812255, + "sub_districts": [] + }, + { + "code": "150624", + "name": "鄂托克", + "level": "THREE_LEVEL", + "geoname_id": 1799152, + "sub_districts": [] + }, + { + "code": "150623", + "name": "鄂托克前", + "level": "THREE_LEVEL", + "geoname_id": 1799151, + "sub_districts": [] + }, + { + "code": "150625", + "name": "杭锦", + "level": "THREE_LEVEL", + "geoname_id": 1808938, + "sub_districts": [] + }, + { + "code": "150603", + "name": "康巴什", + "level": "THREE_LEVEL", + "geoname_id": 150603, + "sub_districts": [] + }, + { + "code": "150626", + "name": "乌审", + "level": "THREE_LEVEL", + "geoname_id": 1792275, + "sub_districts": [] + }, + { + "code": "150627", + "name": "伊金霍洛", + "level": "THREE_LEVEL", + "geoname_id": 1811740, + "sub_districts": [] + }, + { + "code": "150622", + "name": "准格尔", + "level": "THREE_LEVEL", + "geoname_id": 1804940, + "sub_districts": [] + } + ] + }, + { + "code": "150100", + "name": "呼和浩特", + "level": "TWO_LEVEL", + "geoname_id": 2036892, + "sub_districts": [ + { + "code": "150123", + "name": "和林格尔", + "level": "THREE_LEVEL", + "geoname_id": 2033051, + "sub_districts": [] + }, + { + "code": "150103", + "name": "回民", + "level": "THREE_LEVEL", + "geoname_id": 6643396, + "sub_districts": [] + }, + { + "code": "150124", + "name": "清水河", + "level": "THREE_LEVEL", + "geoname_id": 1797730, + "sub_districts": [] + }, + { + "code": "150105", + "name": "赛罕", + "level": "THREE_LEVEL", + "geoname_id": 6643398, + "sub_districts": [] + }, + { + "code": "150122", + "name": "托克托", + "level": "THREE_LEVEL", + "geoname_id": 2034427, + "sub_districts": [] + }, + { + "code": "150121", + "name": "土默特左", + "level": "THREE_LEVEL", + "geoname_id": 2034341, + "sub_districts": [] + }, + { + "code": "150125", + "name": "武川", + "level": "THREE_LEVEL", + "geoname_id": 2034139, + "sub_districts": [] + }, + { + "code": "150102", + "name": "新城", + "level": "THREE_LEVEL", + "geoname_id": 6643399, + "sub_districts": [] + }, + { + "code": "150104", + "name": "玉泉", + "level": "THREE_LEVEL", + "geoname_id": 6643397, + "sub_districts": [] + } + ] + }, + { + "code": "150700", + "name": "呼伦贝尔", + "level": "TWO_LEVEL", + "geoname_id": 2036660, + "sub_districts": [ + { + "code": "150721", + "name": "阿荣", + "level": "THREE_LEVEL", + "geoname_id": 6643411, + "sub_districts": [] + }, + { + "code": "150725", + "name": "陈巴尔虎", + "level": "THREE_LEVEL", + "geoname_id": 2038088, + "sub_districts": [] + }, + { + "code": "150784", + "name": "额尔古纳", + "level": "THREE_LEVEL", + "geoname_id": 2037477, + "sub_districts": [] + }, + { + "code": "150723", + "name": "鄂伦春", + "level": "THREE_LEVEL", + "geoname_id": 2035531, + "sub_districts": [] + }, + { + "code": "150724", + "name": "鄂温克族", + "level": "THREE_LEVEL", + "geoname_id": 2037435, + "sub_districts": [] + }, + { + "code": "150785", + "name": "根河", + "level": "THREE_LEVEL", + "geoname_id": 2037478, + "sub_districts": [] + }, + { + "code": "150702", + "name": "海拉尔", + "level": "THREE_LEVEL", + "geoname_id": 2037076, + "sub_districts": [] + }, + { + "code": "150722", + "name": "莫力达瓦", + "level": "THREE_LEVEL", + "geoname_id": 6643412, + "sub_districts": [] + }, + { + "code": "150781", + "name": "满洲里", + "level": "THREE_LEVEL", + "geoname_id": 2035835, + "sub_districts": [] + }, + { + "code": "150727", + "name": "新巴尔虎右", + "level": "THREE_LEVEL", + "geoname_id": 2033796, + "sub_districts": [] + }, + { + "code": "150726", + "name": "新巴尔虎左", + "level": "THREE_LEVEL", + "geoname_id": 2033797, + "sub_districts": [] + }, + { + "code": "150782", + "name": "牙克石", + "level": "THREE_LEVEL", + "geoname_id": 2033535, + "sub_districts": [] + }, + { + "code": "150703", + "name": "扎赉诺尔", + "level": "THREE_LEVEL", + "geoname_id": 2036595, + "sub_districts": [] + }, + { + "code": "150783", + "name": "扎兰屯", + "level": "THREE_LEVEL", + "geoname_id": 2033224, + "sub_districts": [] + } + ] + }, + { + "code": "150500", + "name": "通辽", + "level": "TWO_LEVEL", + "geoname_id": 2034400, + "sub_districts": [ + { + "code": "150581", + "name": "霍林郭勒", + "level": "THREE_LEVEL", + "geoname_id": 6569942, + "sub_districts": [] + }, + { + "code": "150502", + "name": "科尔沁", + "level": "THREE_LEVEL", + "geoname_id": 2034398, + "sub_districts": [] + }, + { + "code": "150522", + "name": "科尔沁左翼后", + "level": "THREE_LEVEL", + "geoname_id": 2036806, + "sub_districts": [] + }, + { + "code": "150521", + "name": "科尔沁左翼中", + "level": "THREE_LEVEL", + "geoname_id": 2036805, + "sub_districts": [] + }, + { + "code": "150524", + "name": "库伦", + "level": "THREE_LEVEL", + "geoname_id": 2036629, + "sub_districts": [] + }, + { + "code": "150523", + "name": "开鲁", + "level": "THREE_LEVEL", + "geoname_id": 2036340, + "sub_districts": [] + }, + { + "code": "150525", + "name": "奈曼", + "level": "THREE_LEVEL", + "geoname_id": 2035682, + "sub_districts": [] + }, + { + "code": "150526", + "name": "扎鲁特", + "level": "THREE_LEVEL", + "geoname_id": 2036588, + "sub_districts": [] + } + ] + }, + { + "code": "150300", + "name": "乌海", + "level": "TWO_LEVEL", + "geoname_id": 1791249, + "sub_districts": [ + { + "code": "150302", + "name": "海勃湾", + "level": "THREE_LEVEL", + "geoname_id": 6643401, + "sub_districts": [] + }, + { + "code": "150303", + "name": "海南", + "level": "THREE_LEVEL", + "geoname_id": 6643400, + "sub_districts": [] + }, + { + "code": "150304", + "name": "乌达", + "level": "THREE_LEVEL", + "geoname_id": 6643402, + "sub_districts": [] + } + ] + }, + { + "code": "150900", + "name": "乌兰察布", + "level": "TWO_LEVEL", + "geoname_id": 2034303, + "sub_districts": [ + { + "code": "150928", + "name": "察哈尔右翼后", + "level": "THREE_LEVEL", + "geoname_id": 2035423, + "sub_districts": [] + }, + { + "code": "150926", + "name": "察哈尔右翼前", + "level": "THREE_LEVEL", + "geoname_id": 2035422, + "sub_districts": [] + }, + { + "code": "150927", + "name": "察哈尔右翼中", + "level": "THREE_LEVEL", + "geoname_id": 2035421, + "sub_districts": [] + }, + { + "code": "150981", + "name": "丰镇", + "level": "THREE_LEVEL", + "geoname_id": 2037390, + "sub_districts": [] + }, + { + "code": "150922", + "name": "化德", + "level": "THREE_LEVEL", + "geoname_id": 2036777, + "sub_districts": [] + }, + { + "code": "150902", + "name": "集宁", + "level": "THREE_LEVEL", + "geoname_id": 2036457, + "sub_districts": [] + }, + { + "code": "150925", + "name": "凉城", + "level": "THREE_LEVEL", + "geoname_id": 2036166, + "sub_districts": [] + }, + { + "code": "150923", + "name": "商都", + "level": "THREE_LEVEL", + "geoname_id": 2035030, + "sub_districts": [] + }, + { + "code": "150929", + "name": "四子王", + "level": "THREE_LEVEL", + "geoname_id": 2034704, + "sub_districts": [] + }, + { + "code": "150924", + "name": "兴和", + "level": "THREE_LEVEL", + "geoname_id": 2033758, + "sub_districts": [] + }, + { + "code": "150921", + "name": "卓资", + "level": "THREE_LEVEL", + "geoname_id": 2033066, + "sub_districts": [] + } + ] + }, + { + "code": "152200", + "name": "兴安", + "level": "TWO_LEVEL", + "geoname_id": 2036898, + "sub_districts": [ + { + "code": "152202", + "name": "阿尔山", + "level": "THREE_LEVEL", + "geoname_id": 6643414, + "sub_districts": [] + }, + { + "code": "152221", + "name": "科尔沁右翼前", + "level": "THREE_LEVEL", + "geoname_id": 2036808, + "sub_districts": [] + }, + { + "code": "152222", + "name": "科尔沁右翼中", + "level": "THREE_LEVEL", + "geoname_id": 2036807, + "sub_districts": [] + }, + { + "code": "152224", + "name": "突泉", + "level": "THREE_LEVEL", + "geoname_id": 2034322, + "sub_districts": [] + }, + { + "code": "152201", + "name": "乌兰浩特", + "level": "THREE_LEVEL", + "geoname_id": 2034311, + "sub_districts": [] + }, + { + "code": "152223", + "name": "扎赉特", + "level": "THREE_LEVEL", + "geoname_id": 2036596, + "sub_districts": [] + } + ] + }, + { + "code": "152500", + "name": "锡林郭勒", + "level": "TWO_LEVEL", + "geoname_id": 2033827, + "sub_districts": [ + { + "code": "152522", + "name": "阿巴嘎", + "level": "THREE_LEVEL", + "geoname_id": 2038681, + "sub_districts": [] + }, + { + "code": "152531", + "name": "多伦", + "level": "THREE_LEVEL", + "geoname_id": 2037529, + "sub_districts": [] + }, + { + "code": "152525", + "name": "东乌珠穆沁", + "level": "THREE_LEVEL", + "geoname_id": 2037587, + "sub_districts": [] + }, + { + "code": "152501", + "name": "二连浩特", + "level": "THREE_LEVEL", + "geoname_id": 2037484, + "sub_districts": [] + }, + { + "code": "152524", + "name": "苏尼特右", + "level": "THREE_LEVEL", + "geoname_id": 2034671, + "sub_districts": [] + }, + { + "code": "152523", + "name": "苏尼特左", + "level": "THREE_LEVEL", + "geoname_id": 2034670, + "sub_districts": [] + }, + { + "code": "152527", + "name": "太仆寺", + "level": "THREE_LEVEL", + "geoname_id": 2034608, + "sub_districts": [] + }, + { + "code": "152528", + "name": "镶黄", + "level": "THREE_LEVEL", + "geoname_id": 2034017, + "sub_districts": [] + }, + { + "code": "152502", + "name": "锡林浩特", + "level": "THREE_LEVEL", + "geoname_id": 2033823, + "sub_districts": [] + }, + { + "code": "152526", + "name": "西乌珠穆沁", + "level": "THREE_LEVEL", + "geoname_id": 2033607, + "sub_districts": [] + }, + { + "code": "152530", + "name": "正蓝", + "level": "THREE_LEVEL", + "geoname_id": 2033134, + "sub_districts": [] + }, + { + "code": "152529", + "name": "正镶白", + "level": "THREE_LEVEL", + "geoname_id": 2033132, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "64", + "name": "宁夏", + "level": "ONE_LEVEL", + "geoname_id": 1799355, + "sub_districts": [ + { + "code": "640400", + "name": "固原", + "level": "TWO_LEVEL", + "geoname_id": 1809151, + "sub_districts": [ + { + "code": "640424", + "name": "泾源", + "level": "THREE_LEVEL", + "geoname_id": 1805548, + "sub_districts": [] + }, + { + "code": "640423", + "name": "隆德", + "level": "THREE_LEVEL", + "geoname_id": 1802671, + "sub_districts": [] + }, + { + "code": "640425", + "name": "彭阳", + "level": "THREE_LEVEL", + "geoname_id": 1798902, + "sub_districts": [] + }, + { + "code": "640422", + "name": "西吉", + "level": "THREE_LEVEL", + "geoname_id": 640422, + "sub_districts": [] + }, + { + "code": "640402", + "name": "原州", + "level": "THREE_LEVEL", + "geoname_id": 1809150, + "sub_districts": [] + } + ] + }, + { + "code": "640200", + "name": "石嘴山", + "level": "TWO_LEVEL", + "geoname_id": 1794805, + "sub_districts": [ + { + "code": "640202", + "name": "大武口", + "level": "THREE_LEVEL", + "geoname_id": 6643244, + "sub_districts": [] + }, + { + "code": "640205", + "name": "惠农", + "level": "THREE_LEVEL", + "geoname_id": 6643243, + "sub_districts": [] + }, + { + "code": "640221", + "name": "平罗", + "level": "THREE_LEVEL", + "geoname_id": 1798743, + "sub_districts": [] + } + ] + }, + { + "code": "640300", + "name": "吴忠", + "level": "TWO_LEVEL", + "geoname_id": 1786512, + "sub_districts": [ + { + "code": "640303", + "name": "红寺堡", + "level": "THREE_LEVEL", + "geoname_id": 8066511, + "sub_districts": [] + }, + { + "code": "640302", + "name": "利通", + "level": "THREE_LEVEL", + "geoname_id": 1790841, + "sub_districts": [] + }, + { + "code": "640381", + "name": "青铜峡", + "level": "THREE_LEVEL", + "geoname_id": 1797692, + "sub_districts": [] + }, + { + "code": "640324", + "name": "同心", + "level": "THREE_LEVEL", + "geoname_id": 1792542, + "sub_districts": [] + }, + { + "code": "640323", + "name": "盐池", + "level": "THREE_LEVEL", + "geoname_id": 1787736, + "sub_districts": [] + } + ] + }, + { + "code": "640100", + "name": "银川", + "level": "TWO_LEVEL", + "geoname_id": 1786657, + "sub_districts": [ + { + "code": "640122", + "name": "贺兰", + "level": "THREE_LEVEL", + "geoname_id": 1808551, + "sub_districts": [] + }, + { + "code": "640106", + "name": "金凤", + "level": "THREE_LEVEL", + "geoname_id": 6643241, + "sub_districts": [] + }, + { + "code": "640181", + "name": "灵武", + "level": "THREE_LEVEL", + "geoname_id": 1803449, + "sub_districts": [] + }, + { + "code": "640104", + "name": "兴庆", + "level": "THREE_LEVEL", + "geoname_id": 6643242, + "sub_districts": [] + }, + { + "code": "640105", + "name": "西夏", + "level": "THREE_LEVEL", + "geoname_id": 6643240, + "sub_districts": [] + }, + { + "code": "640121", + "name": "永宁", + "level": "THREE_LEVEL", + "geoname_id": 1786280, + "sub_districts": [] + } + ] + }, + { + "code": "640500", + "name": "中卫", + "level": "TWO_LEVEL", + "geoname_id": 6643239, + "sub_districts": [ + { + "code": "640522", + "name": "海原", + "level": "THREE_LEVEL", + "geoname_id": 1809007, + "sub_districts": [] + }, + { + "code": "640502", + "name": "沙坡头", + "level": "THREE_LEVEL", + "geoname_id": 1784284, + "sub_districts": [] + }, + { + "code": "640521", + "name": "中宁", + "level": "THREE_LEVEL", + "geoname_id": 1784343, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "63", + "name": "青海", + "level": "ONE_LEVEL", + "geoname_id": 1280239, + "sub_districts": [ + { + "code": "632600", + "name": "果洛", + "level": "TWO_LEVEL", + "geoname_id": 1281178, + "sub_districts": [ + { + "code": "632622", + "name": "班玛", + "level": "THREE_LEVEL", + "geoname_id": 1817513, + "sub_districts": [] + }, + { + "code": "632624", + "name": "达日", + "level": "THREE_LEVEL", + "geoname_id": 1281407, + "sub_districts": [] + }, + { + "code": "632623", + "name": "甘德", + "level": "THREE_LEVEL", + "geoname_id": 1281265, + "sub_districts": [] + }, + { + "code": "632625", + "name": "久治", + "level": "THREE_LEVEL", + "geoname_id": 1805808, + "sub_districts": [] + }, + { + "code": "632626", + "name": "玛多", + "level": "THREE_LEVEL", + "geoname_id": 1280650, + "sub_districts": [] + }, + { + "code": "632621", + "name": "玛沁", + "level": "THREE_LEVEL", + "geoname_id": 1801093, + "sub_districts": [] + } + ] + }, + { + "code": "632200", + "name": "海北", + "level": "TWO_LEVEL", + "geoname_id": 1809111, + "sub_districts": [ + { + "code": "632224", + "name": "刚察", + "level": "THREE_LEVEL", + "geoname_id": 1810771, + "sub_districts": [] + }, + { + "code": "632223", + "name": "海晏", + "level": "THREE_LEVEL", + "geoname_id": 1809014, + "sub_districts": [] + }, + { + "code": "632221", + "name": "门源", + "level": "THREE_LEVEL", + "geoname_id": 1800654, + "sub_districts": [] + }, + { + "code": "632222", + "name": "祁连", + "level": "THREE_LEVEL", + "geoname_id": 1798012, + "sub_districts": [] + } + ] + }, + { + "code": "630200", + "name": "海东", + "level": "TWO_LEVEL", + "geoname_id": 1809101, + "sub_districts": [ + { + "code": "630224", + "name": "化隆", + "level": "THREE_LEVEL", + "geoname_id": 1807615, + "sub_districts": [] + }, + { + "code": "630223", + "name": "互助", + "level": "THREE_LEVEL", + "geoname_id": 1806531, + "sub_districts": [] + }, + { + "code": "630202", + "name": "乐都", + "level": "THREE_LEVEL", + "geoname_id": 1804249, + "sub_districts": [] + }, + { + "code": "630222", + "name": "民和", + "level": "THREE_LEVEL", + "geoname_id": 1800477, + "sub_districts": [] + }, + { + "code": "630203", + "name": "平安", + "level": "THREE_LEVEL", + "geoname_id": 1798864, + "sub_districts": [] + }, + { + "code": "630225", + "name": "循化", + "level": "THREE_LEVEL", + "geoname_id": 1787896, + "sub_districts": [] + } + ] + }, + { + "code": "632500", + "name": "海南州", + "level": "TWO_LEVEL", + "geoname_id": 1809051, + "sub_districts": [ + { + "code": "632523", + "name": "贵德", + "level": "THREE_LEVEL", + "geoname_id": 1809527, + "sub_districts": [] + }, + { + "code": "632521", + "name": "共和", + "level": "THREE_LEVEL", + "geoname_id": 1810130, + "sub_districts": [] + }, + { + "code": "632525", + "name": "贵南", + "level": "THREE_LEVEL", + "geoname_id": 1809487, + "sub_districts": [] + }, + { + "code": "632522", + "name": "同德", + "level": "THREE_LEVEL", + "geoname_id": 1792688, + "sub_districts": [] + }, + { + "code": "632524", + "name": "兴海", + "level": "THREE_LEVEL", + "geoname_id": 1789027, + "sub_districts": [] + } + ] + }, + { + "code": "632300", + "name": "黄南", + "level": "TWO_LEVEL", + "geoname_id": 1807329, + "sub_districts": [ + { + "code": "632324", + "name": "河南", + "level": "THREE_LEVEL", + "geoname_id": 1808521, + "sub_districts": [] + }, + { + "code": "632322", + "name": "尖扎", + "level": "THREE_LEVEL", + "geoname_id": 1806525, + "sub_districts": [] + }, + { + "code": "6323010000001", + "name": "同仁", + "level": "THREE_LEVEL", + "geoname_id": 1792589, + "sub_districts": [] + }, + { + "code": "632323", + "name": "泽库", + "level": "THREE_LEVEL", + "geoname_id": 1785440, + "sub_districts": [] + } + ] + }, + { + "code": "632800", + "name": "海西", + "level": "TWO_LEVEL", + "geoname_id": 1281075, + "sub_districts": [ + { + "code": "632857", + "name": "大柴旦", + "level": "THREE_LEVEL", + "geoname_id": 632857, + "sub_districts": [] + }, + { + "code": "632802", + "name": "德令哈", + "level": "THREE_LEVEL", + "geoname_id": 6643155, + "sub_districts": [] + }, + { + "code": "632822", + "name": "都兰", + "level": "THREE_LEVEL", + "geoname_id": 1281290, + "sub_districts": [] + }, + { + "code": "632801", + "name": "格尔木", + "level": "THREE_LEVEL", + "geoname_id": 1281181, + "sub_districts": [] + }, + { + "code": "632803", + "name": "茫崖", + "level": "THREE_LEVEL", + "geoname_id": 8074301, + "sub_districts": [] + }, + { + "code": "632823", + "name": "天峻", + "level": "THREE_LEVEL", + "geoname_id": 1279885, + "sub_districts": [] + }, + { + "code": "632821", + "name": "乌兰", + "level": "THREE_LEVEL", + "geoname_id": 1279831, + "sub_districts": [] + } + ] + }, + { + "code": "630100", + "name": "西宁", + "level": "TWO_LEVEL", + "geoname_id": 1788852, + "sub_districts": [ + { + "code": "630105", + "name": "城北", + "level": "THREE_LEVEL", + "geoname_id": 6643150, + "sub_districts": [] + }, + { + "code": "630102", + "name": "城东", + "level": "THREE_LEVEL", + "geoname_id": 6643153, + "sub_districts": [] + }, + { + "code": "630104", + "name": "城西", + "level": "THREE_LEVEL", + "geoname_id": 6643151, + "sub_districts": [] + }, + { + "code": "630103", + "name": "城中", + "level": "THREE_LEVEL", + "geoname_id": 6643152, + "sub_districts": [] + }, + { + "code": "630121", + "name": "大通", + "level": "THREE_LEVEL", + "geoname_id": 1813441, + "sub_districts": [] + }, + { + "code": "630123", + "name": "湟源", + "level": "THREE_LEVEL", + "geoname_id": 1807127, + "sub_districts": [] + }, + { + "code": "6301060000001", + "name": "湟中", + "level": "THREE_LEVEL", + "geoname_id": 1807113, + "sub_districts": [] + } + ] + }, + { + "code": "632700", + "name": "玉树", + "level": "TWO_LEVEL", + "geoname_id": 1279540, + "sub_districts": [ + { + "code": "632723", + "name": "称多", + "level": "THREE_LEVEL", + "geoname_id": 1281521, + "sub_districts": [] + }, + { + "code": "632725", + "name": "囊谦", + "level": "THREE_LEVEL", + "geoname_id": 1280488, + "sub_districts": [] + }, + { + "code": "632726", + "name": "曲麻莱", + "level": "THREE_LEVEL", + "geoname_id": 1280200, + "sub_districts": [] + }, + { + "code": "632701", + "name": "玉树", + "level": "THREE_LEVEL", + "geoname_id": 1279541, + "sub_districts": [] + }, + { + "code": "632722", + "name": "杂多", + "level": "THREE_LEVEL", + "geoname_id": 1279535, + "sub_districts": [] + }, + { + "code": "632724", + "name": "治多", + "level": "THREE_LEVEL", + "geoname_id": 1279466, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "51", + "name": "四川", + "level": "ONE_LEVEL", + "geoname_id": 1794299, + "sub_districts": [ + { + "code": "513200", + "name": "阿坝", + "level": "TWO_LEVEL", + "geoname_id": 1818175, + "sub_districts": [ + { + "code": "513231", + "name": "阿坝", + "level": "THREE_LEVEL", + "geoname_id": 1818176, + "sub_districts": [] + }, + { + "code": "513228", + "name": "黑水", + "level": "THREE_LEVEL", + "geoname_id": 1808646, + "sub_districts": [] + }, + { + "code": "513233", + "name": "红原", + "level": "THREE_LEVEL", + "geoname_id": 1807922, + "sub_districts": [] + }, + { + "code": "513226", + "name": "金川", + "level": "THREE_LEVEL", + "geoname_id": 1805731, + "sub_districts": [] + }, + { + "code": "513225", + "name": "九寨沟", + "level": "THREE_LEVEL", + "geoname_id": 1799836, + "sub_districts": [] + }, + { + "code": "513222", + "name": "理县", + "level": "THREE_LEVEL", + "geoname_id": 1802816, + "sub_districts": [] + }, + { + "code": "513201", + "name": "马尔康", + "level": "THREE_LEVEL", + "geoname_id": 10200107, + "sub_districts": [] + }, + { + "code": "513223", + "name": "茂县", + "level": "THREE_LEVEL", + "geoname_id": 1801130, + "sub_districts": [] + }, + { + "code": "513232", + "name": "若尔盖", + "level": "THREE_LEVEL", + "geoname_id": 1783665, + "sub_districts": [] + }, + { + "code": "513230", + "name": "壤塘", + "level": "THREE_LEVEL", + "geoname_id": 1785513, + "sub_districts": [] + }, + { + "code": "513224", + "name": "松潘", + "level": "THREE_LEVEL", + "geoname_id": 1793997, + "sub_districts": [] + }, + { + "code": "513221", + "name": "汶川", + "level": "THREE_LEVEL", + "geoname_id": 1791528, + "sub_districts": [] + }, + { + "code": "513227", + "name": "小金", + "level": "THREE_LEVEL", + "geoname_id": 1790120, + "sub_districts": [] + } + ] + }, + { + "code": "511900", + "name": "巴中", + "level": "TWO_LEVEL", + "geoname_id": 6643375, + "sub_districts": [ + { + "code": "511902", + "name": "巴州", + "level": "THREE_LEVEL", + "geoname_id": 1816808, + "sub_districts": [] + }, + { + "code": "511903", + "name": "恩阳", + "level": "THREE_LEVEL", + "geoname_id": 1811718, + "sub_districts": [] + }, + { + "code": "511922", + "name": "南江", + "level": "THREE_LEVEL", + "geoname_id": 1799979, + "sub_districts": [] + }, + { + "code": "511923", + "name": "平昌", + "level": "THREE_LEVEL", + "geoname_id": 1798852, + "sub_districts": [] + }, + { + "code": "511921", + "name": "通江", + "level": "THREE_LEVEL", + "geoname_id": 1792643, + "sub_districts": [] + } + ] + }, + { + "code": "510100", + "name": "成都", + "level": "TWO_LEVEL", + "geoname_id": 1815286, + "sub_districts": [ + { + "code": "510108", + "name": "成华", + "level": "THREE_LEVEL", + "geoname_id": 6642924, + "sub_districts": [] + }, + { + "code": "510184", + "name": "崇州", + "level": "THREE_LEVEL", + "geoname_id": 1814903, + "sub_districts": [] + }, + { + "code": "510181", + "name": "都江堰", + "level": "THREE_LEVEL", + "geoname_id": 1809831, + "sub_districts": [] + }, + { + "code": "510129", + "name": "大邑", + "level": "THREE_LEVEL", + "geoname_id": 1813176, + "sub_districts": [] + }, + { + "code": "510104", + "name": "锦江", + "level": "THREE_LEVEL", + "geoname_id": 6642922, + "sub_districts": [] + }, + { + "code": "510106", + "name": "金牛", + "level": "THREE_LEVEL", + "geoname_id": 6642918, + "sub_districts": [] + }, + { + "code": "510121", + "name": "金堂", + "level": "THREE_LEVEL", + "geoname_id": 1805352, + "sub_districts": [] + }, + { + "code": "510185", + "name": "简阳", + "level": "THREE_LEVEL", + "geoname_id": 1806119, + "sub_districts": [] + }, + { + "code": "510112", + "name": "龙泉驿", + "level": "THREE_LEVEL", + "geoname_id": 6642925, + "sub_districts": [] + }, + { + "code": "5101170000001", + "name": "郫都", + "level": "THREE_LEVEL", + "geoname_id": 510124, + "sub_districts": [] + }, + { + "code": "510131", + "name": "蒲江", + "level": "THREE_LEVEL", + "geoname_id": 1798496, + "sub_districts": [] + }, + { + "code": "510182", + "name": "彭州", + "level": "THREE_LEVEL", + "geoname_id": 1798906, + "sub_districts": [] + }, + { + "code": "510113", + "name": "青白江", + "level": "THREE_LEVEL", + "geoname_id": 6642931, + "sub_districts": [] + }, + { + "code": "510183", + "name": "邛崃", + "level": "THREE_LEVEL", + "geoname_id": 1797540, + "sub_districts": [] + }, + { + "code": "510105", + "name": "青羊", + "level": "THREE_LEVEL", + "geoname_id": 6642920, + "sub_districts": [] + }, + { + "code": "510116", + "name": "双流", + "level": "THREE_LEVEL", + "geoname_id": 1794651, + "sub_districts": [] + }, + { + "code": "510107", + "name": "武侯", + "level": "THREE_LEVEL", + "geoname_id": 6642917, + "sub_districts": [] + }, + { + "code": "510115", + "name": "温江", + "level": "THREE_LEVEL", + "geoname_id": 1791482, + "sub_districts": [] + }, + { + "code": "510114", + "name": "新都", + "level": "THREE_LEVEL", + "geoname_id": 1789091, + "sub_districts": [] + }, + { + "code": "5101180000001", + "name": "新津", + "level": "THREE_LEVEL", + "geoname_id": 1788768, + "sub_districts": [] + } + ] + }, + { + "code": "510600", + "name": "德阳", + "level": "TWO_LEVEL", + "geoname_id": 1812961, + "sub_districts": [ + { + "code": "510681", + "name": "广汉", + "level": "THREE_LEVEL", + "geoname_id": 510681, + "sub_districts": [] + }, + { + "code": "510603", + "name": "旌阳", + "level": "THREE_LEVEL", + "geoname_id": 1812960, + "sub_districts": [] + }, + { + "code": "5106040000001", + "name": "罗江", + "level": "THREE_LEVEL", + "geoname_id": 6642948, + "sub_districts": [] + }, + { + "code": "510683", + "name": "绵竹", + "level": "THREE_LEVEL", + "geoname_id": 1800623, + "sub_districts": [] + }, + { + "code": "510682", + "name": "什邡", + "level": "THREE_LEVEL", + "geoname_id": 1795399, + "sub_districts": [] + }, + { + "code": "510623", + "name": "中江", + "level": "THREE_LEVEL", + "geoname_id": 1784372, + "sub_districts": [] + } + ] + }, + { + "code": "511700", + "name": "达州", + "level": "TWO_LEVEL", + "geoname_id": 1813325, + "sub_districts": [ + { + "code": "511703", + "name": "达川", + "level": "THREE_LEVEL", + "geoname_id": 511703, + "sub_districts": [] + }, + { + "code": "511724", + "name": "大竹", + "level": "THREE_LEVEL", + "geoname_id": 1813059, + "sub_districts": [] + }, + { + "code": "511723", + "name": "开江", + "level": "THREE_LEVEL", + "geoname_id": 1804868, + "sub_districts": [] + }, + { + "code": "511725", + "name": "渠县", + "level": "THREE_LEVEL", + "geoname_id": 1797277, + "sub_districts": [] + }, + { + "code": "511702", + "name": "通川", + "level": "THREE_LEVEL", + "geoname_id": 1813320, + "sub_districts": [] + }, + { + "code": "511781", + "name": "万源", + "level": "THREE_LEVEL", + "geoname_id": 1791738, + "sub_districts": [] + }, + { + "code": "511722", + "name": "宣汉", + "level": "THREE_LEVEL", + "geoname_id": 1788072, + "sub_districts": [] + } + ] + }, + { + "code": "511600", + "name": "广安", + "level": "TWO_LEVEL", + "geoname_id": 6643373, + "sub_districts": [ + { + "code": "511602", + "name": "广安", + "level": "THREE_LEVEL", + "geoname_id": 1809946, + "sub_districts": [] + }, + { + "code": "511681", + "name": "华蓥", + "level": "THREE_LEVEL", + "geoname_id": 1806983, + "sub_districts": [] + }, + { + "code": "511623", + "name": "邻水", + "level": "THREE_LEVEL", + "geoname_id": 1803351, + "sub_districts": [] + }, + { + "code": "511603", + "name": "前锋", + "level": "THREE_LEVEL", + "geoname_id": 9640804, + "sub_districts": [] + }, + { + "code": "511622", + "name": "武胜", + "level": "THREE_LEVEL", + "geoname_id": 1790996, + "sub_districts": [] + }, + { + "code": "511621", + "name": "岳池", + "level": "THREE_LEVEL", + "geoname_id": 1785945, + "sub_districts": [] + } + ] + }, + { + "code": "510800", + "name": "广元", + "level": "TWO_LEVEL", + "geoname_id": 1806466, + "sub_districts": [ + { + "code": "510812", + "name": "朝天", + "level": "THREE_LEVEL", + "geoname_id": 6642908, + "sub_districts": [] + }, + { + "code": "510824", + "name": "苍溪", + "level": "THREE_LEVEL", + "geoname_id": 1816082, + "sub_districts": [] + }, + { + "code": "510823", + "name": "剑阁", + "level": "THREE_LEVEL", + "geoname_id": 1806385, + "sub_districts": [] + }, + { + "code": "510802", + "name": "利州", + "level": "THREE_LEVEL", + "geoname_id": 7925035, + "sub_districts": [] + }, + { + "code": "510822", + "name": "青川", + "level": "THREE_LEVEL", + "geoname_id": 1797935, + "sub_districts": [] + }, + { + "code": "510821", + "name": "旺苍", + "level": "THREE_LEVEL", + "geoname_id": 1792162, + "sub_districts": [] + }, + { + "code": "510811", + "name": "昭化", + "level": "THREE_LEVEL", + "geoname_id": 1784914, + "sub_districts": [] + } + ] + }, + { + "code": "513300", + "name": "甘孜", + "level": "TWO_LEVEL", + "geoname_id": 1810269, + "sub_districts": [ + { + "code": "513335", + "name": "巴塘", + "level": "THREE_LEVEL", + "geoname_id": 1281661, + "sub_districts": [] + }, + { + "code": "513331", + "name": "白玉", + "level": "THREE_LEVEL", + "geoname_id": 1281695, + "sub_districts": [] + }, + { + "code": "513323", + "name": "丹巴", + "level": "THREE_LEVEL", + "geoname_id": 1813896, + "sub_districts": [] + }, + { + "code": "513337", + "name": "稻城", + "level": "THREE_LEVEL", + "geoname_id": 1813787, + "sub_districts": [] + }, + { + "code": "513326", + "name": "道孚", + "level": "THREE_LEVEL", + "geoname_id": 1813340, + "sub_districts": [] + }, + { + "code": "513330", + "name": "德格", + "level": "THREE_LEVEL", + "geoname_id": 1281383, + "sub_districts": [] + }, + { + "code": "513338", + "name": "得荣", + "level": "THREE_LEVEL", + "geoname_id": 1281361, + "sub_districts": [] + }, + { + "code": "513328", + "name": "甘孜", + "level": "THREE_LEVEL", + "geoname_id": 1810270, + "sub_districts": [] + }, + { + "code": "513324", + "name": "九龙", + "level": "THREE_LEVEL", + "geoname_id": 1805133, + "sub_districts": [] + }, + { + "code": "513301", + "name": "康定", + "level": "THREE_LEVEL", + "geoname_id": 1804839, + "sub_districts": [] + }, + { + "code": "513322", + "name": "泸定", + "level": "THREE_LEVEL", + "geoname_id": 1802142, + "sub_districts": [] + }, + { + "code": "513327", + "name": "炉霍", + "level": "THREE_LEVEL", + "geoname_id": 1802087, + "sub_districts": [] + }, + { + "code": "513334", + "name": "理塘", + "level": "THREE_LEVEL", + "geoname_id": 1803228, + "sub_districts": [] + }, + { + "code": "513333", + "name": "色达", + "level": "THREE_LEVEL", + "geoname_id": 1796483, + "sub_districts": [] + }, + { + "code": "513332", + "name": "石渠", + "level": "THREE_LEVEL", + "geoname_id": 1280040, + "sub_districts": [] + }, + { + "code": "513336", + "name": "乡城", + "level": "THREE_LEVEL", + "geoname_id": 1279737, + "sub_districts": [] + }, + { + "code": "513329", + "name": "新龙", + "level": "THREE_LEVEL", + "geoname_id": 1788737, + "sub_districts": [] + }, + { + "code": "513325", + "name": "雅江", + "level": "THREE_LEVEL", + "geoname_id": 1787784, + "sub_districts": [] + } + ] + }, + { + "code": "511100", + "name": "乐山", + "level": "TWO_LEVEL", + "geoname_id": 1804153, + "sub_districts": [ + { + "code": "511132", + "name": "峨边", + "level": "THREE_LEVEL", + "geoname_id": 1811752, + "sub_districts": [] + }, + { + "code": "511181", + "name": "峨眉山", + "level": "THREE_LEVEL", + "geoname_id": 1811732, + "sub_districts": [] + }, + { + "code": "511126", + "name": "夹江", + "level": "THREE_LEVEL", + "geoname_id": 1806482, + "sub_districts": [] + }, + { + "code": "511113", + "name": "金口河", + "level": "THREE_LEVEL", + "geoname_id": 6642894, + "sub_districts": [] + }, + { + "code": "511124", + "name": "井研", + "level": "THREE_LEVEL", + "geoname_id": 1805554, + "sub_districts": [] + }, + { + "code": "511133", + "name": "马边", + "level": "THREE_LEVEL", + "geoname_id": 1801606, + "sub_districts": [] + }, + { + "code": "511129", + "name": "沐川", + "level": "THREE_LEVEL", + "geoname_id": 1800339, + "sub_districts": [] + }, + { + "code": "511123", + "name": "犍为", + "level": "THREE_LEVEL", + "geoname_id": 1798232, + "sub_districts": [] + }, + { + "code": "511111", + "name": "沙湾", + "level": "THREE_LEVEL", + "geoname_id": 6642895, + "sub_districts": [] + }, + { + "code": "511102", + "name": "市中", + "level": "THREE_LEVEL", + "geoname_id": 1809862, + "sub_districts": [] + }, + { + "code": "511112", + "name": "五通桥", + "level": "THREE_LEVEL", + "geoname_id": 6642897, + "sub_districts": [] + } + ] + }, + { + "code": "513400", + "name": "凉山", + "level": "TWO_LEVEL", + "geoname_id": 1803984, + "sub_districts": [ + { + "code": "513429", + "name": "布拖", + "level": "THREE_LEVEL", + "geoname_id": 1816199, + "sub_districts": [] + }, + { + "code": "513424", + "name": "德昌", + "level": "THREE_LEVEL", + "geoname_id": 1813036, + "sub_districts": [] + }, + { + "code": "513435", + "name": "甘洛", + "level": "THREE_LEVEL", + "geoname_id": 1810688, + "sub_districts": [] + }, + { + "code": "513426", + "name": "会东", + "level": "THREE_LEVEL", + "geoname_id": 1806873, + "sub_districts": [] + }, + { + "code": "5134020000001", + "name": "会理", + "level": "THREE_LEVEL", + "geoname_id": 1806848, + "sub_districts": [] + }, + { + "code": "513430", + "name": "金阳", + "level": "THREE_LEVEL", + "geoname_id": 1805317, + "sub_districts": [] + }, + { + "code": "513437", + "name": "雷波", + "level": "THREE_LEVEL", + "geoname_id": 1804245, + "sub_districts": [] + }, + { + "code": "513436", + "name": "美姑", + "level": "THREE_LEVEL", + "geoname_id": 1800865, + "sub_districts": [] + }, + { + "code": "513422", + "name": "木里", + "level": "THREE_LEVEL", + "geoname_id": 1800288, + "sub_districts": [] + }, + { + "code": "513433", + "name": "冕宁", + "level": "THREE_LEVEL", + "geoname_id": 1800635, + "sub_districts": [] + }, + { + "code": "513427", + "name": "宁南", + "level": "THREE_LEVEL", + "geoname_id": 1799363, + "sub_districts": [] + }, + { + "code": "513428", + "name": "普格", + "level": "THREE_LEVEL", + "geoname_id": 1798517, + "sub_districts": [] + }, + { + "code": "513401", + "name": "西昌", + "level": "THREE_LEVEL", + "geoname_id": 1789645, + "sub_districts": [] + }, + { + "code": "513432", + "name": "喜德", + "level": "THREE_LEVEL", + "geoname_id": 1789602, + "sub_districts": [] + }, + { + "code": "513434", + "name": "越西", + "level": "THREE_LEVEL", + "geoname_id": 1785888, + "sub_districts": [] + }, + { + "code": "513423", + "name": "盐源", + "level": "THREE_LEVEL", + "geoname_id": 1787039, + "sub_districts": [] + }, + { + "code": "513431", + "name": "昭觉", + "level": "THREE_LEVEL", + "geoname_id": 1784875, + "sub_districts": [] + } + ] + }, + { + "code": "510500", + "name": "泸州", + "level": "TWO_LEVEL", + "geoname_id": 1801637, + "sub_districts": [ + { + "code": "510525", + "name": "古蔺", + "level": "THREE_LEVEL", + "geoname_id": 1809403, + "sub_districts": [] + }, + { + "code": "510522", + "name": "合江", + "level": "THREE_LEVEL", + "geoname_id": 1808609, + "sub_districts": [] + }, + { + "code": "510502", + "name": "江阳", + "level": "THREE_LEVEL", + "geoname_id": 6642903, + "sub_districts": [] + }, + { + "code": "510504", + "name": "龙马潭", + "level": "THREE_LEVEL", + "geoname_id": 6642904, + "sub_districts": [] + }, + { + "code": "510521", + "name": "泸县", + "level": "THREE_LEVEL", + "geoname_id": 1801683, + "sub_districts": [] + }, + { + "code": "510503", + "name": "纳溪", + "level": "THREE_LEVEL", + "geoname_id": 1799506, + "sub_districts": [] + }, + { + "code": "510524", + "name": "叙永", + "level": "THREE_LEVEL", + "geoname_id": 1787827, + "sub_districts": [] + } + ] + }, + { + "code": "511400", + "name": "眉山", + "level": "TWO_LEVEL", + "geoname_id": 1800818, + "sub_districts": [ + { + "code": "511424", + "name": "丹棱", + "level": "THREE_LEVEL", + "geoname_id": 1813819, + "sub_districts": [] + }, + { + "code": "511402", + "name": "东坡", + "level": "THREE_LEVEL", + "geoname_id": 1800811, + "sub_districts": [] + }, + { + "code": "511423", + "name": "洪雅", + "level": "THREE_LEVEL", + "geoname_id": 1807928, + "sub_districts": [] + }, + { + "code": "511403", + "name": "彭山", + "level": "THREE_LEVEL", + "geoname_id": 1798916, + "sub_districts": [] + }, + { + "code": "511425", + "name": "青神", + "level": "THREE_LEVEL", + "geoname_id": 1797760, + "sub_districts": [] + }, + { + "code": "511421", + "name": "仁寿", + "level": "THREE_LEVEL", + "geoname_id": 1797176, + "sub_districts": [] + } + ] + }, + { + "code": "510700", + "name": "绵阳", + "level": "TWO_LEVEL", + "geoname_id": 1800627, + "sub_districts": [ + { + "code": "510705", + "name": "安州", + "level": "THREE_LEVEL", + "geoname_id": 510705, + "sub_districts": [] + }, + { + "code": "510726", + "name": "北川", + "level": "THREE_LEVEL", + "geoname_id": 1816762, + "sub_districts": [] + }, + { + "code": "510703", + "name": "涪城", + "level": "THREE_LEVEL", + "geoname_id": 6642911, + "sub_districts": [] + }, + { + "code": "510781", + "name": "江油", + "level": "THREE_LEVEL", + "geoname_id": 1806207, + "sub_districts": [] + }, + { + "code": "510727", + "name": "平武", + "level": "THREE_LEVEL", + "geoname_id": 1798664, + "sub_districts": [] + }, + { + "code": "510722", + "name": "三台", + "level": "THREE_LEVEL", + "geoname_id": 1796597, + "sub_districts": [] + }, + { + "code": "510723", + "name": "盐亭", + "level": "THREE_LEVEL", + "geoname_id": 1787069, + "sub_districts": [] + }, + { + "code": "510704", + "name": "游仙", + "level": "THREE_LEVEL", + "geoname_id": 6642910, + "sub_districts": [] + }, + { + "code": "510725", + "name": "梓潼", + "level": "THREE_LEVEL", + "geoname_id": 1783697, + "sub_districts": [] + } + ] + }, + { + "code": "511300", + "name": "南充", + "level": "TWO_LEVEL", + "geoname_id": 1800146, + "sub_districts": [ + { + "code": "511303", + "name": "高坪", + "level": "THREE_LEVEL", + "geoname_id": 6642907, + "sub_districts": [] + }, + { + "code": "511304", + "name": "嘉陵", + "level": "THREE_LEVEL", + "geoname_id": 1800144, + "sub_districts": [] + }, + { + "code": "511381", + "name": "阆中", + "level": "THREE_LEVEL", + "geoname_id": 1804485, + "sub_districts": [] + }, + { + "code": "511321", + "name": "南部", + "level": "THREE_LEVEL", + "geoname_id": 1800173, + "sub_districts": [] + }, + { + "code": "511323", + "name": "蓬安", + "level": "THREE_LEVEL", + "geoname_id": 1798948, + "sub_districts": [] + }, + { + "code": "511302", + "name": "顺庆", + "level": "THREE_LEVEL", + "geoname_id": 1800143, + "sub_districts": [] + }, + { + "code": "511325", + "name": "西充", + "level": "THREE_LEVEL", + "geoname_id": 1789629, + "sub_districts": [] + }, + { + "code": "511324", + "name": "仪陇", + "level": "THREE_LEVEL", + "geoname_id": 1786680, + "sub_districts": [] + }, + { + "code": "511322", + "name": "营山", + "level": "THREE_LEVEL", + "geoname_id": 1786583, + "sub_districts": [] + } + ] + }, + { + "code": "511000", + "name": "内江", + "level": "TWO_LEVEL", + "geoname_id": 1799491, + "sub_districts": [ + { + "code": "511011", + "name": "东兴", + "level": "THREE_LEVEL", + "geoname_id": 1799489, + "sub_districts": [] + }, + { + "code": "5110830000001", + "name": "隆昌", + "level": "THREE_LEVEL", + "geoname_id": 1802690, + "sub_districts": [] + }, + { + "code": "511002", + "name": "市中", + "level": "THREE_LEVEL", + "geoname_id": 6642902, + "sub_districts": [] + }, + { + "code": "511024", + "name": "威远", + "level": "THREE_LEVEL", + "geoname_id": 1791571, + "sub_districts": [] + }, + { + "code": "511025", + "name": "资中", + "level": "THREE_LEVEL", + "geoname_id": 1783668, + "sub_districts": [] + } + ] + }, + { + "code": "510400", + "name": "攀枝花", + "level": "TWO_LEVEL", + "geoname_id": 1798997, + "sub_districts": [ + { + "code": "510402", + "name": "东区", + "level": "THREE_LEVEL", + "geoname_id": 6642891, + "sub_districts": [] + }, + { + "code": "510421", + "name": "米易", + "level": "THREE_LEVEL", + "geoname_id": 1800429, + "sub_districts": [] + }, + { + "code": "510411", + "name": "仁和", + "level": "THREE_LEVEL", + "geoname_id": 6642889, + "sub_districts": [] + }, + { + "code": "510403", + "name": "西区", + "level": "THREE_LEVEL", + "geoname_id": 6642888, + "sub_districts": [] + }, + { + "code": "510422", + "name": "盐边", + "level": "THREE_LEVEL", + "geoname_id": 1787759, + "sub_districts": [] + } + ] + }, + { + "code": "510900", + "name": "遂宁", + "level": "TWO_LEVEL", + "geoname_id": 6643374, + "sub_districts": [ + { + "code": "510904", + "name": "安居", + "level": "THREE_LEVEL", + "geoname_id": 6642905, + "sub_districts": [] + }, + { + "code": "510903", + "name": "船山", + "level": "THREE_LEVEL", + "geoname_id": 1793898, + "sub_districts": [] + }, + { + "code": "510923", + "name": "大英", + "level": "THREE_LEVEL", + "geoname_id": 6642906, + "sub_districts": [] + }, + { + "code": "510921", + "name": "蓬溪", + "level": "THREE_LEVEL", + "geoname_id": 1798904, + "sub_districts": [] + }, + { + "code": "5109810000001", + "name": "射洪", + "level": "THREE_LEVEL", + "geoname_id": 1795715, + "sub_districts": [] + } + ] + }, + { + "code": "511800", + "name": "雅安", + "level": "TWO_LEVEL", + "geoname_id": 1787815, + "sub_districts": [ + { + "code": "511827", + "name": "宝兴", + "level": "THREE_LEVEL", + "geoname_id": 1816898, + "sub_districts": [] + }, + { + "code": "511823", + "name": "汉源", + "level": "THREE_LEVEL", + "geoname_id": 1808860, + "sub_districts": [] + }, + { + "code": "511826", + "name": "芦山", + "level": "THREE_LEVEL", + "geoname_id": 1801737, + "sub_districts": [] + }, + { + "code": "511803", + "name": "名山", + "level": "THREE_LEVEL", + "geoname_id": 1800500, + "sub_districts": [] + }, + { + "code": "511824", + "name": "石棉", + "level": "THREE_LEVEL", + "geoname_id": 1795102, + "sub_districts": [] + }, + { + "code": "511825", + "name": "天全", + "level": "THREE_LEVEL", + "geoname_id": 1792904, + "sub_districts": [] + }, + { + "code": "511802", + "name": "雨城", + "level": "THREE_LEVEL", + "geoname_id": 1787814, + "sub_districts": [] + }, + { + "code": "511822", + "name": "荥经", + "level": "THREE_LEVEL", + "geoname_id": 1786611, + "sub_districts": [] + } + ] + }, + { + "code": "511500", + "name": "宜宾", + "level": "TWO_LEVEL", + "geoname_id": 1786770, + "sub_districts": [ + { + "code": "511524", + "name": "长宁", + "level": "THREE_LEVEL", + "geoname_id": 1815607, + "sub_districts": [] + }, + { + "code": "511502", + "name": "翠屏", + "level": "THREE_LEVEL", + "geoname_id": 1786768, + "sub_districts": [] + }, + { + "code": "511525", + "name": "高县", + "level": "THREE_LEVEL", + "geoname_id": 1810340, + "sub_districts": [] + }, + { + "code": "511526", + "name": "珙县", + "level": "THREE_LEVEL", + "geoname_id": 1810079, + "sub_districts": [] + }, + { + "code": "511523", + "name": "江安", + "level": "THREE_LEVEL", + "geoname_id": 1806417, + "sub_districts": [] + }, + { + "code": "511527", + "name": "筠连", + "level": "THREE_LEVEL", + "geoname_id": 1804933, + "sub_districts": [] + }, + { + "code": "511503", + "name": "南溪", + "level": "THREE_LEVEL", + "geoname_id": 1799645, + "sub_districts": [] + }, + { + "code": "511529", + "name": "屏山", + "level": "THREE_LEVEL", + "geoname_id": 1798699, + "sub_districts": [] + }, + { + "code": "511528", + "name": "兴文", + "level": "THREE_LEVEL", + "geoname_id": 1788914, + "sub_districts": [] + }, + { + "code": "5115040000001", + "name": "叙州", + "level": "THREE_LEVEL", + "geoname_id": 511521, + "sub_districts": [] + } + ] + }, + { + "code": "510300", + "name": "自贡", + "level": "TWO_LEVEL", + "geoname_id": 1783745, + "sub_districts": [ + { + "code": "510304", + "name": "大安", + "level": "THREE_LEVEL", + "geoname_id": 6642898, + "sub_districts": [] + }, + { + "code": "510322", + "name": "富顺", + "level": "THREE_LEVEL", + "geoname_id": 1810901, + "sub_districts": [] + }, + { + "code": "510303", + "name": "贡井", + "level": "THREE_LEVEL", + "geoname_id": 6642901, + "sub_districts": [] + }, + { + "code": "510321", + "name": "荣县", + "level": "THREE_LEVEL", + "geoname_id": 1797087, + "sub_districts": [] + }, + { + "code": "510311", + "name": "沿滩", + "level": "THREE_LEVEL", + "geoname_id": 6642900, + "sub_districts": [] + }, + { + "code": "510302", + "name": "自流井", + "level": "THREE_LEVEL", + "geoname_id": 6642899, + "sub_districts": [] + } + ] + }, + { + "code": "512000", + "name": "资阳", + "level": "TWO_LEVEL", + "geoname_id": 8594180, + "sub_districts": [ + { + "code": "512021", + "name": "安岳", + "level": "THREE_LEVEL", + "geoname_id": 1817929, + "sub_districts": [] + }, + { + "code": "512022", + "name": "乐至", + "level": "THREE_LEVEL", + "geoname_id": 1804128, + "sub_districts": [] + }, + { + "code": "512002", + "name": "雁江", + "level": "THREE_LEVEL", + "geoname_id": 1783680, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "37", + "name": "山东", + "level": "ONE_LEVEL", + "geoname_id": 1796328, + "sub_districts": [ + { + "code": "371600", + "name": "滨州", + "level": "TWO_LEVEL", + "geoname_id": 1816336, + "sub_districts": [ + { + "code": "371602", + "name": "滨城", + "level": "THREE_LEVEL", + "geoname_id": 1816341, + "sub_districts": [] + }, + { + "code": "371625", + "name": "博兴", + "level": "THREE_LEVEL", + "geoname_id": 1816250, + "sub_districts": [] + }, + { + "code": "371621", + "name": "惠民", + "level": "THREE_LEVEL", + "geoname_id": 1806822, + "sub_districts": [] + }, + { + "code": "371623", + "name": "无棣", + "level": "THREE_LEVEL", + "geoname_id": 1791301, + "sub_districts": [] + }, + { + "code": "371622", + "name": "阳信", + "level": "THREE_LEVEL", + "geoname_id": 1787259, + "sub_districts": [] + }, + { + "code": "371603", + "name": "沾化", + "level": "THREE_LEVEL", + "geoname_id": 1784993, + "sub_districts": [] + }, + { + "code": "3716810000001", + "name": "邹平", + "level": "THREE_LEVEL", + "geoname_id": 1783640, + "sub_districts": [] + } + ] + }, + { + "code": "370500", + "name": "东营", + "level": "TWO_LEVEL", + "geoname_id": 1812101, + "sub_districts": [ + { + "code": "370502", + "name": "东营", + "level": "THREE_LEVEL", + "geoname_id": 6573958, + "sub_districts": [] + }, + { + "code": "370523", + "name": "广饶", + "level": "THREE_LEVEL", + "geoname_id": 1809882, + "sub_districts": [] + }, + { + "code": "370503", + "name": "河口", + "level": "THREE_LEVEL", + "geoname_id": 6573959, + "sub_districts": [] + }, + { + "code": "370505", + "name": "垦利", + "level": "THREE_LEVEL", + "geoname_id": 1804755, + "sub_districts": [] + }, + { + "code": "370522", + "name": "利津", + "level": "THREE_LEVEL", + "geoname_id": 1803630, + "sub_districts": [] + } + ] + }, + { + "code": "371400", + "name": "德州", + "level": "TWO_LEVEL", + "geoname_id": 1812955, + "sub_districts": [ + { + "code": "371402", + "name": "德城", + "level": "THREE_LEVEL", + "geoname_id": 6573957, + "sub_districts": [] + }, + { + "code": "371403", + "name": "陵城", + "level": "THREE_LEVEL", + "geoname_id": 1803437, + "sub_districts": [] + }, + { + "code": "371481", + "name": "乐陵", + "level": "THREE_LEVEL", + "geoname_id": 1804194, + "sub_districts": [] + }, + { + "code": "371424", + "name": "临邑", + "level": "THREE_LEVEL", + "geoname_id": 1803311, + "sub_districts": [] + }, + { + "code": "371422", + "name": "宁津", + "level": "THREE_LEVEL", + "geoname_id": 1799371, + "sub_districts": [] + }, + { + "code": "371426", + "name": "平原", + "level": "THREE_LEVEL", + "geoname_id": 1798620, + "sub_districts": [] + }, + { + "code": "371425", + "name": "齐河", + "level": "THREE_LEVEL", + "geoname_id": 1798048, + "sub_districts": [] + }, + { + "code": "371423", + "name": "庆云", + "level": "THREE_LEVEL", + "geoname_id": 1797614, + "sub_districts": [] + }, + { + "code": "371428", + "name": "武城", + "level": "THREE_LEVEL", + "geoname_id": 1791338, + "sub_districts": [] + }, + { + "code": "371427", + "name": "夏津", + "level": "THREE_LEVEL", + "geoname_id": 1790687, + "sub_districts": [] + }, + { + "code": "371482", + "name": "禹城", + "level": "THREE_LEVEL", + "geoname_id": 1785977, + "sub_districts": [] + } + ] + }, + { + "code": "371700", + "name": "菏泽", + "level": "TWO_LEVEL", + "geoname_id": 1808198, + "sub_districts": [ + { + "code": "371723", + "name": "成武", + "level": "THREE_LEVEL", + "geoname_id": 1815195, + "sub_districts": [] + }, + { + "code": "371721", + "name": "曹县", + "level": "THREE_LEVEL", + "geoname_id": 1815954, + "sub_districts": [] + }, + { + "code": "371728", + "name": "东明", + "level": "THREE_LEVEL", + "geoname_id": 1812351, + "sub_districts": [] + }, + { + "code": "371703", + "name": "定陶", + "level": "THREE_LEVEL", + "geoname_id": 1812753, + "sub_districts": [] + }, + { + "code": "371726", + "name": "鄄城", + "level": "THREE_LEVEL", + "geoname_id": 1804993, + "sub_districts": [] + }, + { + "code": "371724", + "name": "巨野", + "level": "THREE_LEVEL", + "geoname_id": 1804891, + "sub_districts": [] + }, + { + "code": "371702", + "name": "牡丹", + "level": "THREE_LEVEL", + "geoname_id": 6573987, + "sub_districts": [] + }, + { + "code": "371722", + "name": "单县", + "level": "THREE_LEVEL", + "geoname_id": 1795921, + "sub_districts": [] + }, + { + "code": "371725", + "name": "郓城", + "level": "THREE_LEVEL", + "geoname_id": 1785734, + "sub_districts": [] + } + ] + }, + { + "code": "370100", + "name": "济南", + "level": "TWO_LEVEL", + "geoname_id": 1805753, + "sub_districts": [ + { + "code": "370113", + "name": "长清", + "level": "THREE_LEVEL", + "geoname_id": 1815582, + "sub_districts": [] + }, + { + "code": "3701170000001", + "name": "钢城", + "level": "THREE_LEVEL", + "geoname_id": 6573944, + "sub_districts": [] + }, + { + "code": "370104", + "name": "槐荫", + "level": "THREE_LEVEL", + "geoname_id": 6573948, + "sub_districts": [] + }, + { + "code": "3701150000001", + "name": "济阳", + "level": "THREE_LEVEL", + "geoname_id": 1805018, + "sub_districts": [] + }, + { + "code": "370112", + "name": "历城", + "level": "THREE_LEVEL", + "geoname_id": 1803785, + "sub_districts": [] + }, + { + "code": "3701160000001", + "name": "莱芜", + "level": "THREE_LEVEL", + "geoname_id": 6573943, + "sub_districts": [] + }, + { + "code": "370102", + "name": "历下", + "level": "THREE_LEVEL", + "geoname_id": 6573950, + "sub_districts": [] + }, + { + "code": "370124", + "name": "平阴", + "level": "THREE_LEVEL", + "geoname_id": 1798631, + "sub_districts": [] + }, + { + "code": "370126", + "name": "商河", + "level": "THREE_LEVEL", + "geoname_id": 1796219, + "sub_districts": [] + }, + { + "code": "370103", + "name": "市中", + "level": "THREE_LEVEL", + "geoname_id": 370103, + "sub_districts": [] + }, + { + "code": "370105", + "name": "天桥", + "level": "THREE_LEVEL", + "geoname_id": 6573949, + "sub_districts": [] + }, + { + "code": "3701140000001", + "name": "章丘", + "level": "THREE_LEVEL", + "geoname_id": 1785093, + "sub_districts": [] + } + ] + }, + { + "code": "370800", + "name": "济宁", + "level": "TWO_LEVEL", + "geoname_id": 1805518, + "sub_districts": [ + { + "code": "370828", + "name": "金乡", + "level": "THREE_LEVEL", + "geoname_id": 1805329, + "sub_districts": [] + }, + { + "code": "370829", + "name": "嘉祥", + "level": "THREE_LEVEL", + "geoname_id": 1805954, + "sub_districts": [] + }, + { + "code": "370832", + "name": "梁山", + "level": "THREE_LEVEL", + "geoname_id": 1803985, + "sub_districts": [] + }, + { + "code": "370881", + "name": "曲阜", + "level": "THREE_LEVEL", + "geoname_id": 1797333, + "sub_districts": [] + }, + { + "code": "370811", + "name": "任城", + "level": "THREE_LEVEL", + "geoname_id": 6573986, + "sub_districts": [] + }, + { + "code": "370831", + "name": "泗水", + "level": "THREE_LEVEL", + "geoname_id": 1794139, + "sub_districts": [] + }, + { + "code": "370826", + "name": "微山", + "level": "THREE_LEVEL", + "geoname_id": 1791613, + "sub_districts": [] + }, + { + "code": "370830", + "name": "汶上", + "level": "THREE_LEVEL", + "geoname_id": 1791426, + "sub_districts": [] + }, + { + "code": "370827", + "name": "鱼台", + "level": "THREE_LEVEL", + "geoname_id": 1785606, + "sub_districts": [] + }, + { + "code": "370812", + "name": "兖州", + "level": "THREE_LEVEL", + "geoname_id": 1787030, + "sub_districts": [] + }, + { + "code": "370883", + "name": "邹城", + "level": "THREE_LEVEL", + "geoname_id": 1783633, + "sub_districts": [] + } + ] + }, + { + "code": "371500", + "name": "聊城", + "level": "TWO_LEVEL", + "geoname_id": 1803834, + "sub_districts": [ + { + "code": "3715030000001", + "name": "茌平", + "level": "THREE_LEVEL", + "geoname_id": 1814985, + "sub_districts": [] + }, + { + "code": "371502", + "name": "东昌府", + "level": "THREE_LEVEL", + "geoname_id": 6573956, + "sub_districts": [] + }, + { + "code": "371524", + "name": "东阿", + "level": "THREE_LEVEL", + "geoname_id": 1812593, + "sub_districts": [] + }, + { + "code": "371526", + "name": "高唐", + "level": "THREE_LEVEL", + "geoname_id": 1810357, + "sub_districts": [] + }, + { + "code": "371525", + "name": "冠县", + "level": "THREE_LEVEL", + "geoname_id": 1809727, + "sub_districts": [] + }, + { + "code": "371581", + "name": "临清", + "level": "THREE_LEVEL", + "geoname_id": 1803366, + "sub_districts": [] + }, + { + "code": "371522", + "name": "莘县", + "level": "THREE_LEVEL", + "geoname_id": 1795581, + "sub_districts": [] + }, + { + "code": "371521", + "name": "阳谷", + "level": "THREE_LEVEL", + "geoname_id": 1787593, + "sub_districts": [] + } + ] + }, + { + "code": "371300", + "name": "临沂", + "level": "TWO_LEVEL", + "geoname_id": 1803316, + "sub_districts": [ + { + "code": "371325", + "name": "费县", + "level": "THREE_LEVEL", + "geoname_id": 1811441, + "sub_districts": [] + }, + { + "code": "371312", + "name": "河东", + "level": "THREE_LEVEL", + "geoname_id": 6573978, + "sub_districts": [] + }, + { + "code": "371327", + "name": "莒南", + "level": "THREE_LEVEL", + "geoname_id": 1804953, + "sub_districts": [] + }, + { + "code": "371324", + "name": "兰陵", + "level": "THREE_LEVEL", + "geoname_id": 371324, + "sub_districts": [] + }, + { + "code": "371302", + "name": "兰山", + "level": "THREE_LEVEL", + "geoname_id": 6573976, + "sub_districts": [] + }, + { + "code": "371329", + "name": "临沭", + "level": "THREE_LEVEL", + "geoname_id": 1803350, + "sub_districts": [] + }, + { + "code": "371311", + "name": "罗庄", + "level": "THREE_LEVEL", + "geoname_id": 6573977, + "sub_districts": [] + }, + { + "code": "371328", + "name": "蒙阴", + "level": "THREE_LEVEL", + "geoname_id": 1800674, + "sub_districts": [] + }, + { + "code": "371326", + "name": "平邑", + "level": "THREE_LEVEL", + "geoname_id": 1798630, + "sub_districts": [] + }, + { + "code": "371322", + "name": "郯城", + "level": "THREE_LEVEL", + "geoname_id": 1793473, + "sub_districts": [] + }, + { + "code": "371321", + "name": "沂南", + "level": "THREE_LEVEL", + "geoname_id": 1786662, + "sub_districts": [] + }, + { + "code": "371323", + "name": "沂水", + "level": "THREE_LEVEL", + "geoname_id": 1786452, + "sub_districts": [] + } + ] + }, + { + "code": "370200", + "name": "青岛", + "level": "TWO_LEVEL", + "geoname_id": 1797929, + "sub_districts": [ + { + "code": "370214", + "name": "城阳", + "level": "THREE_LEVEL", + "geoname_id": 6573973, + "sub_districts": [] + }, + { + "code": "370211", + "name": "黄岛", + "level": "THREE_LEVEL", + "geoname_id": 6573972, + "sub_districts": [] + }, + { + "code": "3702150000001", + "name": "即墨", + "level": "THREE_LEVEL", + "geoname_id": 1805756, + "sub_districts": [] + }, + { + "code": "370281", + "name": "胶州", + "level": "THREE_LEVEL", + "geoname_id": 1806003, + "sub_districts": [] + }, + { + "code": "370213", + "name": "李沧", + "level": "THREE_LEVEL", + "geoname_id": 6573974, + "sub_districts": [] + }, + { + "code": "370212", + "name": "崂山", + "level": "THREE_LEVEL", + "geoname_id": 1804332, + "sub_districts": [] + }, + { + "code": "370285", + "name": "莱西", + "level": "THREE_LEVEL", + "geoname_id": 1804588, + "sub_districts": [] + }, + { + "code": "370283", + "name": "平度", + "level": "THREE_LEVEL", + "geoname_id": 1798819, + "sub_districts": [] + }, + { + "code": "370203", + "name": "市北", + "level": "THREE_LEVEL", + "geoname_id": 6573970, + "sub_districts": [] + }, + { + "code": "370202", + "name": "市南", + "level": "THREE_LEVEL", + "geoname_id": 6573969, + "sub_districts": [] + } + ] + }, + { + "code": "371100", + "name": "日照", + "level": "TWO_LEVEL", + "geoname_id": 1797132, + "sub_districts": [ + { + "code": "371102", + "name": "东港", + "level": "THREE_LEVEL", + "geoname_id": 6573975, + "sub_districts": [] + }, + { + "code": "371122", + "name": "莒县", + "level": "THREE_LEVEL", + "geoname_id": 1804897, + "sub_districts": [] + }, + { + "code": "371103", + "name": "岚山", + "level": "THREE_LEVEL", + "geoname_id": 1818098, + "sub_districts": [] + }, + { + "code": "371121", + "name": "五莲", + "level": "THREE_LEVEL", + "geoname_id": 1791136, + "sub_districts": [] + } + ] + }, + { + "code": "370900", + "name": "泰安", + "level": "TWO_LEVEL", + "geoname_id": 1793722, + "sub_districts": [ + { + "code": "370923", + "name": "东平", + "level": "THREE_LEVEL", + "geoname_id": 1812323, + "sub_districts": [] + }, + { + "code": "370911", + "name": "岱岳", + "level": "THREE_LEVEL", + "geoname_id": 6573946, + "sub_districts": [] + }, + { + "code": "370983", + "name": "肥城", + "level": "THREE_LEVEL", + "geoname_id": 1811458, + "sub_districts": [] + }, + { + "code": "370921", + "name": "宁阳", + "level": "THREE_LEVEL", + "geoname_id": 1799347, + "sub_districts": [] + }, + { + "code": "370902", + "name": "泰山", + "level": "THREE_LEVEL", + "geoname_id": 6573945, + "sub_districts": [] + }, + { + "code": "370982", + "name": "新泰", + "level": "THREE_LEVEL", + "geoname_id": 1788616, + "sub_districts": [] + } + ] + }, + { + "code": "370700", + "name": "潍坊", + "level": "TWO_LEVEL", + "geoname_id": 1791681, + "sub_districts": [ + { + "code": "370784", + "name": "安丘", + "level": "THREE_LEVEL", + "geoname_id": 1817989, + "sub_districts": [] + }, + { + "code": "370725", + "name": "昌乐", + "level": "THREE_LEVEL", + "geoname_id": 1815661, + "sub_districts": [] + }, + { + "code": "370786", + "name": "昌邑", + "level": "THREE_LEVEL", + "geoname_id": 1815479, + "sub_districts": [] + }, + { + "code": "370704", + "name": "坊子", + "level": "THREE_LEVEL", + "geoname_id": 6573962, + "sub_districts": [] + }, + { + "code": "370785", + "name": "高密", + "level": "THREE_LEVEL", + "geoname_id": 1810451, + "sub_districts": [] + }, + { + "code": "370703", + "name": "寒亭", + "level": "THREE_LEVEL", + "geoname_id": 6573961, + "sub_districts": [] + }, + { + "code": "370705", + "name": "奎文", + "level": "THREE_LEVEL", + "geoname_id": 6573963, + "sub_districts": [] + }, + { + "code": "370724", + "name": "临朐", + "level": "THREE_LEVEL", + "geoname_id": 1803360, + "sub_districts": [] + }, + { + "code": "370781", + "name": "青州", + "level": "THREE_LEVEL", + "geoname_id": 1797603, + "sub_districts": [] + }, + { + "code": "370783", + "name": "寿光", + "level": "THREE_LEVEL", + "geoname_id": 1794793, + "sub_districts": [] + }, + { + "code": "370702", + "name": "潍城", + "level": "THREE_LEVEL", + "geoname_id": 6573960, + "sub_districts": [] + }, + { + "code": "370782", + "name": "诸城", + "level": "THREE_LEVEL", + "geoname_id": 1783987, + "sub_districts": [] + } + ] + }, + { + "code": "371000", + "name": "威海", + "level": "TWO_LEVEL", + "geoname_id": 1791673, + "sub_districts": [ + { + "code": "371002", + "name": "环翠", + "level": "THREE_LEVEL", + "geoname_id": 6573968, + "sub_districts": [] + }, + { + "code": "371082", + "name": "荣成", + "level": "THREE_LEVEL", + "geoname_id": 1786855, + "sub_districts": [] + }, + { + "code": "371083", + "name": "乳山", + "level": "THREE_LEVEL", + "geoname_id": 8541400, + "sub_districts": [] + }, + { + "code": "371003", + "name": "文登", + "level": "THREE_LEVEL", + "geoname_id": 1791526, + "sub_districts": [] + } + ] + }, + { + "code": "370600", + "name": "烟台", + "level": "TWO_LEVEL", + "geoname_id": 1787093, + "sub_districts": [ + { + "code": "370611", + "name": "福山", + "level": "THREE_LEVEL", + "geoname_id": 1810920, + "sub_districts": [] + }, + { + "code": "370687", + "name": "海阳", + "level": "THREE_LEVEL", + "geoname_id": 1809017, + "sub_districts": [] + }, + { + "code": "370681", + "name": "龙口", + "level": "THREE_LEVEL", + "geoname_id": 1802548, + "sub_districts": [] + }, + { + "code": "370613", + "name": "莱山", + "level": "THREE_LEVEL", + "geoname_id": 6573966, + "sub_districts": [] + }, + { + "code": "370682", + "name": "莱阳", + "level": "THREE_LEVEL", + "geoname_id": 1804585, + "sub_districts": [] + }, + { + "code": "370683", + "name": "莱州", + "level": "THREE_LEVEL", + "geoname_id": 1804578, + "sub_districts": [] + }, + { + "code": "370612", + "name": "牟平", + "level": "THREE_LEVEL", + "geoname_id": 1800283, + "sub_districts": [] + }, + { + "code": "3706140000001", + "name": "蓬莱", + "level": "THREE_LEVEL", + "geoname_id": 1812988, + "sub_districts": [] + }, + { + "code": "370686", + "name": "栖霞", + "level": "THREE_LEVEL", + "geoname_id": 1797438, + "sub_districts": [] + }, + { + "code": "370602", + "name": "芝罘", + "level": "THREE_LEVEL", + "geoname_id": 6573964, + "sub_districts": [] + }, + { + "code": "370685", + "name": "招远", + "level": "THREE_LEVEL", + "geoname_id": 1784953, + "sub_districts": [] + } + ] + }, + { + "code": "370300", + "name": "淄博", + "level": "TWO_LEVEL", + "geoname_id": 1785286, + "sub_districts": [ + { + "code": "370304", + "name": "博山", + "level": "THREE_LEVEL", + "geoname_id": 6573951, + "sub_districts": [] + }, + { + "code": "370322", + "name": "高青", + "level": "THREE_LEVEL", + "geoname_id": 1810401, + "sub_districts": [] + }, + { + "code": "370321", + "name": "桓台", + "level": "THREE_LEVEL", + "geoname_id": 1807084, + "sub_districts": [] + }, + { + "code": "370305", + "name": "临淄", + "level": "THREE_LEVEL", + "geoname_id": 6573954, + "sub_districts": [] + }, + { + "code": "370323", + "name": "沂源", + "level": "THREE_LEVEL", + "geoname_id": 1786414, + "sub_districts": [] + }, + { + "code": "370302", + "name": "淄川", + "level": "THREE_LEVEL", + "geoname_id": 6573952, + "sub_districts": [] + }, + { + "code": "370306", + "name": "周村", + "level": "THREE_LEVEL", + "geoname_id": 6573953, + "sub_districts": [] + }, + { + "code": "370303", + "name": "张店", + "level": "THREE_LEVEL", + "geoname_id": 6573955, + "sub_districts": [] + } + ] + }, + { + "code": "370400", + "name": "枣庄", + "level": "TWO_LEVEL", + "geoname_id": 1785453, + "sub_districts": [ + { + "code": "370406", + "name": "山亭", + "level": "THREE_LEVEL", + "geoname_id": 6573983, + "sub_districts": [] + }, + { + "code": "370402", + "name": "市中", + "level": "THREE_LEVEL", + "geoname_id": 370402, + "sub_districts": [] + }, + { + "code": "370405", + "name": "台儿庄", + "level": "THREE_LEVEL", + "geoname_id": 6573982, + "sub_districts": [] + }, + { + "code": "370481", + "name": "滕州", + "level": "THREE_LEVEL", + "geoname_id": 1793036, + "sub_districts": [] + }, + { + "code": "370403", + "name": "薛城", + "level": "THREE_LEVEL", + "geoname_id": 6573980, + "sub_districts": [] + }, + { + "code": "370404", + "name": "峄城", + "level": "THREE_LEVEL", + "geoname_id": 6573981, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "31", + "name": "上海", + "level": "ONE_LEVEL", + "geoname_id": 1796231, + "sub_districts": [ + { + "code": "310000", + "name": "上海", + "level": "TWO_LEVEL", + "geoname_id": 1796236, + "sub_districts": [ + { + "code": "310113", + "name": "宝山", + "level": "THREE_LEVEL", + "geoname_id": 1816914, + "sub_districts": [] + }, + { + "code": "310151", + "name": "崇明", + "level": "THREE_LEVEL", + "geoname_id": 1814912, + "sub_districts": [] + }, + { + "code": "310105", + "name": "长宁", + "level": "THREE_LEVEL", + "geoname_id": 1815609, + "sub_districts": [] + }, + { + "code": "310120", + "name": "奉贤", + "level": "THREE_LEVEL", + "geoname_id": 1811193, + "sub_districts": [] + }, + { + "code": "310109", + "name": "虹口", + "level": "THREE_LEVEL", + "geoname_id": 1808089, + "sub_districts": [] + }, + { + "code": "310101", + "name": "黄浦", + "level": "THREE_LEVEL", + "geoname_id": 1807293, + "sub_districts": [] + }, + { + "code": "310106", + "name": "静安", + "level": "THREE_LEVEL", + "geoname_id": 1805695, + "sub_districts": [] + }, + { + "code": "310114", + "name": "嘉定", + "level": "THREE_LEVEL", + "geoname_id": 1806507, + "sub_districts": [] + }, + { + "code": "310116", + "name": "金山", + "level": "THREE_LEVEL", + "geoname_id": 1805390, + "sub_districts": [] + }, + { + "code": "310112", + "name": "闵行", + "level": "THREE_LEVEL", + "geoname_id": 6569431, + "sub_districts": [] + }, + { + "code": "310115", + "name": "浦东", + "level": "THREE_LEVEL", + "geoname_id": 1798524, + "sub_districts": [] + }, + { + "code": "310107", + "name": "普陀", + "level": "THREE_LEVEL", + "geoname_id": 1798438, + "sub_districts": [] + }, + { + "code": "310118", + "name": "青浦", + "level": "THREE_LEVEL", + "geoname_id": 1797797, + "sub_districts": [] + }, + { + "code": "310117", + "name": "松江", + "level": "THREE_LEVEL", + "geoname_id": 1794034, + "sub_districts": [] + }, + { + "code": "310104", + "name": "徐汇", + "level": "THREE_LEVEL", + "geoname_id": 1787956, + "sub_districts": [] + }, + { + "code": "310110", + "name": "杨浦", + "level": "THREE_LEVEL", + "geoname_id": 1787372, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "14", + "name": "山西", + "level": "ONE_LEVEL", + "geoname_id": 1795912, + "sub_districts": [ + { + "code": "140400", + "name": "长治", + "level": "TWO_LEVEL", + "geoname_id": 1808956, + "sub_districts": [ + { + "code": "140427", + "name": "壶关", + "level": "THREE_LEVEL", + "geoname_id": 1806901, + "sub_districts": [] + }, + { + "code": "1404060000001", + "name": "潞城", + "level": "THREE_LEVEL", + "geoname_id": 1802164, + "sub_districts": [] + }, + { + "code": "140426", + "name": "黎城", + "level": "THREE_LEVEL", + "geoname_id": 1803786, + "sub_districts": [] + }, + { + "code": "140403", + "name": "潞州", + "level": "THREE_LEVEL", + "geoname_id": 140403, + "sub_districts": [] + }, + { + "code": "140425", + "name": "平顺", + "level": "THREE_LEVEL", + "geoname_id": 1798688, + "sub_districts": [] + }, + { + "code": "140430", + "name": "沁县", + "level": "THREE_LEVEL", + "geoname_id": 1797560, + "sub_districts": [] + }, + { + "code": "140431", + "name": "沁源", + "level": "THREE_LEVEL", + "geoname_id": 1797553, + "sub_districts": [] + }, + { + "code": "1404040000001", + "name": "上党", + "level": "THREE_LEVEL", + "geoname_id": 140421, + "sub_districts": [] + }, + { + "code": "1404050000001", + "name": "屯留", + "level": "THREE_LEVEL", + "geoname_id": 1792364, + "sub_districts": [] + }, + { + "code": "140429", + "name": "武乡", + "level": "THREE_LEVEL", + "geoname_id": 1790914, + "sub_districts": [] + }, + { + "code": "140423", + "name": "襄垣", + "level": "THREE_LEVEL", + "geoname_id": 1790444, + "sub_districts": [] + }, + { + "code": "140428", + "name": "长子", + "level": "THREE_LEVEL", + "geoname_id": 1784996, + "sub_districts": [] + } + ] + }, + { + "code": "140200", + "name": "大同", + "level": "TWO_LEVEL", + "geoname_id": 2037799, + "sub_districts": [ + { + "code": "140223", + "name": "广灵", + "level": "THREE_LEVEL", + "geoname_id": 1809907, + "sub_districts": [] + }, + { + "code": "140225", + "name": "浑源", + "level": "THREE_LEVEL", + "geoname_id": 1806686, + "sub_districts": [] + }, + { + "code": "140224", + "name": "灵丘", + "level": "THREE_LEVEL", + "geoname_id": 1803485, + "sub_districts": [] + }, + { + "code": "140213", + "name": "平城", + "level": "THREE_LEVEL", + "geoname_id": 140213, + "sub_districts": [] + }, + { + "code": "140222", + "name": "天镇", + "level": "THREE_LEVEL", + "geoname_id": 2034450, + "sub_districts": [] + }, + { + "code": "140212", + "name": "新荣", + "level": "THREE_LEVEL", + "geoname_id": 6642580, + "sub_districts": [] + }, + { + "code": "140214", + "name": "云冈", + "level": "THREE_LEVEL", + "geoname_id": 140214, + "sub_districts": [] + }, + { + "code": "140221", + "name": "阳高", + "level": "THREE_LEVEL", + "geoname_id": 2033509, + "sub_districts": [] + }, + { + "code": "1402150000001", + "name": "云州", + "level": "THREE_LEVEL", + "geoname_id": 140227, + "sub_districts": [] + }, + { + "code": "140226", + "name": "左云", + "level": "THREE_LEVEL", + "geoname_id": 1783586, + "sub_districts": [] + } + ] + }, + { + "code": "140500", + "name": "晋城", + "level": "TWO_LEVEL", + "geoname_id": 1805739, + "sub_districts": [ + { + "code": "140581", + "name": "高平", + "level": "THREE_LEVEL", + "geoname_id": 1810434, + "sub_districts": [] + }, + { + "code": "140502", + "name": "城区", + "level": "THREE_LEVEL", + "geoname_id": 8053996, + "sub_districts": [] + }, + { + "code": "140524", + "name": "陵川", + "level": "THREE_LEVEL", + "geoname_id": 1803544, + "sub_districts": [] + }, + { + "code": "140521", + "name": "沁水", + "level": "THREE_LEVEL", + "geoname_id": 1797567, + "sub_districts": [] + }, + { + "code": "140522", + "name": "阳城", + "level": "THREE_LEVEL", + "geoname_id": 1787662, + "sub_districts": [] + }, + { + "code": "140525", + "name": "泽州", + "level": "THREE_LEVEL", + "geoname_id": 6642566, + "sub_districts": [] + } + ] + }, + { + "code": "140700", + "name": "晋中", + "level": "TWO_LEVEL", + "geoname_id": 1805302, + "sub_districts": [ + { + "code": "140723", + "name": "和顺", + "level": "THREE_LEVEL", + "geoname_id": 1808273, + "sub_districts": [] + }, + { + "code": "140781", + "name": "介休", + "level": "THREE_LEVEL", + "geoname_id": 1805832, + "sub_districts": [] + }, + { + "code": "140729", + "name": "灵石", + "level": "THREE_LEVEL", + "geoname_id": 1803467, + "sub_districts": [] + }, + { + "code": "140728", + "name": "平遥", + "level": "THREE_LEVEL", + "geoname_id": 1798635, + "sub_districts": [] + }, + { + "code": "140727", + "name": "祁县", + "level": "THREE_LEVEL", + "geoname_id": 1797435, + "sub_districts": [] + }, + { + "code": "140725", + "name": "寿阳", + "level": "THREE_LEVEL", + "geoname_id": 1794777, + "sub_districts": [] + }, + { + "code": "1407030000001", + "name": "太谷", + "level": "THREE_LEVEL", + "geoname_id": 1793690, + "sub_districts": [] + }, + { + "code": "140724", + "name": "昔阳", + "level": "THREE_LEVEL", + "geoname_id": 1788158, + "sub_districts": [] + }, + { + "code": "140702", + "name": "榆次", + "level": "THREE_LEVEL", + "geoname_id": 1785973, + "sub_districts": [] + }, + { + "code": "140721", + "name": "榆社", + "level": "THREE_LEVEL", + "geoname_id": 1785613, + "sub_districts": [] + }, + { + "code": "140722", + "name": "左权", + "level": "THREE_LEVEL", + "geoname_id": 1783599, + "sub_districts": [] + } + ] + }, + { + "code": "141000", + "name": "临汾", + "level": "TWO_LEVEL", + "geoname_id": 1803567, + "sub_districts": [ + { + "code": "141026", + "name": "安泽", + "level": "THREE_LEVEL", + "geoname_id": 1817927, + "sub_districts": [] + }, + { + "code": "141030", + "name": "大宁", + "level": "THREE_LEVEL", + "geoname_id": 1813835, + "sub_districts": [] + }, + { + "code": "141027", + "name": "浮山", + "level": "THREE_LEVEL", + "geoname_id": 1810916, + "sub_districts": [] + }, + { + "code": "141034", + "name": "汾西", + "level": "THREE_LEVEL", + "geoname_id": 1811118, + "sub_districts": [] + }, + { + "code": "141025", + "name": "古县", + "level": "THREE_LEVEL", + "geoname_id": 1809191, + "sub_districts": [] + }, + { + "code": "141024", + "name": "洪洞", + "level": "THREE_LEVEL", + "geoname_id": 1807980, + "sub_districts": [] + }, + { + "code": "141081", + "name": "侯马", + "level": "THREE_LEVEL", + "geoname_id": 1807818, + "sub_districts": [] + }, + { + "code": "141082", + "name": "霍州", + "level": "THREE_LEVEL", + "geoname_id": 1806624, + "sub_districts": [] + }, + { + "code": "141028", + "name": "吉县", + "level": "THREE_LEVEL", + "geoname_id": 1805030, + "sub_districts": [] + }, + { + "code": "141033", + "name": "蒲县", + "level": "THREE_LEVEL", + "geoname_id": 1798428, + "sub_districts": [] + }, + { + "code": "141021", + "name": "曲沃", + "level": "THREE_LEVEL", + "geoname_id": 1797286, + "sub_districts": [] + }, + { + "code": "141023", + "name": "襄汾", + "level": "THREE_LEVEL", + "geoname_id": 1790584, + "sub_districts": [] + }, + { + "code": "141029", + "name": "乡宁", + "level": "THREE_LEVEL", + "geoname_id": 1790533, + "sub_districts": [] + }, + { + "code": "141031", + "name": "隰县", + "level": "THREE_LEVEL", + "geoname_id": 1788209, + "sub_districts": [] + }, + { + "code": "141022", + "name": "翼城", + "level": "THREE_LEVEL", + "geoname_id": 1786756, + "sub_districts": [] + }, + { + "code": "141002", + "name": "尧都", + "level": "THREE_LEVEL", + "geoname_id": 6642564, + "sub_districts": [] + }, + { + "code": "141032", + "name": "永和", + "level": "THREE_LEVEL", + "geoname_id": 1786331, + "sub_districts": [] + } + ] + }, + { + "code": "141100", + "name": "吕梁", + "level": "TWO_LEVEL", + "geoname_id": 1802029, + "sub_districts": [ + { + "code": "141128", + "name": "方山", + "level": "THREE_LEVEL", + "geoname_id": 1811540, + "sub_districts": [] + }, + { + "code": "141182", + "name": "汾阳", + "level": "THREE_LEVEL", + "geoname_id": 1811115, + "sub_districts": [] + }, + { + "code": "141122", + "name": "交城", + "level": "THREE_LEVEL", + "geoname_id": 1806093, + "sub_districts": [] + }, + { + "code": "141130", + "name": "交口", + "level": "THREE_LEVEL", + "geoname_id": 1806048, + "sub_districts": [] + }, + { + "code": "141125", + "name": "柳林", + "level": "THREE_LEVEL", + "geoname_id": 1802979, + "sub_districts": [] + }, + { + "code": "141102", + "name": "离石", + "level": "THREE_LEVEL", + "geoname_id": 1803255, + "sub_districts": [] + }, + { + "code": "141124", + "name": "临县", + "level": "THREE_LEVEL", + "geoname_id": 1803328, + "sub_districts": [] + }, + { + "code": "141127", + "name": "岚县", + "level": "THREE_LEVEL", + "geoname_id": 1804438, + "sub_districts": [] + }, + { + "code": "141126", + "name": "石楼", + "level": "THREE_LEVEL", + "geoname_id": 1795169, + "sub_districts": [] + }, + { + "code": "141121", + "name": "文水", + "level": "THREE_LEVEL", + "geoname_id": 1791419, + "sub_districts": [] + }, + { + "code": "141123", + "name": "兴县", + "level": "THREE_LEVEL", + "geoname_id": 1788913, + "sub_districts": [] + }, + { + "code": "141181", + "name": "孝义", + "level": "THREE_LEVEL", + "geoname_id": 1789888, + "sub_districts": [] + }, + { + "code": "141129", + "name": "中阳", + "level": "THREE_LEVEL", + "geoname_id": 1784234, + "sub_districts": [] + } + ] + }, + { + "code": "140600", + "name": "朔州", + "level": "TWO_LEVEL", + "geoname_id": 6642609, + "sub_districts": [ + { + "code": "1406810000001", + "name": "怀仁", + "level": "THREE_LEVEL", + "geoname_id": 1807670, + "sub_districts": [] + }, + { + "code": "140603", + "name": "平鲁", + "level": "THREE_LEVEL", + "geoname_id": 1798740, + "sub_districts": [] + }, + { + "code": "140602", + "name": "朔城", + "level": "THREE_LEVEL", + "geoname_id": 1794329, + "sub_districts": [] + }, + { + "code": "140621", + "name": "山阴", + "level": "THREE_LEVEL", + "geoname_id": 1795899, + "sub_districts": [] + }, + { + "code": "140622", + "name": "应县", + "level": "THREE_LEVEL", + "geoname_id": 1786560, + "sub_districts": [] + }, + { + "code": "140623", + "name": "右玉", + "level": "THREE_LEVEL", + "geoname_id": 1786132, + "sub_districts": [] + } + ] + }, + { + "code": "140100", + "name": "太原", + "level": "TWO_LEVEL", + "geoname_id": 1793511, + "sub_districts": [ + { + "code": "140181", + "name": "古交", + "level": "THREE_LEVEL", + "geoname_id": 6643157, + "sub_districts": [] + }, + { + "code": "140108", + "name": "尖草坪", + "level": "THREE_LEVEL", + "geoname_id": 6642575, + "sub_districts": [] + }, + { + "code": "140110", + "name": "晋源", + "level": "THREE_LEVEL", + "geoname_id": 6642569, + "sub_districts": [] + }, + { + "code": "140123", + "name": "娄烦", + "level": "THREE_LEVEL", + "geoname_id": 1802229, + "sub_districts": [] + }, + { + "code": "1401210000003", + "name": "清徐", + "level": "THREE_LEVEL", + "geoname_id": 1797661, + "sub_districts": [] + }, + { + "code": "140109", + "name": "万柏林", + "level": "THREE_LEVEL", + "geoname_id": 6642572, + "sub_districts": [] + }, + { + "code": "1401050000003", + "name": "小店", + "level": "THREE_LEVEL", + "geoname_id": 6642570, + "sub_districts": [] + }, + { + "code": "140107", + "name": "杏花岭", + "level": "THREE_LEVEL", + "geoname_id": 6642574, + "sub_districts": [] + }, + { + "code": "140122", + "name": "阳曲", + "level": "THREE_LEVEL", + "geoname_id": 1787344, + "sub_districts": [] + }, + { + "code": "140106", + "name": "迎泽", + "level": "THREE_LEVEL", + "geoname_id": 6642573, + "sub_districts": [] + } + ] + }, + { + "code": "140900", + "name": "忻州", + "level": "TWO_LEVEL", + "geoname_id": 1788450, + "sub_districts": [ + { + "code": "140931", + "name": "保德", + "level": "THREE_LEVEL", + "geoname_id": 1816977, + "sub_districts": [] + }, + { + "code": "140923", + "name": "代县", + "level": "THREE_LEVEL", + "geoname_id": 1814215, + "sub_districts": [] + }, + { + "code": "140921", + "name": "定襄", + "level": "THREE_LEVEL", + "geoname_id": 1812746, + "sub_districts": [] + }, + { + "code": "140924", + "name": "繁峙", + "level": "THREE_LEVEL", + "geoname_id": 1811477, + "sub_districts": [] + }, + { + "code": "140930", + "name": "河曲", + "level": "THREE_LEVEL", + "geoname_id": 1808321, + "sub_districts": [] + }, + { + "code": "140926", + "name": "静乐", + "level": "THREE_LEVEL", + "geoname_id": 1805621, + "sub_districts": [] + }, + { + "code": "140929", + "name": "岢岚", + "level": "THREE_LEVEL", + "geoname_id": 1804774, + "sub_districts": [] + }, + { + "code": "140925", + "name": "宁武", + "level": "THREE_LEVEL", + "geoname_id": 1799357, + "sub_districts": [] + }, + { + "code": "140932", + "name": "偏关", + "level": "THREE_LEVEL", + "geoname_id": 1798887, + "sub_districts": [] + }, + { + "code": "140927", + "name": "神池", + "level": "THREE_LEVEL", + "geoname_id": 1795700, + "sub_districts": [] + }, + { + "code": "1409710000001", + "name": "五台山风景名胜", + "level": "THREE_LEVEL", + "geoname_id": 60000479, + "sub_districts": [] + }, + { + "code": "140922", + "name": "五台", + "level": "THREE_LEVEL", + "geoname_id": 1790954, + "sub_districts": [] + }, + { + "code": "140928", + "name": "五寨", + "level": "THREE_LEVEL", + "geoname_id": 1790852, + "sub_districts": [] + }, + { + "code": "140902", + "name": "忻府", + "level": "THREE_LEVEL", + "geoname_id": 1788447, + "sub_districts": [] + }, + { + "code": "140981", + "name": "原平", + "level": "THREE_LEVEL", + "geoname_id": 1786060, + "sub_districts": [] + } + ] + }, + { + "code": "140800", + "name": "运城", + "level": "TWO_LEVEL", + "geoname_id": 1785738, + "sub_districts": [ + { + "code": "140882", + "name": "河津", + "level": "THREE_LEVEL", + "geoname_id": 1808593, + "sub_districts": [] + }, + { + "code": "140824", + "name": "稷山", + "level": "THREE_LEVEL", + "geoname_id": 1805277, + "sub_districts": [] + }, + { + "code": "140826", + "name": "绛县", + "level": "THREE_LEVEL", + "geoname_id": 1806233, + "sub_districts": [] + }, + { + "code": "140821", + "name": "临猗", + "level": "THREE_LEVEL", + "geoname_id": 1786458, + "sub_districts": [] + }, + { + "code": "140829", + "name": "平陆", + "level": "THREE_LEVEL", + "geoname_id": 1798741, + "sub_districts": [] + }, + { + "code": "140830", + "name": "芮城", + "level": "THREE_LEVEL", + "geoname_id": 1797059, + "sub_districts": [] + }, + { + "code": "140822", + "name": "万荣", + "level": "THREE_LEVEL", + "geoname_id": 1789586, + "sub_districts": [] + }, + { + "code": "140823", + "name": "闻喜", + "level": "THREE_LEVEL", + "geoname_id": 1791400, + "sub_districts": [] + }, + { + "code": "140825", + "name": "新绛", + "level": "THREE_LEVEL", + "geoname_id": 1788796, + "sub_districts": [] + }, + { + "code": "140828", + "name": "夏县", + "level": "THREE_LEVEL", + "geoname_id": 1789753, + "sub_districts": [] + }, + { + "code": "140802", + "name": "盐湖", + "level": "THREE_LEVEL", + "geoname_id": 1785735, + "sub_districts": [] + }, + { + "code": "140881", + "name": "永济", + "level": "THREE_LEVEL", + "geoname_id": 1784818, + "sub_districts": [] + }, + { + "code": "140827", + "name": "垣曲", + "level": "THREE_LEVEL", + "geoname_id": 1786054, + "sub_districts": [] + } + ] + }, + { + "code": "140300", + "name": "阳泉", + "level": "TWO_LEVEL", + "geoname_id": 1787346, + "sub_districts": [ + { + "code": "140321", + "name": "平定", + "level": "THREE_LEVEL", + "geoname_id": 1798825, + "sub_districts": [] + }, + { + "code": "140302", + "name": "城区", + "level": "THREE_LEVEL", + "geoname_id": 8053962, + "sub_districts": [] + }, + { + "code": "140311", + "name": "郊区", + "level": "THREE_LEVEL", + "geoname_id": 1786487, + "sub_districts": [] + }, + { + "code": "140303", + "name": "矿区", + "level": "THREE_LEVEL", + "geoname_id": 8053963, + "sub_districts": [] + }, + { + "code": "140322", + "name": "盂县", + "level": "THREE_LEVEL", + "geoname_id": 1785568, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "61", + "name": "陕西", + "level": "ONE_LEVEL", + "geoname_id": 1796480, + "sub_districts": [ + { + "code": "610900", + "name": "安康", + "level": "TWO_LEVEL", + "geoname_id": 1789065, + "sub_districts": [ + { + "code": "610929", + "name": "白河", + "level": "THREE_LEVEL", + "geoname_id": 1817683, + "sub_districts": [] + }, + { + "code": "610902", + "name": "汉滨", + "level": "THREE_LEVEL", + "geoname_id": 9165898, + "sub_districts": [] + }, + { + "code": "610921", + "name": "汉阴", + "level": "THREE_LEVEL", + "geoname_id": 1808862, + "sub_districts": [] + }, + { + "code": "610925", + "name": "岚皋", + "level": "THREE_LEVEL", + "geoname_id": 1804549, + "sub_districts": [] + }, + { + "code": "610923", + "name": "宁陕", + "level": "THREE_LEVEL", + "geoname_id": 1799360, + "sub_districts": [] + }, + { + "code": "610926", + "name": "平利", + "level": "THREE_LEVEL", + "geoname_id": 1798750, + "sub_districts": [] + }, + { + "code": "610922", + "name": "石泉", + "level": "THREE_LEVEL", + "geoname_id": 1795022, + "sub_districts": [] + }, + { + "code": "6109810000001", + "name": "旬阳", + "level": "THREE_LEVEL", + "geoname_id": 1787871, + "sub_districts": [] + }, + { + "code": "610927", + "name": "镇坪", + "level": "THREE_LEVEL", + "geoname_id": 1784616, + "sub_districts": [] + }, + { + "code": "610924", + "name": "紫阳", + "level": "THREE_LEVEL", + "geoname_id": 1783679, + "sub_districts": [] + } + ] + }, + { + "code": "610300", + "name": "宝鸡", + "level": "TWO_LEVEL", + "geoname_id": 11417275, + "sub_districts": [ + { + "code": "610304", + "name": "陈仓", + "level": "THREE_LEVEL", + "geoname_id": 1809263, + "sub_districts": [] + }, + { + "code": "610324", + "name": "扶风", + "level": "THREE_LEVEL", + "geoname_id": 1811043, + "sub_districts": [] + }, + { + "code": "610330", + "name": "凤县", + "level": "THREE_LEVEL", + "geoname_id": 1794593, + "sub_districts": [] + }, + { + "code": "6103050000001", + "name": "凤翔", + "level": "THREE_LEVEL", + "geoname_id": 7353795, + "sub_districts": [] + }, + { + "code": "610303", + "name": "金台", + "level": "THREE_LEVEL", + "geoname_id": 6599417, + "sub_districts": [] + }, + { + "code": "610327", + "name": "陇县", + "level": "THREE_LEVEL", + "geoname_id": 1802302, + "sub_districts": [] + }, + { + "code": "610329", + "name": "麟游", + "level": "THREE_LEVEL", + "geoname_id": 1803310, + "sub_districts": [] + }, + { + "code": "610326", + "name": "眉县", + "level": "THREE_LEVEL", + "geoname_id": 7352544, + "sub_districts": [] + }, + { + "code": "610323", + "name": "岐山", + "level": "THREE_LEVEL", + "geoname_id": 1797503, + "sub_districts": [] + }, + { + "code": "610328", + "name": "千阳", + "level": "THREE_LEVEL", + "geoname_id": 7428592, + "sub_districts": [] + }, + { + "code": "610331", + "name": "太白", + "level": "THREE_LEVEL", + "geoname_id": 1793708, + "sub_districts": [] + }, + { + "code": "610302", + "name": "渭滨", + "level": "THREE_LEVEL", + "geoname_id": 6599416, + "sub_districts": [] + } + ] + }, + { + "code": "610700", + "name": "汉中", + "level": "TWO_LEVEL", + "geoname_id": 1808857, + "sub_districts": [ + { + "code": "610722", + "name": "城固", + "level": "THREE_LEVEL", + "geoname_id": 1815272, + "sub_districts": [] + }, + { + "code": "610730", + "name": "佛坪", + "level": "THREE_LEVEL", + "geoname_id": 1811104, + "sub_districts": [] + }, + { + "code": "610702", + "name": "汉台", + "level": "THREE_LEVEL", + "geoname_id": 6599419, + "sub_districts": [] + }, + { + "code": "610729", + "name": "留坝", + "level": "THREE_LEVEL", + "geoname_id": 1803208, + "sub_districts": [] + }, + { + "code": "610727", + "name": "略阳", + "level": "THREE_LEVEL", + "geoname_id": 1802135, + "sub_districts": [] + }, + { + "code": "610725", + "name": "勉县", + "level": "THREE_LEVEL", + "geoname_id": 1800630, + "sub_districts": [] + }, + { + "code": "610726", + "name": "宁强", + "level": "THREE_LEVEL", + "geoname_id": 1799361, + "sub_districts": [] + }, + { + "code": "6107030000001", + "name": "南郑", + "level": "THREE_LEVEL", + "geoname_id": 1799555, + "sub_districts": [] + }, + { + "code": "610724", + "name": "西乡", + "level": "THREE_LEVEL", + "geoname_id": 1788203, + "sub_districts": [] + }, + { + "code": "610723", + "name": "洋县", + "level": "THREE_LEVEL", + "geoname_id": 1787266, + "sub_districts": [] + }, + { + "code": "610728", + "name": "镇巴", + "level": "THREE_LEVEL", + "geoname_id": 1784739, + "sub_districts": [] + } + ] + }, + { + "code": "611000", + "name": "商洛", + "level": "TWO_LEVEL", + "geoname_id": 1796165, + "sub_districts": [ + { + "code": "611022", + "name": "丹凤", + "level": "THREE_LEVEL", + "geoname_id": 1813883, + "sub_districts": [] + }, + { + "code": "611021", + "name": "洛南", + "level": "THREE_LEVEL", + "geoname_id": 1801869, + "sub_districts": [] + }, + { + "code": "611023", + "name": "商南", + "level": "THREE_LEVEL", + "geoname_id": 1796151, + "sub_districts": [] + }, + { + "code": "611024", + "name": "山阳", + "level": "THREE_LEVEL", + "geoname_id": 1795903, + "sub_districts": [] + }, + { + "code": "611002", + "name": "商州", + "level": "THREE_LEVEL", + "geoname_id": 6599421, + "sub_districts": [] + }, + { + "code": "611025", + "name": "镇安", + "level": "THREE_LEVEL", + "geoname_id": 1784742, + "sub_districts": [] + }, + { + "code": "611026", + "name": "柞水", + "level": "THREE_LEVEL", + "geoname_id": 1784795, + "sub_districts": [] + } + ] + }, + { + "code": "610200", + "name": "铜川", + "level": "TWO_LEVEL", + "geoname_id": 7064006, + "sub_districts": [ + { + "code": "610202", + "name": "王益", + "level": "THREE_LEVEL", + "geoname_id": 6599414, + "sub_districts": [] + }, + { + "code": "610222", + "name": "宜君", + "level": "THREE_LEVEL", + "geoname_id": 1786692, + "sub_districts": [] + }, + { + "code": "610203", + "name": "印台", + "level": "THREE_LEVEL", + "geoname_id": 6599415, + "sub_districts": [] + }, + { + "code": "610204", + "name": "耀州", + "level": "THREE_LEVEL", + "geoname_id": 1786901, + "sub_districts": [] + } + ] + }, + { + "code": "610500", + "name": "渭南", + "level": "TWO_LEVEL", + "geoname_id": 1791636, + "sub_districts": [ + { + "code": "610527", + "name": "白水", + "level": "THREE_LEVEL", + "geoname_id": 1817355, + "sub_districts": [] + }, + { + "code": "610525", + "name": "澄城", + "level": "THREE_LEVEL", + "geoname_id": 1815300, + "sub_districts": [] + }, + { + "code": "610523", + "name": "大荔", + "level": "THREE_LEVEL", + "geoname_id": 1814024, + "sub_districts": [] + }, + { + "code": "610528", + "name": "富平", + "level": "THREE_LEVEL", + "geoname_id": 1810945, + "sub_districts": [] + }, + { + "code": "610581", + "name": "韩城", + "level": "THREE_LEVEL", + "geoname_id": 1808978, + "sub_districts": [] + }, + { + "code": "610582", + "name": "华阴", + "level": "THREE_LEVEL", + "geoname_id": 1806982, + "sub_districts": [] + }, + { + "code": "610524", + "name": "合阳", + "level": "THREE_LEVEL", + "geoname_id": 1808209, + "sub_districts": [] + }, + { + "code": "610503", + "name": "华州", + "level": "THREE_LEVEL", + "geoname_id": 1807005, + "sub_districts": [] + }, + { + "code": "610502", + "name": "临渭", + "level": "THREE_LEVEL", + "geoname_id": 7577125, + "sub_districts": [] + }, + { + "code": "610526", + "name": "蒲城", + "level": "THREE_LEVEL", + "geoname_id": 1798528, + "sub_districts": [] + }, + { + "code": "610522", + "name": "潼关", + "level": "THREE_LEVEL", + "geoname_id": 1792673, + "sub_districts": [] + } + ] + }, + { + "code": "610100", + "name": "西安", + "level": "TWO_LEVEL", + "geoname_id": 1790630, + "sub_districts": [ + { + "code": "610103", + "name": "碑林", + "level": "THREE_LEVEL", + "geoname_id": 6599410, + "sub_districts": [] + }, + { + "code": "610111", + "name": "灞桥", + "level": "THREE_LEVEL", + "geoname_id": 2001376, + "sub_districts": [] + }, + { + "code": "610116", + "name": "长安", + "level": "THREE_LEVEL", + "geoname_id": 1815800, + "sub_districts": [] + }, + { + "code": "610117", + "name": "高陵", + "level": "THREE_LEVEL", + "geoname_id": 1810475, + "sub_districts": [] + }, + { + "code": "6101180000001", + "name": "鄠邑", + "level": "THREE_LEVEL", + "geoname_id": 610125, + "sub_districts": [] + }, + { + "code": "610104", + "name": "莲湖", + "level": "THREE_LEVEL", + "geoname_id": 2001418, + "sub_districts": [] + }, + { + "code": "610115", + "name": "临潼", + "level": "THREE_LEVEL", + "geoname_id": 1803345, + "sub_districts": [] + }, + { + "code": "610122", + "name": "蓝田", + "level": "THREE_LEVEL", + "geoname_id": 1804446, + "sub_districts": [] + }, + { + "code": "610112", + "name": "未央", + "level": "THREE_LEVEL", + "geoname_id": 2001377, + "sub_districts": [] + }, + { + "code": "610102", + "name": "新城", + "level": "THREE_LEVEL", + "geoname_id": 2001379, + "sub_districts": [] + }, + { + "code": "610114", + "name": "阎良", + "level": "THREE_LEVEL", + "geoname_id": 6599411, + "sub_districts": [] + }, + { + "code": "610113", + "name": "雁塔", + "level": "THREE_LEVEL", + "geoname_id": 2001381, + "sub_districts": [] + }, + { + "code": "610124", + "name": "周至", + "level": "THREE_LEVEL", + "geoname_id": 1784075, + "sub_districts": [] + } + ] + }, + { + "code": "610400", + "name": "咸阳", + "level": "TWO_LEVEL", + "geoname_id": 1790353, + "sub_districts": [ + { + "code": "6104820000001", + "name": "彬州", + "level": "THREE_LEVEL", + "geoname_id": 610427, + "sub_districts": [] + }, + { + "code": "610430", + "name": "淳化", + "level": "THREE_LEVEL", + "geoname_id": 1814779, + "sub_districts": [] + }, + { + "code": "610428", + "name": "长武", + "level": "THREE_LEVEL", + "geoname_id": 1815508, + "sub_districts": [] + }, + { + "code": "610423", + "name": "泾阳", + "level": "THREE_LEVEL", + "geoname_id": 1805555, + "sub_districts": [] + }, + { + "code": "610425", + "name": "礼泉", + "level": "THREE_LEVEL", + "geoname_id": 1803280, + "sub_districts": [] + }, + { + "code": "610402", + "name": "秦都", + "level": "THREE_LEVEL", + "geoname_id": 2001073, + "sub_districts": [] + }, + { + "code": "610424", + "name": "乾县", + "level": "THREE_LEVEL", + "geoname_id": 1798229, + "sub_districts": [] + }, + { + "code": "610422", + "name": "三原", + "level": "THREE_LEVEL", + "geoname_id": 1796520, + "sub_districts": [] + }, + { + "code": "610404", + "name": "渭城", + "level": "THREE_LEVEL", + "geoname_id": 2001074, + "sub_districts": [] + }, + { + "code": "610431", + "name": "武功", + "level": "THREE_LEVEL", + "geoname_id": 1791261, + "sub_districts": [] + }, + { + "code": "610481", + "name": "兴平", + "level": "THREE_LEVEL", + "geoname_id": 1788947, + "sub_districts": [] + }, + { + "code": "610429", + "name": "旬邑", + "level": "THREE_LEVEL", + "geoname_id": 1787869, + "sub_districts": [] + }, + { + "code": "610403", + "name": "杨陵", + "level": "THREE_LEVEL", + "geoname_id": 1787458, + "sub_districts": [] + }, + { + "code": "610426", + "name": "永寿", + "level": "THREE_LEVEL", + "geoname_id": 1786262, + "sub_districts": [] + } + ] + }, + { + "code": "610600", + "name": "延安", + "level": "TWO_LEVEL", + "geoname_id": 1787763, + "sub_districts": [ + { + "code": "6106030000001", + "name": "安塞", + "level": "THREE_LEVEL", + "geoname_id": 1817976, + "sub_districts": [] + }, + { + "code": "610602", + "name": "宝塔", + "level": "THREE_LEVEL", + "geoname_id": 6599413, + "sub_districts": [] + }, + { + "code": "610628", + "name": "富县", + "level": "THREE_LEVEL", + "geoname_id": 1810877, + "sub_districts": [] + }, + { + "code": "610627", + "name": "甘泉", + "level": "THREE_LEVEL", + "geoname_id": 1810679, + "sub_districts": [] + }, + { + "code": "610631", + "name": "黄龙", + "level": "THREE_LEVEL", + "geoname_id": 1807357, + "sub_districts": [] + }, + { + "code": "610632", + "name": "黄陵", + "level": "THREE_LEVEL", + "geoname_id": 1807378, + "sub_districts": [] + }, + { + "code": "610629", + "name": "洛川", + "level": "THREE_LEVEL", + "geoname_id": 1801979, + "sub_districts": [] + }, + { + "code": "610626", + "name": "吴起", + "level": "THREE_LEVEL", + "geoname_id": 1791025, + "sub_districts": [] + }, + { + "code": "610621", + "name": "延长", + "level": "THREE_LEVEL", + "geoname_id": 1787748, + "sub_districts": [] + }, + { + "code": "610622", + "name": "延川", + "level": "THREE_LEVEL", + "geoname_id": 1787734, + "sub_districts": [] + }, + { + "code": "610630", + "name": "宜川", + "level": "THREE_LEVEL", + "geoname_id": 1786748, + "sub_districts": [] + }, + { + "code": "610625", + "name": "志丹", + "level": "THREE_LEVEL", + "geoname_id": 1784547, + "sub_districts": [] + }, + { + "code": "6106810000001", + "name": "子长", + "level": "THREE_LEVEL", + "geoname_id": 1783748, + "sub_districts": [] + } + ] + }, + { + "code": "610800", + "name": "榆林", + "level": "TWO_LEVEL", + "geoname_id": 1785769, + "sub_districts": [ + { + "code": "610825", + "name": "定边", + "level": "THREE_LEVEL", + "geoname_id": 1812822, + "sub_districts": [] + }, + { + "code": "610822", + "name": "府谷", + "level": "THREE_LEVEL", + "geoname_id": 1811037, + "sub_districts": [] + }, + { + "code": "610803", + "name": "横山", + "level": "THREE_LEVEL", + "geoname_id": 1808407, + "sub_districts": [] + }, + { + "code": "610824", + "name": "靖边", + "level": "THREE_LEVEL", + "geoname_id": 1805690, + "sub_districts": [] + }, + { + "code": "610828", + "name": "佳县", + "level": "THREE_LEVEL", + "geoname_id": 1805958, + "sub_districts": [] + }, + { + "code": "610827", + "name": "米脂", + "level": "THREE_LEVEL", + "geoname_id": 1800424, + "sub_districts": [] + }, + { + "code": "610830", + "name": "清涧", + "level": "THREE_LEVEL", + "geoname_id": 1797867, + "sub_districts": [] + }, + { + "code": "610826", + "name": "绥德", + "level": "THREE_LEVEL", + "geoname_id": 1793904, + "sub_districts": [] + }, + { + "code": "6108810000001", + "name": "神木", + "level": "THREE_LEVEL", + "geoname_id": 1795616, + "sub_districts": [] + }, + { + "code": "610829", + "name": "吴堡", + "level": "THREE_LEVEL", + "geoname_id": 1791353, + "sub_districts": [] + }, + { + "code": "610802", + "name": "榆阳", + "level": "THREE_LEVEL", + "geoname_id": 6599412, + "sub_districts": [] + }, + { + "code": "610831", + "name": "子洲", + "level": "THREE_LEVEL", + "geoname_id": 1783667, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "12", + "name": "天津", + "level": "ONE_LEVEL", + "geoname_id": 1792943, + "sub_districts": [ + { + "code": "120000", + "name": "天津", + "level": "TWO_LEVEL", + "geoname_id": 1792947, + "sub_districts": [ + { + "code": "1201130000000", + "name": "北辰", + "level": "THREE_LEVEL", + "geoname_id": 1816677, + "sub_districts": [] + }, + { + "code": "120115", + "name": "宝坻", + "level": "THREE_LEVEL", + "geoname_id": 1816968, + "sub_districts": [] + }, + { + "code": "120116", + "name": "滨海", + "level": "THREE_LEVEL", + "geoname_id": 120116, + "sub_districts": [] + }, + { + "code": "120110", + "name": "东丽", + "level": "THREE_LEVEL", + "geoname_id": 1812452, + "sub_districts": [] + }, + { + "code": "120105", + "name": "河北", + "level": "THREE_LEVEL", + "geoname_id": 8426818, + "sub_districts": [] + }, + { + "code": "120102", + "name": "河东", + "level": "THREE_LEVEL", + "geoname_id": 1808724, + "sub_districts": [] + }, + { + "code": "120101", + "name": "和平", + "level": "THREE_LEVEL", + "geoname_id": 1808339, + "sub_districts": [] + }, + { + "code": "1201060000000", + "name": "红桥", + "level": "THREE_LEVEL", + "geoname_id": 1808042, + "sub_districts": [] + }, + { + "code": "120103", + "name": "河西", + "level": "THREE_LEVEL", + "geoname_id": 1808215, + "sub_districts": [] + }, + { + "code": "120118", + "name": "静海", + "level": "THREE_LEVEL", + "geoname_id": 1805657, + "sub_districts": [] + }, + { + "code": "120112", + "name": "津南", + "level": "THREE_LEVEL", + "geoname_id": 1799971, + "sub_districts": [] + }, + { + "code": "1201190000001", + "name": "蓟州", + "level": "THREE_LEVEL", + "geoname_id": 120225, + "sub_districts": [] + }, + { + "code": "120117", + "name": "宁河", + "level": "THREE_LEVEL", + "geoname_id": 1799380, + "sub_districts": [] + }, + { + "code": "120104", + "name": "南开", + "level": "THREE_LEVEL", + "geoname_id": 1799949, + "sub_districts": [] + }, + { + "code": "120114", + "name": "武清", + "level": "THREE_LEVEL", + "geoname_id": 120114, + "sub_districts": [] + }, + { + "code": "120111", + "name": "西青", + "level": "THREE_LEVEL", + "geoname_id": 1789395, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "71", + "name": "台湾", + "level": "ONE_LEVEL", + "geoname_id": 7280291, + "sub_districts": [] + }, + { + "code": "81", + "name": "香港", + "level": "ONE_LEVEL", + "geoname_id": 1819729, + "sub_districts": [] + }, + { + "code": "65", + "name": "新疆", + "level": "ONE_LEVEL", + "geoname_id": 1529047, + "sub_districts": [ + { + "code": "652900", + "name": "阿克苏", + "level": "TWO_LEVEL", + "geoname_id": 1529658, + "sub_districts": [ + { + "code": "652901", + "name": "阿克苏", + "level": "THREE_LEVEL", + "geoname_id": 1529655, + "sub_districts": [] + }, + { + "code": "652928", + "name": "阿瓦提", + "level": "THREE_LEVEL", + "geoname_id": 1529633, + "sub_districts": [] + }, + { + "code": "652926", + "name": "拜城", + "level": "THREE_LEVEL", + "geoname_id": 1529628, + "sub_districts": [] + }, + { + "code": "6529020000001", + "name": "库车", + "level": "THREE_LEVEL", + "geoname_id": 1529360, + "sub_districts": [] + }, + { + "code": "652929", + "name": "柯坪", + "level": "THREE_LEVEL", + "geoname_id": 1529407, + "sub_districts": [] + }, + { + "code": "652924", + "name": "沙雅", + "level": "THREE_LEVEL", + "geoname_id": 1529074, + "sub_districts": [] + }, + { + "code": "652922", + "name": "温宿", + "level": "THREE_LEVEL", + "geoname_id": 1529087, + "sub_districts": [] + }, + { + "code": "652927", + "name": "乌什", + "level": "THREE_LEVEL", + "geoname_id": 1529082, + "sub_districts": [] + }, + { + "code": "652925", + "name": "新和", + "level": "THREE_LEVEL", + "geoname_id": 1529048, + "sub_districts": [] + } + ] + }, + { + "code": "659002", + "name": "阿拉尔", + "level": "TWO_LEVEL", + "geoname_id": 8080717, + "sub_districts": [ + { + "code": "659002", + "name": "阿拉尔", + "level": "THREE_LEVEL", + "geoname_id": 1529641, + "sub_districts": [] + } + ] + }, + { + "code": "654300", + "name": "阿勒泰", + "level": "TWO_LEVEL", + "geoname_id": 1529650, + "sub_districts": [ + { + "code": "654301", + "name": "阿勒泰", + "level": "THREE_LEVEL", + "geoname_id": 1529649, + "sub_districts": [] + }, + { + "code": "654321", + "name": "布尔津", + "level": "THREE_LEVEL", + "geoname_id": 1529572, + "sub_districts": [] + }, + { + "code": "654323", + "name": "福海", + "level": "THREE_LEVEL", + "geoname_id": 1529507, + "sub_districts": [] + }, + { + "code": "654322", + "name": "富蕴", + "level": "THREE_LEVEL", + "geoname_id": 1529503, + "sub_districts": [] + }, + { + "code": "654324", + "name": "哈巴河", + "level": "THREE_LEVEL", + "geoname_id": 1529488, + "sub_districts": [] + }, + { + "code": "654326", + "name": "吉木乃", + "level": "THREE_LEVEL", + "geoname_id": 1528988, + "sub_districts": [] + }, + { + "code": "654325", + "name": "青河", + "level": "THREE_LEVEL", + "geoname_id": 1529254, + "sub_districts": [] + } + ] + }, + { + "code": "652700", + "name": "博尔塔拉", + "level": "TWO_LEVEL", + "geoname_id": 1529581, + "sub_districts": [ + { + "code": "652702", + "name": "阿拉山口", + "level": "THREE_LEVEL", + "geoname_id": 11606030, + "sub_districts": [] + }, + { + "code": "652701", + "name": "博乐", + "level": "THREE_LEVEL", + "geoname_id": 1529586, + "sub_districts": [] + }, + { + "code": "652722", + "name": "精河", + "level": "THREE_LEVEL", + "geoname_id": 1529416, + "sub_districts": [] + }, + { + "code": "652723", + "name": "温泉", + "level": "THREE_LEVEL", + "geoname_id": 1529089, + "sub_districts": [] + } + ] + }, + { + "code": "659005", + "name": "北屯", + "level": "TWO_LEVEL", + "geoname_id": 1529594, + "sub_districts": [ + { + "code": "659005", + "name": "北屯", + "level": "THREE_LEVEL", + "geoname_id": 659005, + "sub_districts": [] + } + ] + }, + { + "code": "652800", + "name": "巴音郭楞", + "level": "TWO_LEVEL", + "geoname_id": 1529604, + "sub_districts": [ + { + "code": "652829", + "name": "博湖", + "level": "THREE_LEVEL", + "geoname_id": 1529588, + "sub_districts": [] + }, + { + "code": "652827", + "name": "和静", + "level": "THREE_LEVEL", + "geoname_id": 1529475, + "sub_districts": [] + }, + { + "code": "652828", + "name": "和硕", + "level": "THREE_LEVEL", + "geoname_id": 1529451, + "sub_districts": [] + }, + { + "code": "652801", + "name": "库尔勒", + "level": "THREE_LEVEL", + "geoname_id": 1529375, + "sub_districts": [] + }, + { + "code": "652822", + "name": "轮台", + "level": "THREE_LEVEL", + "geoname_id": 1529332, + "sub_districts": [] + }, + { + "code": "652825", + "name": "且末", + "level": "THREE_LEVEL", + "geoname_id": 1280248, + "sub_districts": [] + }, + { + "code": "652824", + "name": "若羌", + "level": "THREE_LEVEL", + "geoname_id": 1280120, + "sub_districts": [] + }, + { + "code": "652823", + "name": "尉犁", + "level": "THREE_LEVEL", + "geoname_id": 1529000, + "sub_districts": [] + }, + { + "code": "652826", + "name": "焉耆", + "level": "THREE_LEVEL", + "geoname_id": 1529030, + "sub_districts": [] + } + ] + }, + { + "code": "652300", + "name": "昌吉", + "level": "TWO_LEVEL", + "geoname_id": 1529568, + "sub_districts": [ + { + "code": "652301", + "name": "昌吉", + "level": "THREE_LEVEL", + "geoname_id": 1529569, + "sub_districts": [] + }, + { + "code": "652302", + "name": "阜康", + "level": "THREE_LEVEL", + "geoname_id": 1529505, + "sub_districts": [] + }, + { + "code": "652323", + "name": "呼图壁", + "level": "THREE_LEVEL", + "geoname_id": 1529436, + "sub_districts": [] + }, + { + "code": "652327", + "name": "吉木萨尔", + "level": "THREE_LEVEL", + "geoname_id": 1529418, + "sub_districts": [] + }, + { + "code": "652328", + "name": "木垒", + "level": "THREE_LEVEL", + "geoname_id": 1529302, + "sub_districts": [] + }, + { + "code": "652324", + "name": "玛纳斯", + "level": "THREE_LEVEL", + "geoname_id": 1529320, + "sub_districts": [] + }, + { + "code": "652325", + "name": "奇台", + "level": "THREE_LEVEL", + "geoname_id": 1529249, + "sub_districts": [] + } + ] + }, + { + "code": "650500", + "name": "哈密", + "level": "TWO_LEVEL", + "geoname_id": 1529484, + "sub_districts": [ + { + "code": "650521", + "name": "巴里坤", + "level": "THREE_LEVEL", + "geoname_id": 1529612, + "sub_districts": [] + }, + { + "code": "650522", + "name": "伊吾", + "level": "THREE_LEVEL", + "geoname_id": 1529006, + "sub_districts": [] + }, + { + "code": "650502", + "name": "伊州", + "level": "THREE_LEVEL", + "geoname_id": 650502, + "sub_districts": [] + } + ] + }, + { + "code": "653200", + "name": "和田", + "level": "TWO_LEVEL", + "geoname_id": 1281018, + "sub_districts": [ + { + "code": "653225", + "name": "策勒", + "level": "THREE_LEVEL", + "geoname_id": 1280226, + "sub_districts": [] + }, + { + "code": "653201", + "name": "和田市", + "level": "THREE_LEVEL", + "geoname_id": 1281017, + "sub_districts": [] + }, + { + "code": "653221", + "name": "和田县", + "level": "THREE_LEVEL", + "geoname_id": 1281016, + "sub_districts": [] + }, + { + "code": "653224", + "name": "洛浦", + "level": "THREE_LEVEL", + "geoname_id": 1280689, + "sub_districts": [] + }, + { + "code": "653227", + "name": "民丰", + "level": "THREE_LEVEL", + "geoname_id": 1280554, + "sub_districts": [] + }, + { + "code": "653222", + "name": "墨玉", + "level": "THREE_LEVEL", + "geoname_id": 1280540, + "sub_districts": [] + }, + { + "code": "653223", + "name": "皮山", + "level": "THREE_LEVEL", + "geoname_id": 1280326, + "sub_districts": [] + }, + { + "code": "653226", + "name": "于田", + "level": "THREE_LEVEL", + "geoname_id": 1279539, + "sub_districts": [] + } + ] + }, + { + "code": "659010", + "name": "胡杨河", + "level": "TWO_LEVEL", + "geoname_id": 659010, + "sub_districts": [ + { + "code": "659010", + "name": "胡杨河", + "level": "THREE_LEVEL", + "geoname_id": 6590100, + "sub_districts": [] + } + ] + }, + { + "code": "659008", + "name": "可克达拉", + "level": "TWO_LEVEL", + "geoname_id": 659008, + "sub_districts": [ + { + "code": "659008", + "name": "可克达拉", + "level": "THREE_LEVEL", + "geoname_id": 65900802, + "sub_districts": [] + } + ] + }, + { + "code": "650200", + "name": "克拉玛依", + "level": "TWO_LEVEL", + "geoname_id": 1529401, + "sub_districts": [ + { + "code": "6502040000000", + "name": "白碱滩", + "level": "THREE_LEVEL", + "geoname_id": 8079494, + "sub_districts": [] + }, + { + "code": "650202", + "name": "独山子", + "level": "THREE_LEVEL", + "geoname_id": 8079496, + "sub_districts": [] + }, + { + "code": "6502030000000", + "name": "克拉玛依", + "level": "THREE_LEVEL", + "geoname_id": 8079493, + "sub_districts": [] + }, + { + "code": "650205", + "name": "乌尔禾", + "level": "THREE_LEVEL", + "geoname_id": 8079495, + "sub_districts": [] + } + ] + }, + { + "code": "653100", + "name": "喀什", + "level": "TWO_LEVEL", + "geoname_id": 1280848, + "sub_districts": [ + { + "code": "653130", + "name": "巴楚", + "level": "THREE_LEVEL", + "geoname_id": 1281721, + "sub_districts": [] + }, + { + "code": "653129", + "name": "伽师", + "level": "THREE_LEVEL", + "geoname_id": 1280958, + "sub_districts": [] + }, + { + "code": "653101", + "name": "喀什", + "level": "THREE_LEVEL", + "geoname_id": 1280847, + "sub_districts": [] + }, + { + "code": "653127", + "name": "麦盖提", + "level": "THREE_LEVEL", + "geoname_id": 1280603, + "sub_districts": [] + }, + { + "code": "653125", + "name": "莎车", + "level": "THREE_LEVEL", + "geoname_id": 1280036, + "sub_districts": [] + }, + { + "code": "653121", + "name": "疏附", + "level": "THREE_LEVEL", + "geoname_id": 1279994, + "sub_districts": [] + }, + { + "code": "653122", + "name": "疏勒", + "level": "THREE_LEVEL", + "geoname_id": 1279985, + "sub_districts": [] + }, + { + "code": "653131", + "name": "塔什库尔干", + "level": "THREE_LEVEL", + "geoname_id": 1279900, + "sub_districts": [] + }, + { + "code": "653126", + "name": "叶城", + "level": "THREE_LEVEL", + "geoname_id": 1279601, + "sub_districts": [] + }, + { + "code": "653123", + "name": "英吉沙", + "level": "THREE_LEVEL", + "geoname_id": 1279589, + "sub_districts": [] + }, + { + "code": "653128", + "name": "岳普湖", + "level": "THREE_LEVEL", + "geoname_id": 1279563, + "sub_districts": [] + }, + { + "code": "653124", + "name": "泽普", + "level": "THREE_LEVEL", + "geoname_id": 1279500, + "sub_districts": [] + } + ] + }, + { + "code": "659009", + "name": "昆玉", + "level": "TWO_LEVEL", + "geoname_id": 659009, + "sub_districts": [ + { + "code": "659009", + "name": "昆玉", + "level": "THREE_LEVEL", + "geoname_id": 65900902, + "sub_districts": [] + } + ] + }, + { + "code": "653000", + "name": "克孜勒苏", + "level": "TWO_LEVEL", + "geoname_id": 1280828, + "sub_districts": [ + { + "code": "653023", + "name": "阿合奇", + "level": "THREE_LEVEL", + "geoname_id": 1529661, + "sub_districts": [] + }, + { + "code": "653022", + "name": "阿克陶", + "level": "THREE_LEVEL", + "geoname_id": 1281773, + "sub_districts": [] + }, + { + "code": "653001", + "name": "阿图什", + "level": "THREE_LEVEL", + "geoname_id": 1281742, + "sub_districts": [] + }, + { + "code": "653024", + "name": "乌恰", + "level": "THREE_LEVEL", + "geoname_id": 1279782, + "sub_districts": [] + } + ] + }, + { + "code": "659007", + "name": "双河", + "level": "TWO_LEVEL", + "geoname_id": 659007, + "sub_districts": [ + { + "code": "659007", + "name": "双河", + "level": "THREE_LEVEL", + "geoname_id": 65900702, + "sub_districts": [] + } + ] + }, + { + "code": "659001", + "name": "石河子", + "level": "TWO_LEVEL", + "geoname_id": 1529195, + "sub_districts": [ + { + "code": "659001", + "name": "石河子", + "level": "THREE_LEVEL", + "geoname_id": 1529194, + "sub_districts": [] + } + ] + }, + { + "code": "654200", + "name": "塔城", + "level": "TWO_LEVEL", + "geoname_id": 1529166, + "sub_districts": [ + { + "code": "654221", + "name": "额敏", + "level": "THREE_LEVEL", + "geoname_id": 1529520, + "sub_districts": [] + }, + { + "code": "654226", + "name": "和布克赛尔", + "level": "THREE_LEVEL", + "geoname_id": 1529472, + "sub_districts": [] + }, + { + "code": "6542030000001", + "name": "沙湾", + "level": "THREE_LEVEL", + "geoname_id": 1529209, + "sub_districts": [] + }, + { + "code": "654201", + "name": "塔城", + "level": "THREE_LEVEL", + "geoname_id": 1529165, + "sub_districts": [] + }, + { + "code": "654224", + "name": "托里", + "level": "THREE_LEVEL", + "geoname_id": 1529123, + "sub_districts": [] + }, + { + "code": "654202", + "name": "乌苏", + "level": "THREE_LEVEL", + "geoname_id": 1529098, + "sub_districts": [] + }, + { + "code": "654225", + "name": "裕民", + "level": "THREE_LEVEL", + "geoname_id": 1528997, + "sub_districts": [] + } + ] + }, + { + "code": "650400", + "name": "吐鲁番", + "level": "TWO_LEVEL", + "geoname_id": 1529111, + "sub_districts": [ + { + "code": "650402", + "name": "高昌", + "level": "THREE_LEVEL", + "geoname_id": 650402, + "sub_districts": [] + }, + { + "code": "650421", + "name": "鄯善", + "level": "THREE_LEVEL", + "geoname_id": 1529214, + "sub_districts": [] + }, + { + "code": "650422", + "name": "托克逊", + "level": "THREE_LEVEL", + "geoname_id": 1529126, + "sub_districts": [] + } + ] + }, + { + "code": "659006", + "name": "铁门关", + "level": "TWO_LEVEL", + "geoname_id": 659006, + "sub_districts": [ + { + "code": "659006", + "name": "铁门关", + "level": "THREE_LEVEL", + "geoname_id": 65900602, + "sub_districts": [] + } + ] + }, + { + "code": "659003", + "name": "图木舒克", + "level": "TWO_LEVEL", + "geoname_id": 8080762, + "sub_districts": [ + { + "code": "659003", + "name": "图木舒克", + "level": "THREE_LEVEL", + "geoname_id": 12022102, + "sub_districts": [] + } + ] + }, + { + "code": "659004", + "name": "五家渠", + "level": "TWO_LEVEL", + "geoname_id": 8079473, + "sub_districts": [ + { + "code": "659004", + "name": "五家渠", + "level": "THREE_LEVEL", + "geoname_id": 1529085, + "sub_districts": [] + } + ] + }, + { + "code": "650100", + "name": "乌鲁木齐", + "level": "TWO_LEVEL", + "geoname_id": 1529102, + "sub_districts": [ + { + "code": "650107", + "name": "达坂城", + "level": "THREE_LEVEL", + "geoname_id": 8078641, + "sub_districts": [] + }, + { + "code": "650109", + "name": "米东", + "level": "THREE_LEVEL", + "geoname_id": 1529307, + "sub_districts": [] + }, + { + "code": "650105", + "name": "水磨沟", + "level": "THREE_LEVEL", + "geoname_id": 8075951, + "sub_districts": [] + }, + { + "code": "650103", + "name": "沙依巴克", + "level": "THREE_LEVEL", + "geoname_id": 9275960, + "sub_districts": [] + }, + { + "code": "650102", + "name": "天山", + "level": "THREE_LEVEL", + "geoname_id": 7874240, + "sub_districts": [] + }, + { + "code": "650106", + "name": "头屯河", + "level": "THREE_LEVEL", + "geoname_id": 8078640, + "sub_districts": [] + }, + { + "code": "650121", + "name": "乌鲁木齐", + "level": "THREE_LEVEL", + "geoname_id": 1529100, + "sub_districts": [] + }, + { + "code": "650104", + "name": "新市", + "level": "THREE_LEVEL", + "geoname_id": 8075952, + "sub_districts": [] + } + ] + }, + { + "code": "6590110008001", + "name": "新星", + "level": "TWO_LEVEL", + "geoname_id": 60000483, + "sub_districts": [ + { + "code": "6590110000001", + "name": "新星", + "level": "THREE_LEVEL", + "geoname_id": 60000516, + "sub_districts": [] + } + ] + }, + { + "code": "654000", + "name": "伊犁", + "level": "TWO_LEVEL", + "geoname_id": 1529434, + "sub_districts": [ + { + "code": "654022", + "name": "察布查尔", + "level": "THREE_LEVEL", + "geoname_id": 1529278, + "sub_districts": [] + }, + { + "code": "654024", + "name": "巩留", + "level": "THREE_LEVEL", + "geoname_id": 1529497, + "sub_districts": [] + }, + { + "code": "654023", + "name": "霍城", + "level": "THREE_LEVEL", + "geoname_id": 11694038, + "sub_districts": [] + }, + { + "code": "654004", + "name": "霍尔果斯", + "level": "THREE_LEVEL", + "geoname_id": 11980795, + "sub_districts": [] + }, + { + "code": "654003", + "name": "奎屯", + "level": "THREE_LEVEL", + "geoname_id": 1529353, + "sub_districts": [] + }, + { + "code": "654028", + "name": "尼勒克", + "level": "THREE_LEVEL", + "geoname_id": 1529289, + "sub_districts": [] + }, + { + "code": "654027", + "name": "特克斯", + "level": "THREE_LEVEL", + "geoname_id": 1529145, + "sub_districts": [] + }, + { + "code": "654025", + "name": "新源", + "level": "THREE_LEVEL", + "geoname_id": 1529045, + "sub_districts": [] + }, + { + "code": "654002", + "name": "伊宁市", + "level": "THREE_LEVEL", + "geoname_id": 1529012, + "sub_districts": [] + }, + { + "code": "654021", + "name": "伊宁县", + "level": "THREE_LEVEL", + "geoname_id": 1529013, + "sub_districts": [] + }, + { + "code": "654026", + "name": "昭苏", + "level": "THREE_LEVEL", + "geoname_id": 1528991, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "54", + "name": "西藏", + "level": "ONE_LEVEL", + "geoname_id": 1279685, + "sub_districts": [ + { + "code": "542500", + "name": "阿里", + "level": "TWO_LEVEL", + "geoname_id": 1280456, + "sub_districts": [ + { + "code": "542527", + "name": "措勤", + "level": "THREE_LEVEL", + "geoname_id": 1281478, + "sub_districts": [] + }, + { + "code": "542523", + "name": "噶尔", + "level": "THREE_LEVEL", + "geoname_id": 1281220, + "sub_districts": [] + }, + { + "code": "542525", + "name": "革吉", + "level": "THREE_LEVEL", + "geoname_id": 1281206, + "sub_districts": [] + }, + { + "code": "542526", + "name": "改则", + "level": "THREE_LEVEL", + "geoname_id": 1281200, + "sub_districts": [] + }, + { + "code": "542521", + "name": "普兰", + "level": "THREE_LEVEL", + "geoname_id": 1281592, + "sub_districts": [] + }, + { + "code": "542524", + "name": "日土", + "level": "THREE_LEVEL", + "geoname_id": 1280115, + "sub_districts": [] + }, + { + "code": "542522", + "name": "札达", + "level": "THREE_LEVEL", + "geoname_id": 1279526, + "sub_districts": [] + } + ] + }, + { + "code": "540300", + "name": "昌都", + "level": "TWO_LEVEL", + "geoname_id": 1280280, + "sub_districts": [ + { + "code": "540330", + "name": "边坝", + "level": "THREE_LEVEL", + "geoname_id": 1281688, + "sub_districts": [] + }, + { + "code": "540326", + "name": "八宿", + "level": "THREE_LEVEL", + "geoname_id": 1281657, + "sub_districts": [] + }, + { + "code": "540325", + "name": "察雅", + "level": "THREE_LEVEL", + "geoname_id": 1279493, + "sub_districts": [] + }, + { + "code": "540324", + "name": "丁青", + "level": "THREE_LEVEL", + "geoname_id": 1281371, + "sub_districts": [] + }, + { + "code": "540322", + "name": "贡觉", + "level": "THREE_LEVEL", + "geoname_id": 1281166, + "sub_districts": [] + }, + { + "code": "540321", + "name": "江达", + "level": "THREE_LEVEL", + "geoname_id": 1280926, + "sub_districts": [] + }, + { + "code": "540302", + "name": "卡若", + "level": "THREE_LEVEL", + "geoname_id": 8041923, + "sub_districts": [] + }, + { + "code": "540329", + "name": "洛隆", + "level": "THREE_LEVEL", + "geoname_id": 1280723, + "sub_districts": [] + }, + { + "code": "540323", + "name": "类乌齐", + "level": "THREE_LEVEL", + "geoname_id": 1280141, + "sub_districts": [] + }, + { + "code": "540328", + "name": "芒康", + "level": "THREE_LEVEL", + "geoname_id": 1280605, + "sub_districts": [] + }, + { + "code": "540327", + "name": "左贡", + "level": "THREE_LEVEL", + "geoname_id": 1279433, + "sub_districts": [] + } + ] + }, + { + "code": "540100", + "name": "拉萨", + "level": "TWO_LEVEL", + "geoname_id": 1280737, + "sub_districts": [ + { + "code": "540102", + "name": "城关", + "level": "THREE_LEVEL", + "geoname_id": 6643440, + "sub_districts": [] + }, + { + "code": "540103", + "name": "堆龙德庆", + "level": "THREE_LEVEL", + "geoname_id": 1281329, + "sub_districts": [] + }, + { + "code": "540122", + "name": "当雄", + "level": "THREE_LEVEL", + "geoname_id": 1281423, + "sub_districts": [] + }, + { + "code": "5401040000001", + "name": "达孜", + "level": "THREE_LEVEL", + "geoname_id": 1281446, + "sub_districts": [] + }, + { + "code": "540121", + "name": "林周", + "level": "THREE_LEVEL", + "geoname_id": 1280717, + "sub_districts": [] + }, + { + "code": "540127", + "name": "墨竹工卡", + "level": "THREE_LEVEL", + "geoname_id": 1280638, + "sub_districts": [] + }, + { + "code": "540123", + "name": "尼木", + "level": "THREE_LEVEL", + "geoname_id": 1280401, + "sub_districts": [] + }, + { + "code": "540124", + "name": "曲水", + "level": "THREE_LEVEL", + "geoname_id": 1280180, + "sub_districts": [] + } + ] + }, + { + "code": "540400", + "name": "林芝", + "level": "TWO_LEVEL", + "geoname_id": 1280390, + "sub_districts": [ + { + "code": "540424", + "name": "波密", + "level": "THREE_LEVEL", + "geoname_id": 1281613, + "sub_districts": [] + }, + { + "code": "540402", + "name": "巴宜", + "level": "THREE_LEVEL", + "geoname_id": 540402, + "sub_districts": [] + }, + { + "code": "540425", + "name": "察隅", + "level": "THREE_LEVEL", + "geoname_id": 1279505, + "sub_districts": [] + }, + { + "code": "540421", + "name": "工布江达", + "level": "THREE_LEVEL", + "geoname_id": 1281172, + "sub_districts": [] + }, + { + "code": "540426", + "name": "朗县", + "level": "THREE_LEVEL", + "geoname_id": 1280486, + "sub_districts": [] + }, + { + "code": "540422", + "name": "米林", + "level": "THREE_LEVEL", + "geoname_id": 1280642, + "sub_districts": [] + }, + { + "code": "540423", + "name": "墨脱", + "level": "THREE_LEVEL", + "geoname_id": 1280587, + "sub_districts": [] + } + ] + }, + { + "code": "542400", + "name": "那曲", + "level": "TWO_LEVEL", + "geoname_id": 1280515, + "sub_districts": [ + { + "code": "5424240009001", + "name": "安多", + "level": "THREE_LEVEL", + "geoname_id": 1281765, + "sub_districts": [] + }, + { + "code": "5424270009001", + "name": "班戈", + "level": "THREE_LEVEL", + "geoname_id": 1281704, + "sub_districts": [] + }, + { + "code": "5424280009001", + "name": "巴青", + "level": "THREE_LEVEL", + "geoname_id": 1281669, + "sub_districts": [] + }, + { + "code": "5424220009001", + "name": "比如", + "level": "THREE_LEVEL", + "geoname_id": 1281623, + "sub_districts": [] + }, + { + "code": "5424210009001", + "name": "嘉黎", + "level": "THREE_LEVEL", + "geoname_id": 1280738, + "sub_districts": [] + }, + { + "code": "5424290009001", + "name": "尼玛", + "level": "THREE_LEVEL", + "geoname_id": 1280392, + "sub_districts": [] + }, + { + "code": "5424230009001", + "name": "聂荣", + "level": "THREE_LEVEL", + "geoname_id": 1280408, + "sub_districts": [] + }, + { + "code": "5424300009001", + "name": "双湖", + "level": "THREE_LEVEL", + "geoname_id": 542431, + "sub_districts": [] + }, + { + "code": "5424020009001", + "name": "色尼", + "level": "THREE_LEVEL", + "geoname_id": 542421, + "sub_districts": [] + }, + { + "code": "5424260009001", + "name": "索县", + "level": "THREE_LEVEL", + "geoname_id": 1279531, + "sub_districts": [] + }, + { + "code": "5424250009001", + "name": "申扎", + "level": "THREE_LEVEL", + "geoname_id": 1279770, + "sub_districts": [] + } + ] + }, + { + "code": "540200", + "name": "日喀则", + "level": "TWO_LEVEL", + "geoname_id": 1279713, + "sub_districts": [ + { + "code": "540226", + "name": "昂仁", + "level": "THREE_LEVEL", + "geoname_id": 1280467, + "sub_districts": [] + }, + { + "code": "540228", + "name": "白朗", + "level": "THREE_LEVEL", + "geoname_id": 1280425, + "sub_districts": [] + }, + { + "code": "540231", + "name": "定结", + "level": "THREE_LEVEL", + "geoname_id": 1281124, + "sub_districts": [] + }, + { + "code": "540223", + "name": "定日", + "level": "THREE_LEVEL", + "geoname_id": 1279749, + "sub_districts": [] + }, + { + "code": "540237", + "name": "岗巴", + "level": "THREE_LEVEL", + "geoname_id": 1281256, + "sub_districts": [] + }, + { + "code": "540234", + "name": "吉隆", + "level": "THREE_LEVEL", + "geoname_id": 1279429, + "sub_districts": [] + }, + { + "code": "540222", + "name": "江孜", + "level": "THREE_LEVEL", + "geoname_id": 1281118, + "sub_districts": [] + }, + { + "code": "540230", + "name": "康马", + "level": "THREE_LEVEL", + "geoname_id": 1280887, + "sub_districts": [] + }, + { + "code": "540225", + "name": "拉孜", + "level": "THREE_LEVEL", + "geoname_id": 1280181, + "sub_districts": [] + }, + { + "code": "540235", + "name": "聂拉木", + "level": "THREE_LEVEL", + "geoname_id": 1281484, + "sub_districts": [] + }, + { + "code": "540221", + "name": "南木林", + "level": "THREE_LEVEL", + "geoname_id": 8049689, + "sub_districts": [] + }, + { + "code": "540229", + "name": "仁布", + "level": "THREE_LEVEL", + "geoname_id": 1280277, + "sub_districts": [] + }, + { + "code": "540236", + "name": "萨嘎", + "level": "THREE_LEVEL", + "geoname_id": 1280110, + "sub_districts": [] + }, + { + "code": "540224", + "name": "萨迦", + "level": "THREE_LEVEL", + "geoname_id": 1280108, + "sub_districts": [] + }, + { + "code": "540202", + "name": "桑珠孜", + "level": "THREE_LEVEL", + "geoname_id": 1279715, + "sub_districts": [] + }, + { + "code": "540227", + "name": "谢通门", + "level": "THREE_LEVEL", + "geoname_id": 1281208, + "sub_districts": [] + }, + { + "code": "540233", + "name": "亚东", + "level": "THREE_LEVEL", + "geoname_id": 1279754, + "sub_districts": [] + }, + { + "code": "540232", + "name": "仲巴", + "level": "THREE_LEVEL", + "geoname_id": 1279497, + "sub_districts": [] + } + ] + }, + { + "code": "540500", + "name": "山南", + "level": "TWO_LEVEL", + "geoname_id": 1280019, + "sub_districts": [ + { + "code": "540526", + "name": "措美", + "level": "THREE_LEVEL", + "geoname_id": 1281491, + "sub_districts": [] + }, + { + "code": "540530", + "name": "错那", + "level": "THREE_LEVEL", + "geoname_id": 1281486, + "sub_districts": [] + }, + { + "code": "540522", + "name": "贡嘎", + "level": "THREE_LEVEL", + "geoname_id": 1281170, + "sub_districts": [] + }, + { + "code": "540528", + "name": "加查", + "level": "THREE_LEVEL", + "geoname_id": 1281138, + "sub_districts": [] + }, + { + "code": "540531", + "name": "浪卡子", + "level": "THREE_LEVEL", + "geoname_id": 1280520, + "sub_districts": [] + }, + { + "code": "540527", + "name": "洛扎", + "level": "THREE_LEVEL", + "geoname_id": 1280721, + "sub_districts": [] + }, + { + "code": "540529", + "name": "隆子", + "level": "THREE_LEVEL", + "geoname_id": 1280719, + "sub_districts": [] + }, + { + "code": "540502", + "name": "乃东", + "level": "THREE_LEVEL", + "geoname_id": 1280470, + "sub_districts": [] + }, + { + "code": "540524", + "name": "琼结", + "level": "THREE_LEVEL", + "geoname_id": 1280215, + "sub_districts": [] + }, + { + "code": "540525", + "name": "曲松", + "level": "THREE_LEVEL", + "geoname_id": 1280183, + "sub_districts": [] + }, + { + "code": "540523", + "name": "桑日", + "level": "THREE_LEVEL", + "geoname_id": 1280080, + "sub_districts": [] + }, + { + "code": "540521", + "name": "扎囊", + "level": "THREE_LEVEL", + "geoname_id": 1279488, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "53", + "name": "云南", + "level": "ONE_LEVEL", + "geoname_id": 1785694, + "sub_districts": [ + { + "code": "530500", + "name": "保山", + "level": "TWO_LEVEL", + "geoname_id": 1281672, + "sub_districts": [ + { + "code": "530524", + "name": "昌宁", + "level": "THREE_LEVEL", + "geoname_id": 1281541, + "sub_districts": [] + }, + { + "code": "530523", + "name": "龙陵", + "level": "THREE_LEVEL", + "geoname_id": 1280695, + "sub_districts": [] + }, + { + "code": "530502", + "name": "隆阳", + "level": "THREE_LEVEL", + "geoname_id": 6643310, + "sub_districts": [] + }, + { + "code": "530521", + "name": "施甸", + "level": "THREE_LEVEL", + "geoname_id": 1280007, + "sub_districts": [] + }, + { + "code": "530581", + "name": "腾冲", + "level": "THREE_LEVEL", + "geoname_id": 1279890, + "sub_districts": [] + } + ] + }, + { + "code": "532300", + "name": "楚雄", + "level": "TWO_LEVEL", + "geoname_id": 1814758, + "sub_districts": [ + { + "code": "532301", + "name": "楚雄", + "level": "THREE_LEVEL", + "geoname_id": 1814759, + "sub_districts": [] + }, + { + "code": "532326", + "name": "大姚", + "level": "THREE_LEVEL", + "geoname_id": 1813209, + "sub_districts": [] + }, + { + "code": "5323020000001", + "name": "禄丰", + "level": "THREE_LEVEL", + "geoname_id": 1802129, + "sub_districts": [] + }, + { + "code": "532323", + "name": "牟定", + "level": "THREE_LEVEL", + "geoname_id": 1800369, + "sub_districts": [] + }, + { + "code": "532324", + "name": "南华", + "level": "THREE_LEVEL", + "geoname_id": 1799997, + "sub_districts": [] + }, + { + "code": "532322", + "name": "双柏", + "level": "THREE_LEVEL", + "geoname_id": 1794767, + "sub_districts": [] + }, + { + "code": "532329", + "name": "武定", + "level": "THREE_LEVEL", + "geoname_id": 1791302, + "sub_districts": [] + }, + { + "code": "532325", + "name": "姚安", + "level": "THREE_LEVEL", + "geoname_id": 1787009, + "sub_districts": [] + }, + { + "code": "532328", + "name": "元谋", + "level": "THREE_LEVEL", + "geoname_id": 1786062, + "sub_districts": [] + }, + { + "code": "532327", + "name": "永仁", + "level": "THREE_LEVEL", + "geoname_id": 1786267, + "sub_districts": [] + } + ] + }, + { + "code": "533100", + "name": "德宏", + "level": "TWO_LEVEL", + "geoname_id": 1281381, + "sub_districts": [ + { + "code": "533124", + "name": "陇川", + "level": "THREE_LEVEL", + "geoname_id": 1280698, + "sub_districts": [] + }, + { + "code": "533122", + "name": "梁河", + "level": "THREE_LEVEL", + "geoname_id": 1280716, + "sub_districts": [] + }, + { + "code": "533103", + "name": "芒市", + "level": "THREE_LEVEL", + "geoname_id": 1280623, + "sub_districts": [] + }, + { + "code": "533102", + "name": "瑞丽", + "level": "THREE_LEVEL", + "geoname_id": 1280123, + "sub_districts": [] + }, + { + "code": "533123", + "name": "盈江", + "level": "THREE_LEVEL", + "geoname_id": 1279577, + "sub_districts": [] + } + ] + }, + { + "code": "532900", + "name": "大理", + "level": "TWO_LEVEL", + "geoname_id": 1814065, + "sub_districts": [ + { + "code": "532924", + "name": "宾川", + "level": "THREE_LEVEL", + "geoname_id": 1816363, + "sub_districts": [] + }, + { + "code": "532901", + "name": "大理", + "level": "THREE_LEVEL", + "geoname_id": 1814039, + "sub_districts": [] + }, + { + "code": "532930", + "name": "洱源", + "level": "THREE_LEVEL", + "geoname_id": 1281274, + "sub_districts": [] + }, + { + "code": "532932", + "name": "鹤庆", + "level": "THREE_LEVEL", + "geoname_id": 1808325, + "sub_districts": [] + }, + { + "code": "532931", + "name": "剑川", + "level": "THREE_LEVEL", + "geoname_id": 1280966, + "sub_districts": [] + }, + { + "code": "532925", + "name": "弥渡", + "level": "THREE_LEVEL", + "geoname_id": 1800543, + "sub_districts": [] + }, + { + "code": "532926", + "name": "南涧", + "level": "THREE_LEVEL", + "geoname_id": 1799978, + "sub_districts": [] + }, + { + "code": "532927", + "name": "巍山", + "level": "THREE_LEVEL", + "geoname_id": 1791612, + "sub_districts": [] + }, + { + "code": "532923", + "name": "祥云", + "level": "THREE_LEVEL", + "geoname_id": 1790441, + "sub_districts": [] + }, + { + "code": "532922", + "name": "漾濞", + "level": "THREE_LEVEL", + "geoname_id": 1787683, + "sub_districts": [] + }, + { + "code": "532929", + "name": "云龙", + "level": "THREE_LEVEL", + "geoname_id": 1279544, + "sub_districts": [] + }, + { + "code": "532928", + "name": "永平", + "level": "THREE_LEVEL", + "geoname_id": 1279565, + "sub_districts": [] + } + ] + }, + { + "code": "533400", + "name": "迪庆", + "level": "TWO_LEVEL", + "geoname_id": 1281365, + "sub_districts": [ + { + "code": "533422", + "name": "德钦", + "level": "THREE_LEVEL", + "geoname_id": 1281366, + "sub_districts": [] + }, + { + "code": "533423", + "name": "维西", + "level": "THREE_LEVEL", + "geoname_id": 1279803, + "sub_districts": [] + }, + { + "code": "533401", + "name": "香格里拉", + "level": "THREE_LEVEL", + "geoname_id": 1279460, + "sub_districts": [] + } + ] + }, + { + "code": "532500", + "name": "红河", + "level": "TWO_LEVEL", + "geoname_id": 1808130, + "sub_districts": [ + { + "code": "532501", + "name": "个旧", + "level": "THREE_LEVEL", + "geoname_id": 1810239, + "sub_districts": [] + }, + { + "code": "532529", + "name": "红河", + "level": "THREE_LEVEL", + "geoname_id": 1808127, + "sub_districts": [] + }, + { + "code": "532532", + "name": "河口", + "level": "THREE_LEVEL", + "geoname_id": 1808557, + "sub_districts": [] + }, + { + "code": "532530", + "name": "金平", + "level": "THREE_LEVEL", + "geoname_id": 1805429, + "sub_districts": [] + }, + { + "code": "532524", + "name": "建水", + "level": "THREE_LEVEL", + "geoname_id": 1806144, + "sub_districts": [] + }, + { + "code": "532502", + "name": "开远", + "level": "THREE_LEVEL", + "geoname_id": 1804849, + "sub_districts": [] + }, + { + "code": "532531", + "name": "绿春", + "level": "THREE_LEVEL", + "geoname_id": 1802161, + "sub_districts": [] + }, + { + "code": "532527", + "name": "泸西", + "level": "THREE_LEVEL", + "geoname_id": 1801677, + "sub_districts": [] + }, + { + "code": "532504", + "name": "弥勒", + "level": "THREE_LEVEL", + "geoname_id": 1800535, + "sub_districts": [] + }, + { + "code": "532503", + "name": "蒙自", + "level": "THREE_LEVEL", + "geoname_id": 1800662, + "sub_districts": [] + }, + { + "code": "532523", + "name": "屏边", + "level": "THREE_LEVEL", + "geoname_id": 1798854, + "sub_districts": [] + }, + { + "code": "532525", + "name": "石屏", + "level": "THREE_LEVEL", + "geoname_id": 1795072, + "sub_districts": [] + }, + { + "code": "532528", + "name": "元阳", + "level": "THREE_LEVEL", + "geoname_id": 1786015, + "sub_districts": [] + } + ] + }, + { + "code": "530100", + "name": "昆明", + "level": "TWO_LEVEL", + "geoname_id": 1804651, + "sub_districts": [ + { + "code": "530181", + "name": "安宁", + "level": "THREE_LEVEL", + "geoname_id": 1818007, + "sub_districts": [] + }, + { + "code": "530114", + "name": "呈贡", + "level": "THREE_LEVEL", + "geoname_id": 1815278, + "sub_districts": [] + }, + { + "code": "530113", + "name": "东川", + "level": "THREE_LEVEL", + "geoname_id": 1812626, + "sub_districts": [] + }, + { + "code": "530124", + "name": "富民", + "level": "THREE_LEVEL", + "geoname_id": 1810956, + "sub_districts": [] + }, + { + "code": "530111", + "name": "官渡", + "level": "THREE_LEVEL", + "geoname_id": 6643299, + "sub_districts": [] + }, + { + "code": "5301150000001", + "name": "晋宁", + "level": "THREE_LEVEL", + "geoname_id": 1805445, + "sub_districts": [] + }, + { + "code": "530128", + "name": "禄劝", + "level": "THREE_LEVEL", + "geoname_id": 1801749, + "sub_districts": [] + }, + { + "code": "530103", + "name": "盘龙", + "level": "THREE_LEVEL", + "geoname_id": 6643298, + "sub_districts": [] + }, + { + "code": "530126", + "name": "石林", + "level": "THREE_LEVEL", + "geoname_id": 1802011, + "sub_districts": [] + }, + { + "code": "530127", + "name": "嵩明", + "level": "THREE_LEVEL", + "geoname_id": 1794002, + "sub_districts": [] + }, + { + "code": "530102", + "name": "五华", + "level": "THREE_LEVEL", + "geoname_id": 6643300, + "sub_districts": [] + }, + { + "code": "530129", + "name": "寻甸", + "level": "THREE_LEVEL", + "geoname_id": 1787898, + "sub_districts": [] + }, + { + "code": "530112", + "name": "西山", + "level": "THREE_LEVEL", + "geoname_id": 1788353, + "sub_districts": [] + }, + { + "code": "530125", + "name": "宜良", + "level": "THREE_LEVEL", + "geoname_id": 1804685, + "sub_districts": [] + } + ] + }, + { + "code": "530900", + "name": "临沧", + "level": "TWO_LEVEL", + "geoname_id": 1803589, + "sub_districts": [ + { + "code": "530927", + "name": "沧源", + "level": "THREE_LEVEL", + "geoname_id": 1281580, + "sub_districts": [] + }, + { + "code": "530921", + "name": "凤庆", + "level": "THREE_LEVEL", + "geoname_id": 1281271, + "sub_districts": [] + }, + { + "code": "530926", + "name": "耿马", + "level": "THREE_LEVEL", + "geoname_id": 1281202, + "sub_districts": [] + }, + { + "code": "530902", + "name": "临翔", + "level": "THREE_LEVEL", + "geoname_id": 6643308, + "sub_districts": [] + }, + { + "code": "530925", + "name": "双江", + "level": "THREE_LEVEL", + "geoname_id": 1279997, + "sub_districts": [] + }, + { + "code": "530923", + "name": "永德", + "level": "THREE_LEVEL", + "geoname_id": 1279567, + "sub_districts": [] + }, + { + "code": "530922", + "name": "云县", + "level": "THREE_LEVEL", + "geoname_id": 1785664, + "sub_districts": [] + }, + { + "code": "530924", + "name": "镇康", + "level": "THREE_LEVEL", + "geoname_id": 1279469, + "sub_districts": [] + } + ] + }, + { + "code": "530700", + "name": "丽江", + "level": "TWO_LEVEL", + "geoname_id": 1803666, + "sub_districts": [ + { + "code": "530702", + "name": "古城", + "level": "THREE_LEVEL", + "geoname_id": 6643315, + "sub_districts": [] + }, + { + "code": "530723", + "name": "华坪", + "level": "THREE_LEVEL", + "geoname_id": 1807069, + "sub_districts": [] + }, + { + "code": "530724", + "name": "宁蒗", + "level": "THREE_LEVEL", + "geoname_id": 1799369, + "sub_districts": [] + }, + { + "code": "530721", + "name": "玉龙", + "level": "THREE_LEVEL", + "geoname_id": 6642883, + "sub_districts": [] + }, + { + "code": "530722", + "name": "永胜", + "level": "THREE_LEVEL", + "geoname_id": 1786264, + "sub_districts": [] + } + ] + }, + { + "code": "533300", + "name": "怒江", + "level": "TWO_LEVEL", + "geoname_id": 1280418, + "sub_districts": [ + { + "code": "533323", + "name": "福贡", + "level": "THREE_LEVEL", + "geoname_id": 1281267, + "sub_districts": [] + }, + { + "code": "533324", + "name": "贡山", + "level": "THREE_LEVEL", + "geoname_id": 1281167, + "sub_districts": [] + }, + { + "code": "533325", + "name": "兰坪", + "level": "THREE_LEVEL", + "geoname_id": 1280761, + "sub_districts": [] + }, + { + "code": "533301", + "name": "泸水", + "level": "THREE_LEVEL", + "geoname_id": 1280661, + "sub_districts": [] + } + ] + }, + { + "code": "530800", + "name": "普洱", + "level": "TWO_LEVEL", + "geoname_id": 1794208, + "sub_districts": [ + { + "code": "530826", + "name": "江城", + "level": "THREE_LEVEL", + "geoname_id": 1806405, + "sub_districts": [] + }, + { + "code": "530823", + "name": "景东", + "level": "THREE_LEVEL", + "geoname_id": 1805676, + "sub_districts": [] + }, + { + "code": "530824", + "name": "景谷", + "level": "THREE_LEVEL", + "geoname_id": 1805660, + "sub_districts": [] + }, + { + "code": "530828", + "name": "澜沧", + "level": "THREE_LEVEL", + "geoname_id": 1280771, + "sub_districts": [] + }, + { + "code": "530822", + "name": "墨江", + "level": "THREE_LEVEL", + "geoname_id": 1800397, + "sub_districts": [] + }, + { + "code": "530827", + "name": "孟连", + "level": "THREE_LEVEL", + "geoname_id": 1280572, + "sub_districts": [] + }, + { + "code": "530821", + "name": "宁洱", + "level": "THREE_LEVEL", + "geoname_id": 1798519, + "sub_districts": [] + }, + { + "code": "530802", + "name": "思茅", + "level": "THREE_LEVEL", + "geoname_id": 1794207, + "sub_districts": [] + }, + { + "code": "530829", + "name": "西盟", + "level": "THREE_LEVEL", + "geoname_id": 1279707, + "sub_districts": [] + }, + { + "code": "530825", + "name": "镇沅", + "level": "THREE_LEVEL", + "geoname_id": 1784584, + "sub_districts": [] + } + ] + }, + { + "code": "530300", + "name": "曲靖", + "level": "TWO_LEVEL", + "geoname_id": 1797318, + "sub_districts": [ + { + "code": "530325", + "name": "富源", + "level": "THREE_LEVEL", + "geoname_id": 1810823, + "sub_districts": [] + }, + { + "code": "530326", + "name": "会泽", + "level": "THREE_LEVEL", + "geoname_id": 1806777, + "sub_districts": [] + }, + { + "code": "530322", + "name": "陆良", + "level": "THREE_LEVEL", + "geoname_id": 1802026, + "sub_districts": [] + }, + { + "code": "530324", + "name": "罗平", + "level": "THREE_LEVEL", + "geoname_id": 1801861, + "sub_districts": [] + }, + { + "code": "5303040000001", + "name": "马龙", + "level": "THREE_LEVEL", + "geoname_id": 1801331, + "sub_districts": [] + }, + { + "code": "530302", + "name": "麒麟", + "level": "THREE_LEVEL", + "geoname_id": 6643324, + "sub_districts": [] + }, + { + "code": "530323", + "name": "师宗", + "level": "THREE_LEVEL", + "geoname_id": 1794809, + "sub_districts": [] + }, + { + "code": "530381", + "name": "宣威", + "level": "THREE_LEVEL", + "geoname_id": 1788059, + "sub_districts": [] + }, + { + "code": "530303", + "name": "沾益", + "level": "THREE_LEVEL", + "geoname_id": 6643436, + "sub_districts": [] + } + ] + }, + { + "code": "532600", + "name": "文山", + "level": "TWO_LEVEL", + "geoname_id": 1791424, + "sub_districts": [ + { + "code": "532628", + "name": "富宁", + "level": "THREE_LEVEL", + "geoname_id": 1810950, + "sub_districts": [] + }, + { + "code": "532627", + "name": "广南", + "level": "THREE_LEVEL", + "geoname_id": 1809894, + "sub_districts": [] + }, + { + "code": "532625", + "name": "马关", + "level": "THREE_LEVEL", + "geoname_id": 1801504, + "sub_districts": [] + }, + { + "code": "532624", + "name": "麻栗坡", + "level": "THREE_LEVEL", + "geoname_id": 1801341, + "sub_districts": [] + }, + { + "code": "532626", + "name": "丘北", + "level": "THREE_LEVEL", + "geoname_id": 1797478, + "sub_districts": [] + }, + { + "code": "532601", + "name": "文山", + "level": "THREE_LEVEL", + "geoname_id": 8505006, + "sub_districts": [] + }, + { + "code": "532623", + "name": "西畴", + "level": "THREE_LEVEL", + "geoname_id": 1789628, + "sub_districts": [] + }, + { + "code": "532622", + "name": "砚山", + "level": "THREE_LEVEL", + "geoname_id": 1787107, + "sub_districts": [] + } + ] + }, + { + "code": "532800", + "name": "西双版纳", + "level": "TWO_LEVEL", + "geoname_id": 1788323, + "sub_districts": [ + { + "code": "532801", + "name": "景洪", + "level": "THREE_LEVEL", + "geoname_id": 1805645, + "sub_districts": [] + }, + { + "code": "532822", + "name": "勐海", + "level": "THREE_LEVEL", + "geoname_id": 1800745, + "sub_districts": [] + }, + { + "code": "532823", + "name": "勐腊", + "level": "THREE_LEVEL", + "geoname_id": 1800715, + "sub_districts": [] + } + ] + }, + { + "code": "530400", + "name": "玉溪", + "level": "TWO_LEVEL", + "geoname_id": 1784185, + "sub_districts": [ + { + "code": "5304810000001", + "name": "澄江", + "level": "THREE_LEVEL", + "geoname_id": 1815250, + "sub_districts": [] + }, + { + "code": "530426", + "name": "峨山", + "level": "THREE_LEVEL", + "geoname_id": 1811629, + "sub_districts": [] + }, + { + "code": "530424", + "name": "华宁", + "level": "THREE_LEVEL", + "geoname_id": 1807093, + "sub_districts": [] + }, + { + "code": "530402", + "name": "红塔", + "level": "THREE_LEVEL", + "geoname_id": 6643303, + "sub_districts": [] + }, + { + "code": "530403", + "name": "江川", + "level": "THREE_LEVEL", + "geoname_id": 1814169, + "sub_districts": [] + }, + { + "code": "530423", + "name": "通海", + "level": "THREE_LEVEL", + "geoname_id": 1792662, + "sub_districts": [] + }, + { + "code": "530427", + "name": "新平", + "level": "THREE_LEVEL", + "geoname_id": 1788700, + "sub_districts": [] + }, + { + "code": "530428", + "name": "元江", + "level": "THREE_LEVEL", + "geoname_id": 1786081, + "sub_districts": [] + }, + { + "code": "530425", + "name": "易门", + "level": "THREE_LEVEL", + "geoname_id": 1786665, + "sub_districts": [] + } + ] + }, + { + "code": "530600", + "name": "昭通", + "level": "TWO_LEVEL", + "geoname_id": 1784841, + "sub_districts": [ + { + "code": "530624", + "name": "大关", + "level": "THREE_LEVEL", + "geoname_id": 1814376, + "sub_districts": [] + }, + { + "code": "530621", + "name": "鲁甸", + "level": "THREE_LEVEL", + "geoname_id": 1802143, + "sub_districts": [] + }, + { + "code": "530622", + "name": "巧家", + "level": "THREE_LEVEL", + "geoname_id": 1798171, + "sub_districts": [] + }, + { + "code": "5306810000001", + "name": "水富", + "level": "THREE_LEVEL", + "geoname_id": 1794488, + "sub_districts": [] + }, + { + "code": "530626", + "name": "绥江", + "level": "THREE_LEVEL", + "geoname_id": 1793901, + "sub_districts": [] + }, + { + "code": "530629", + "name": "威信", + "level": "THREE_LEVEL", + "geoname_id": 1791581, + "sub_districts": [] + }, + { + "code": "530623", + "name": "盐津", + "level": "THREE_LEVEL", + "geoname_id": 1787157, + "sub_districts": [] + }, + { + "code": "530628", + "name": "彝良", + "level": "THREE_LEVEL", + "geoname_id": 1786686, + "sub_districts": [] + }, + { + "code": "530625", + "name": "永善", + "level": "THREE_LEVEL", + "geoname_id": 1786265, + "sub_districts": [] + }, + { + "code": "530627", + "name": "镇雄", + "level": "THREE_LEVEL", + "geoname_id": 1784591, + "sub_districts": [] + }, + { + "code": "530602", + "name": "昭阳", + "level": "THREE_LEVEL", + "geoname_id": 6643328, + "sub_districts": [] + } + ] + } + ] + }, + { + "code": "33", + "name": "浙江", + "level": "ONE_LEVEL", + "geoname_id": 1784764, + "sub_districts": [ + { + "code": "330100", + "name": "杭州", + "level": "TWO_LEVEL", + "geoname_id": 1808926, + "sub_districts": [ + { + "code": "330108", + "name": "滨江", + "level": "THREE_LEVEL", + "geoname_id": 6607385, + "sub_districts": [] + }, + { + "code": "330127", + "name": "淳安", + "level": "THREE_LEVEL", + "geoname_id": 1814787, + "sub_districts": [] + }, + { + "code": "330111", + "name": "富阳", + "level": "THREE_LEVEL", + "geoname_id": 1810846, + "sub_districts": [] + }, + { + "code": "3301050000000", + "name": "拱墅", + "level": "THREE_LEVEL", + "geoname_id": 6607380, + "sub_districts": [] + }, + { + "code": "330182", + "name": "建德", + "level": "THREE_LEVEL", + "geoname_id": 1806431, + "sub_districts": [] + }, + { + "code": "3301120000001", + "name": "临安", + "level": "THREE_LEVEL", + "geoname_id": 1803594, + "sub_districts": [] + }, + { + "code": "3301130000000", + "name": "临平区", + "level": "THREE_LEVEL", + "geoname_id": 330113, + "sub_districts": [] + }, + { + "code": "3301140000000", + "name": "钱塘区", + "level": "THREE_LEVEL", + "geoname_id": 330114, + "sub_districts": [] + }, + { + "code": "3301020000000", + "name": "上城", + "level": "THREE_LEVEL", + "geoname_id": 6607382, + "sub_districts": [] + }, + { + "code": "330122", + "name": "桐庐", + "level": "THREE_LEVEL", + "geoname_id": 1792615, + "sub_districts": [] + }, + { + "code": "330106", + "name": "西湖", + "level": "THREE_LEVEL", + "geoname_id": 6607381, + "sub_districts": [] + }, + { + "code": "3301090000000", + "name": "萧山", + "level": "THREE_LEVEL", + "geoname_id": 1789993, + "sub_districts": [] + }, + { + "code": "3301100000000", + "name": "余杭", + "level": "THREE_LEVEL", + "geoname_id": 1785857, + "sub_districts": [] + } + ] + }, + { + "code": "330500", + "name": "湖州", + "level": "TWO_LEVEL", + "geoname_id": 1806535, + "sub_districts": [ + { + "code": "330523", + "name": "安吉", + "level": "THREE_LEVEL", + "geoname_id": 1818043, + "sub_districts": [] + }, + { + "code": "330522", + "name": "长兴", + "level": "THREE_LEVEL", + "geoname_id": 1815492, + "sub_districts": [] + }, + { + "code": "330521", + "name": "德清", + "level": "THREE_LEVEL", + "geoname_id": 1812981, + "sub_districts": [] + }, + { + "code": "330503", + "name": "南浔", + "level": "THREE_LEVEL", + "geoname_id": 6607480, + "sub_districts": [] + }, + { + "code": "330502", + "name": "吴兴", + "level": "THREE_LEVEL", + "geoname_id": 6607479, + "sub_districts": [] + } + ] + }, + { + "code": "330700", + "name": "金华", + "level": "TWO_LEVEL", + "geoname_id": 1805528, + "sub_districts": [ + { + "code": "330783", + "name": "东阳", + "level": "THREE_LEVEL", + "geoname_id": 1812113, + "sub_districts": [] + }, + { + "code": "330703", + "name": "金东", + "level": "THREE_LEVEL", + "geoname_id": 1805524, + "sub_districts": [] + }, + { + "code": "330781", + "name": "兰溪", + "level": "THREE_LEVEL", + "geoname_id": 1804437, + "sub_districts": [] + }, + { + "code": "330727", + "name": "磐安", + "level": "THREE_LEVEL", + "geoname_id": 1799101, + "sub_districts": [] + }, + { + "code": "330726", + "name": "浦江", + "level": "THREE_LEVEL", + "geoname_id": 1798497, + "sub_districts": [] + }, + { + "code": "330702", + "name": "婺城", + "level": "THREE_LEVEL", + "geoname_id": 6607482, + "sub_districts": [] + }, + { + "code": "330723", + "name": "武义", + "level": "THREE_LEVEL", + "geoname_id": 1790870, + "sub_districts": [] + }, + { + "code": "330784", + "name": "永康", + "level": "THREE_LEVEL", + "geoname_id": 1786317, + "sub_districts": [] + }, + { + "code": "330782", + "name": "义乌", + "level": "THREE_LEVEL", + "geoname_id": 1786431, + "sub_districts": [] + } + ] + }, + { + "code": "330400", + "name": "嘉兴", + "level": "TWO_LEVEL", + "geoname_id": 1805953, + "sub_districts": [ + { + "code": "330481", + "name": "海宁", + "level": "THREE_LEVEL", + "geoname_id": 1809050, + "sub_districts": [] + }, + { + "code": "330424", + "name": "海盐", + "level": "THREE_LEVEL", + "geoname_id": 1809015, + "sub_districts": [] + }, + { + "code": "330421", + "name": "嘉善", + "level": "THREE_LEVEL", + "geoname_id": 1805971, + "sub_districts": [] + }, + { + "code": "330402", + "name": "南湖", + "level": "THREE_LEVEL", + "geoname_id": 6607478, + "sub_districts": [] + }, + { + "code": "330482", + "name": "平湖", + "level": "THREE_LEVEL", + "geoname_id": 1798786, + "sub_districts": [] + }, + { + "code": "330483", + "name": "桐乡", + "level": "THREE_LEVEL", + "geoname_id": 1790942, + "sub_districts": [] + }, + { + "code": "330411", + "name": "秀洲", + "level": "THREE_LEVEL", + "geoname_id": 6607477, + "sub_districts": [] + } + ] + }, + { + "code": "331100", + "name": "丽水", + "level": "TWO_LEVEL", + "geoname_id": 1803245, + "sub_districts": [ + { + "code": "331127", + "name": "景宁", + "level": "THREE_LEVEL", + "geoname_id": 1805605, + "sub_districts": [] + }, + { + "code": "331122", + "name": "缙云", + "level": "THREE_LEVEL", + "geoname_id": 1805309, + "sub_districts": [] + }, + { + "code": "331102", + "name": "莲都", + "level": "THREE_LEVEL", + "geoname_id": 6607484, + "sub_districts": [] + }, + { + "code": "331181", + "name": "龙泉", + "level": "THREE_LEVEL", + "geoname_id": 1802459, + "sub_districts": [] + }, + { + "code": "331121", + "name": "青田", + "level": "THREE_LEVEL", + "geoname_id": 1797696, + "sub_districts": [] + }, + { + "code": "331126", + "name": "庆元", + "level": "THREE_LEVEL", + "geoname_id": 1793952, + "sub_districts": [] + }, + { + "code": "331123", + "name": "遂昌", + "level": "THREE_LEVEL", + "geoname_id": 1793909, + "sub_districts": [] + }, + { + "code": "331124", + "name": "松阳", + "level": "THREE_LEVEL", + "geoname_id": 1793960, + "sub_districts": [] + }, + { + "code": "331125", + "name": "云和", + "level": "THREE_LEVEL", + "geoname_id": 1785715, + "sub_districts": [] + } + ] + }, + { + "code": "330200", + "name": "宁波", + "level": "TWO_LEVEL", + "geoname_id": 1799397, + "sub_districts": [ + { + "code": "330206", + "name": "北仑", + "level": "THREE_LEVEL", + "geoname_id": 1816625, + "sub_districts": [] + }, + { + "code": "330282", + "name": "慈溪", + "level": "THREE_LEVEL", + "geoname_id": 1806602, + "sub_districts": [] + }, + { + "code": "3302130000001", + "name": "奉化", + "level": "THREE_LEVEL", + "geoname_id": 1813658, + "sub_districts": [] + }, + { + "code": "330203", + "name": "海曙", + "level": "THREE_LEVEL", + "geoname_id": 6607394, + "sub_districts": [] + }, + { + "code": "330205", + "name": "江北", + "level": "THREE_LEVEL", + "geoname_id": 6607401, + "sub_districts": [] + }, + { + "code": "330226", + "name": "宁海", + "level": "THREE_LEVEL", + "geoname_id": 1799381, + "sub_districts": [] + }, + { + "code": "330225", + "name": "象山", + "level": "THREE_LEVEL", + "geoname_id": 1790512, + "sub_districts": [] + }, + { + "code": "330281", + "name": "余姚", + "level": "THREE_LEVEL", + "geoname_id": 1785543, + "sub_districts": [] + }, + { + "code": "330212", + "name": "鄞州", + "level": "THREE_LEVEL", + "geoname_id": 1786496, + "sub_districts": [] + }, + { + "code": "330211", + "name": "镇海", + "level": "THREE_LEVEL", + "geoname_id": 1784647, + "sub_districts": [] + } + ] + }, + { + "code": "330800", + "name": "衢州", + "level": "TWO_LEVEL", + "geoname_id": 1797264, + "sub_districts": [ + { + "code": "330822", + "name": "常山", + "level": "THREE_LEVEL", + "geoname_id": 1815556, + "sub_districts": [] + }, + { + "code": "330881", + "name": "江山", + "level": "THREE_LEVEL", + "geoname_id": 1806269, + "sub_districts": [] + }, + { + "code": "330802", + "name": "柯城", + "level": "THREE_LEVEL", + "geoname_id": 6607483, + "sub_districts": [] + }, + { + "code": "330824", + "name": "开化", + "level": "THREE_LEVEL", + "geoname_id": 1804871, + "sub_districts": [] + }, + { + "code": "330825", + "name": "龙游", + "level": "THREE_LEVEL", + "geoname_id": 1802261, + "sub_districts": [] + }, + { + "code": "330803", + "name": "衢江", + "level": "THREE_LEVEL", + "geoname_id": 1797278, + "sub_districts": [] + } + ] + }, + { + "code": "330600", + "name": "绍兴", + "level": "TWO_LEVEL", + "geoname_id": 1795855, + "sub_districts": [ + { + "code": "330603", + "name": "柯桥", + "level": "THREE_LEVEL", + "geoname_id": 1804753, + "sub_districts": [] + }, + { + "code": "3306040000000", + "name": "上虞", + "level": "THREE_LEVEL", + "geoname_id": 330604, + "sub_districts": [] + }, + { + "code": "330683", + "name": "嵊州", + "level": "THREE_LEVEL", + "geoname_id": 1795647, + "sub_districts": [] + }, + { + "code": "330624", + "name": "新昌", + "level": "THREE_LEVEL", + "geoname_id": 1789191, + "sub_districts": [] + }, + { + "code": "3306020000000", + "name": "越城", + "level": "THREE_LEVEL", + "geoname_id": 6607481, + "sub_districts": [] + }, + { + "code": "330681", + "name": "诸暨", + "level": "THREE_LEVEL", + "geoname_id": 1783940, + "sub_districts": [] + } + ] + }, + { + "code": "331000", + "name": "台州", + "level": "TWO_LEVEL", + "geoname_id": 1793504, + "sub_districts": [ + { + "code": "331003", + "name": "黄岩", + "level": "THREE_LEVEL", + "geoname_id": 1807133, + "sub_districts": [] + }, + { + "code": "331002", + "name": "椒江", + "level": "THREE_LEVEL", + "geoname_id": 11778432, + "sub_districts": [] + }, + { + "code": "331082", + "name": "临海", + "level": "THREE_LEVEL", + "geoname_id": 1803421, + "sub_districts": [] + }, + { + "code": "331004", + "name": "路桥", + "level": "THREE_LEVEL", + "geoname_id": 1922898, + "sub_districts": [] + }, + { + "code": "331022", + "name": "三门", + "level": "THREE_LEVEL", + "geoname_id": 1796668, + "sub_districts": [] + }, + { + "code": "331023", + "name": "天台", + "level": "THREE_LEVEL", + "geoname_id": 1792886, + "sub_districts": [] + }, + { + "code": "331081", + "name": "温岭", + "level": "THREE_LEVEL", + "geoname_id": 1791462, + "sub_districts": [] + }, + { + "code": "331024", + "name": "仙居", + "level": "THREE_LEVEL", + "geoname_id": 8398287, + "sub_districts": [] + }, + { + "code": "3310830000001", + "name": "玉环", + "level": "THREE_LEVEL", + "geoname_id": 1785838, + "sub_districts": [] + } + ] + }, + { + "code": "330300", + "name": "温州", + "level": "TWO_LEVEL", + "geoname_id": 1791388, + "sub_districts": [ + { + "code": "330327", + "name": "苍南", + "level": "THREE_LEVEL", + "geoname_id": 1816095, + "sub_districts": [] + }, + { + "code": "330305", + "name": "洞头", + "level": "THREE_LEVEL", + "geoname_id": 1812199, + "sub_districts": [] + }, + { + "code": "330302", + "name": "鹿城", + "level": "THREE_LEVEL", + "geoname_id": 6607379, + "sub_districts": [] + }, + { + "code": "330383", + "name": "龙港", + "level": "THREE_LEVEL", + "geoname_id": 330383, + "sub_districts": [] + }, + { + "code": "330303", + "name": "龙湾", + "level": "THREE_LEVEL", + "geoname_id": 1922899, + "sub_districts": [] + }, + { + "code": "330304", + "name": "瓯海", + "level": "THREE_LEVEL", + "geoname_id": 1799146, + "sub_districts": [] + }, + { + "code": "330326", + "name": "平阳", + "level": "THREE_LEVEL", + "geoname_id": 1798639, + "sub_districts": [] + }, + { + "code": "330381", + "name": "瑞安", + "level": "THREE_LEVEL", + "geoname_id": 1797062, + "sub_districts": [] + }, + { + "code": "330329", + "name": "泰顺", + "level": "THREE_LEVEL", + "geoname_id": 1801794, + "sub_districts": [] + }, + { + "code": "330328", + "name": "文成", + "level": "THREE_LEVEL", + "geoname_id": 1791535, + "sub_districts": [] + }, + { + "code": "330324", + "name": "永嘉", + "level": "THREE_LEVEL", + "geoname_id": 1786326, + "sub_districts": [] + }, + { + "code": "330382", + "name": "乐清", + "level": "THREE_LEVEL", + "geoname_id": 1785913, + "sub_districts": [] + } + ] + }, + { + "code": "330900", + "name": "舟山", + "level": "TWO_LEVEL", + "geoname_id": 1784107, + "sub_districts": [ + { + "code": "330902", + "name": "定海", + "level": "THREE_LEVEL", + "geoname_id": 1812802, + "sub_districts": [] + }, + { + "code": "330921", + "name": "岱山", + "level": "THREE_LEVEL", + "geoname_id": 1814229, + "sub_districts": [] + }, + { + "code": "330903", + "name": "普陀", + "level": "THREE_LEVEL", + "geoname_id": 1798436, + "sub_districts": [] + }, + { + "code": "330922", + "name": "嵊泗", + "level": "THREE_LEVEL", + "geoname_id": 1795653, + "sub_districts": [] + } + ] + } + ] + } + ] + } +] \ No newline at end of file diff --git a/video-gen-api/app/utils/douyinApi.py b/video-gen-api/app/utils/douyinApi.py index cd85c8c7..32960f84 100644 --- a/video-gen-api/app/utils/douyinApi.py +++ b/video-gen-api/app/utils/douyinApi.py @@ -52,4 +52,17 @@ class DouyinApi: url, 'POST', options + ) + + #获取区域信息 + async def get_area(self, oauth_id: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: + if not oauth_id: + raise RuntimeError('OAuth ID is not set.') + + url = "https://api.oceanengine.com/open_api/2/tools/admin/info/" + return await self.request.request_with_token_with_context( + oauth_id, + url, + 'GET', + {'params': params or {}} ) \ No newline at end of file diff --git a/video-gen-app/.gitignore b/video-gen-app/.gitignore index ec6988ea..9cac2492 100644 --- a/video-gen-app/.gitignore +++ b/video-gen-app/.gitignore @@ -24,4 +24,6 @@ dist-ssr *.sw? *.bak *.zip -*.testbak \ No newline at end of file +*.testbak + +.env.production \ No newline at end of file diff --git a/video-gen-app/src/App.css b/video-gen-app/src/App.css index f90339d8..032d5d96 100644 --- a/video-gen-app/src/App.css +++ b/video-gen-app/src/App.css @@ -17,6 +17,7 @@ } } + .hero { position: relative; diff --git a/video-gen-app/src/App.tsx b/video-gen-app/src/App.tsx index fdc6133a..4abf459b 100644 --- a/video-gen-app/src/App.tsx +++ b/video-gen-app/src/App.tsx @@ -20,9 +20,10 @@ import GeneratedRecord from './pages/GeneratedRecord'; import PreTest from './pages/PreTest'; import AuthorizationPage from './pages/AuthorizationPage'; import RemoveInfo from './pages/RemoveInfo'; +import RemoveRw from './pages/RemoveRw'; +// import RemoveFenbu from './pages/RemoveFenbu'; import ConsumePage from './pages/ConsumePage'; import { useAuthStore } from './store/useAuthStore'; - const ProtectedRoute = ({ children }: { children: React.ReactNode }) => { const { user, loading, checkAuth } = useAuthStore(); useEffect(() => { @@ -102,6 +103,10 @@ const App = () => { } /> } /> } /> + } /> + {/* } /> */} + + } /> } /> } /> diff --git a/video-gen-app/src/api/index.ts b/video-gen-app/src/api/index.ts index 598e53b4..70122322 100644 --- a/video-gen-app/src/api/index.ts +++ b/video-gen-app/src/api/index.ts @@ -378,7 +378,7 @@ export async function getReplicationDetail(id: string): Promise { export async function getone(projectId: string, stepId: string): Promise { return api.post(`/hot-opening-replications/tasks/${projectId}/steps/${stepId}/generate-image-prompt`); } - + // 第二步,生成图片 export async function gettwo(projectId: string, stepId: string ,params: any): Promise { return api.post(`/hot-opening-replications/tasks/${projectId}/steps/${stepId}/generate-image`, params); @@ -481,4 +481,73 @@ export async function deletePreTest(templateId: string): Promise { // /api/pre-test-template/default export async function getDefaultPreTest(): Promise { return api.get(`/pre-test-template/default`); -} \ No newline at end of file +} +// 修改第四步视频 AI 提词 JSON schema +export async function updateHotOpeningVideoPromptSchema(projectId: string, stepId: string, params: { prompt_schema: Record }): Promise { + return api.put(`/hot-opening-replications/tasks/${projectId}/steps/${stepId}/video-prompt-schema`, params); +} + +// 镜头复刻 +export async function createShotReplication(params: any): Promise { + return api.post('/shot-replications/task-sets', params); +} +// 获取镜头复刻任务列表 +export async function getShotReplicationList(page: number, page_size: number): Promise { + return api.get(`/shot-replications/task-sets?page=${page}&page_size=${page_size}`); +} +// 获取镜头复刻任务详情 +export async function getShotReplicationDetail(taskSetId: string): Promise { + return api.get(`/shot-replications/task-sets/${taskSetId}`); +} + +// ai拆镜 +export async function createRemoveLens(taskSetId: string, params: any): Promise { + return api.post(`/shot-replications/task-sets/${taskSetId}/split-by-ai`, params); +} + +// 手动分割 +export async function splitCustom(taskSetId: string, params: any): Promise { + return api.post(`/shot-replications/task-sets/${taskSetId}/split-custom`, params); +} + +// 拆镜列表 +export async function Removelist(taskSetId: string): Promise { + return api.get(`/shot-replications/task-sets/${taskSetId}/segments`); +} + +// 生成视频 +export async function removeCreate(recordId: string, params: any): Promise { + return api.post(`/shot-replications/segments/${recordId}/replication-projects`, params); +} + + + + +// 获取爆款开头复刻任务详情 +export async function removeDetail(id: string): Promise { + return api.get(`/shot-replications/projects/${id}`); +} + +// 第一步,生成提示词 +export async function removeone(projectId: string, stepId: string): Promise { + return api.post(`/shot-replications/projects/${projectId}/steps/${stepId}/generate-image-prompt`); + +} + +// 第二步,生成图片 +export async function removetwo(projectId: string, stepId: string ,params: any): Promise { + return api.post(`/shot-replications/projects/${projectId}/steps/${stepId}/generate-image`, params); +} + +// 第三步,生成视频提示词 +export async function removethree(projectId: string, stepId: string ,params: any): Promise { + return api.post(`/shot-replications/projects/${projectId}/steps/${stepId}/generate-video-prompt`, params); + + +} +// 第四步,生成视频 +export async function removefour(projectId: string, stepId: string ,params: any): Promise { + return api.post(`/shot-replications/projects/${projectId}/steps/${stepId}/generate-video`, params); + +} +// diff --git a/video-gen-app/src/components/Layout/AppLayout.tsx b/video-gen-app/src/components/Layout/AppLayout.tsx index 83b5945c..75016123 100644 --- a/video-gen-app/src/components/Layout/AppLayout.tsx +++ b/video-gen-app/src/components/Layout/AppLayout.tsx @@ -167,7 +167,7 @@ const AppLayout: React.FC = () => { const countdownTimerRef = useRef | null>(null); const currentOrderNoRef = useRef(null); const [enabledMethods, setEnabledMethods] = useState<{ alipay: boolean; wechat: boolean }>({ alipay: false, wechat: false }); - + // LocalStorage keys const PENDING_ORDER_KEY = 'pending_payment_order'; @@ -177,12 +177,12 @@ const AppLayout: React.FC = () => { getSiteInfo().then(info => { const name = info.siteName || '民众智创'; const logo = info.siteLogo || ''; - + if (name !== siteName) { setSiteName(name); document.title = name; } - + if (logo && logo !== siteLogo) { setSiteLogo(logo); let faviconLink = document.querySelector('link[rel="icon"]') as HTMLLinkElement; @@ -194,15 +194,15 @@ const AppLayout: React.FC = () => { faviconLink.href = logo; faviconLink.type = 'image/png'; } - + localStorage.setItem('siteInfo', JSON.stringify({ siteName: name, siteLogo: logo })); - }).catch(() => {}); + }).catch(() => { }); }, []); const loadUnreadCount = () => { getUnreadCount().then(count => { setUnreadCount(count); - }).catch(() => {}); + }).catch(() => { }); }; // 检查并恢复待处理的支付订单 @@ -229,7 +229,7 @@ const AppLayout: React.FC = () => { const timeoutSeconds = savedOrder.timeoutSeconds || 180; const elapsedSeconds = Math.floor((now - createdAt) / 1000); const remainingSeconds = Math.max(0, timeoutSeconds - elapsedSeconds); - + if (remainingSeconds > 0) { setQrCodeModalOpen(true); startPolling(savedOrder.orderNo, remainingSeconds); @@ -252,7 +252,7 @@ const AppLayout: React.FC = () => { } } }; - + checkPendingOrder(); }, []); @@ -274,16 +274,16 @@ const AppLayout: React.FC = () => { }); } setMenuItems(items); - }).catch(() => {}); + }).catch(() => { }); getRechargePackages().then(data => { setRechargeOptions(data.filter((p: any) => p.is_active !== false && p.isActive !== false)); - }).catch(() => {}); + }).catch(() => { }); getPaymentMethods().then(data => { setEnabledMethods(data); // Auto-select the first enabled method if (data.alipay) setPaymentMethod('alipay'); else if (data.wechat) setPaymentMethod('wechat'); - }).catch(() => {}); + }).catch(() => { }); loadUnreadCount(); }, [user]); @@ -344,7 +344,7 @@ const AppLayout: React.FC = () => { const startPolling = useCallback((orderNo: string, timeoutSeconds: number = 180) => { stopPolling(); setCountdown(timeoutSeconds); - + // 订单状态轮询(每2秒查询一次,只查询当前订单 const pollingTimer = setInterval(async () => { try { @@ -368,7 +368,7 @@ const AppLayout: React.FC = () => { } }, 2000); pollingTimerRef.current = pollingTimer; - + // 倒计时 const countdownTimer = setInterval(() => { setCountdown(prev => { @@ -376,7 +376,7 @@ const AppLayout: React.FC = () => { // 超时自动取消 stopPolling(); if (currentOrderNoRef.current) { - cancelPaymentOrder(currentOrderNoRef.current).catch(() => {}); + cancelPaymentOrder(currentOrderNoRef.current).catch(() => { }); currentOrderNoRef.current = null; } localStorage.removeItem(PENDING_ORDER_KEY); @@ -474,8 +474,8 @@ const AppLayout: React.FC = () => { background: isActive ? 'linear-gradient(135deg, rgba(99, 102, 241, 0.1) 0%, rgba(139, 92, 246, 0.08) 100%)' : 'transparent', transition: 'all 0.2s ease', }}> - 0 ? 14 : 16, + 0 ? 14 : 16, flexShrink: 0, color: isActive ? '#6366f1' : '#64748b', }}>{menuIcon} @@ -521,13 +521,13 @@ const AppLayout: React.FC = () => { boxShadow: '0 4px 16px rgba(99, 102, 241, 0.4)', transition: 'all 0.3s ease', }} - onMouseEnter={(e) => { - e.currentTarget.style.background = 'linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%)'; + onMouseEnter={(e) => { + e.currentTarget.style.background = 'linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%)'; e.currentTarget.style.transform = 'translateY(-1px)'; e.currentTarget.style.boxShadow = '0 6px 20px rgba(99, 102, 241, 0.5)'; }} - onMouseLeave={(e) => { - e.currentTarget.style.background = 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)'; + onMouseLeave={(e) => { + e.currentTarget.style.background = 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)'; e.currentTarget.style.transform = 'translateY(0)'; e.currentTarget.style.boxShadow = '0 4px 16px rgba(99, 102, 241, 0.4)'; }} @@ -544,7 +544,7 @@ const AppLayout: React.FC = () => { justifyContent: 'flex-start', gap: 12, padding: '10px 14px', - borderRadius: 14, cursor: 'pointer', + borderRadius: 14, cursor: 'pointer', transition: 'all 0.25s ease', background: 'linear-gradient(135deg, rgba(248, 250, 252, 0.9) 0%, rgba(241, 245, 249, 0.9) 100%)', boxShadow: '0 2px 12px rgba(0, 0, 0, 0.04)', @@ -559,8 +559,8 @@ const AppLayout: React.FC = () => { }} > } - style={{ - background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', + style={{ + background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', flexShrink: 0, boxShadow: '0 4px 12px rgba(99, 102, 241, 0.3)', }} /> @@ -568,9 +568,9 @@ const AppLayout: React.FC = () => {
{user?.username}
-
{ {/* Main Content */}
{ const g = GRADIENTS[idx % GRADIENTS.length]; const totalCredits = (opt.credits || 0) + (opt.bonus_credits || opt.bonusCredits || 0); return ( -
setSelectedPlan(opt.id)} style={{ - flex: '1 1 45%', minWidth: 200, borderRadius: 16, padding: '20px 16px', - background: selectedPlan === opt.id ? 'rgba(99,102,241,0.04)' : '#fafbff', - border: selectedPlan === opt.id ? '2px solid #6366f1' : '1px solid #f0f0f5', - cursor: 'pointer', position: 'relative', transition: 'all 0.2s', - }}> - {opt.description && ( - {opt.description} - )} -
-
{g.icon}
-
-
- {opt.name} - {totalCredits.toLocaleString()} 积分 -
+
setSelectedPlan(opt.id)} style={{ + flex: '1 1 45%', minWidth: 200, borderRadius: 16, padding: '20px 16px', + background: selectedPlan === opt.id ? 'rgba(99,102,241,0.04)' : '#fafbff', + border: selectedPlan === opt.id ? '2px solid #6366f1' : '1px solid #f0f0f5', + cursor: 'pointer', position: 'relative', transition: 'all 0.2s', + }}> + {opt.description && ( + {opt.description} + )} +
¥{opt.price}
+ width: 44, height: 44, borderRadius: 12, flexShrink: 0, + background: g.gradient, display: 'flex', alignItems: 'center', justifyContent: 'center', + fontSize: 18, color: '#fff', boxShadow: `0 6px 16px ${g.shadow}`, + }}>{g.icon}
+
+
+ {opt.name} + {totalCredits.toLocaleString()} 积分 +
+
¥{opt.price}
+
-
); })}
@@ -763,7 +766,7 @@ const AppLayout: React.FC = () => { setRechargeModalOpen(false); setQrCodeModalOpen(true); currentOrderNoRef.current = order.orderNo; - + // 保存到 localStorage localStorage.setItem(PENDING_ORDER_KEY, JSON.stringify({ orderNo: order.orderNo, @@ -774,7 +777,7 @@ const AppLayout: React.FC = () => { createdAt: order.createdAt || new Date().toISOString(), timeoutSeconds: 180, })); - + // Start polling for payment status startPolling(order.orderNo); } else { @@ -808,7 +811,7 @@ const AppLayout: React.FC = () => { stopPolling(); // Mark order as cancelled if it's still pending if (currentOrderNoRef.current) { - try { await cancelPaymentOrder(currentOrderNoRef.current); } catch {} + try { await cancelPaymentOrder(currentOrderNoRef.current); } catch { } currentOrderNoRef.current = null; } localStorage.removeItem(PENDING_ORDER_KEY); @@ -934,7 +937,7 @@ const AppLayout: React.FC = () => { onClick={async () => { stopPolling(); if (currentOrderNoRef.current) { - try { await cancelPaymentOrder(currentOrderNoRef.current); } catch {} + try { await cancelPaymentOrder(currentOrderNoRef.current); } catch { } currentOrderNoRef.current = null; } localStorage.removeItem(PENDING_ORDER_KEY); diff --git a/video-gen-app/src/components/VideoPromptSchemaEditor.tsx b/video-gen-app/src/components/VideoPromptSchemaEditor.tsx new file mode 100644 index 00000000..eb865c92 --- /dev/null +++ b/video-gen-app/src/components/VideoPromptSchemaEditor.tsx @@ -0,0 +1,274 @@ +import React from 'react'; +import { Button, Input, Space, Tag, Typography } from 'antd'; + +const { Text } = Typography; +const { TextArea } = Input; + +type JsonValue = any; + +type VideoPromptSchemaEditorProps = { + value: Record; + onChange: (nextValue: Record) => void; +}; + +const LOCKED_TOP_LEVEL_KEYS = new Set([ + 'schema_version', + 'schema_usage', + '动态时间规划', + '输出规格限制', + '合规控制', + '质量控制', +]); + +const LOCKED_FRAME_KEYS = new Set([ + '视频时长', + '视频比例', + '清晰度', + '帧率', + '推荐分辨率', +]); + +const EDITABLE_FRAME_KEYS = new Set([ + '主体描述', + '主体数量', + '主体位置', + '主体占比', + '场景描述', + '构图方式', + '画面风格', + '光影色彩', +]); + +const EDITABLE_FINAL_PROMPT_KEYS = new Set([ + '主提示词', + '动作提示词', + '镜头提示词', + '字幕提示词', + '音频提示词', + '风格提示词', + '负面提示词', +]); + +function clonePlain(value: T): T { + return value === undefined ? value : JSON.parse(JSON.stringify(value)); +} + +function pathIncludes(path: Array, key: string): boolean { + return path.some((item) => String(item) === key); +} + +function getPathValue(root: JsonValue, path: Array): JsonValue { + let current = root; + for (const key of path) { + if (current === undefined || current === null) return undefined; + current = current[key as keyof typeof current]; + } + return current; +} + +function setPathValue(root: JsonValue, path: Array, value: JsonValue): JsonValue { + const next = clonePlain(root); + let current = next; + for (let index = 0; index < path.length - 1; index += 1) { + current = current[path[index] as keyof typeof current]; + } + current[path[path.length - 1] as keyof typeof current] = value; + return next; +} + +function removeArrayItem(root: JsonValue, path: Array, index: number): JsonValue { + const arrayValue = getPathValue(root, path); + if (!Array.isArray(arrayValue)) return root; + return setPathValue(root, path, arrayValue.filter((_, itemIndex) => itemIndex !== index)); +} + +function addArrayItem(root: JsonValue, path: Array, sampleValue: JsonValue): JsonValue { + const arrayValue = getPathValue(root, path); + if (!Array.isArray(arrayValue)) return root; + const nextItem = typeof sampleValue === 'object' && sampleValue !== null ? clonePlain(sampleValue) : ''; + return setPathValue(root, path, [...arrayValue, nextItem]); +} + +function stringifyReadonly(value: JsonValue): string { + if (value === null || value === undefined) return ''; + if (typeof value === 'object') return JSON.stringify(value, null, 2); + return String(value); +} + +function shouldUseTextArea(value: JsonValue): boolean { + const text = stringifyReadonly(value); + return text.length > 40 || text.includes('\n') || text.includes(',') || text.includes('。'); +} + +function isLockedPath(path: Array): boolean { + const rootKey = String(path[0] ?? ''); + const currentKey = String(path[path.length - 1] ?? ''); + + if (LOCKED_TOP_LEVEL_KEYS.has(rootKey)) return true; + if (rootKey === '画面属性') { + if (LOCKED_FRAME_KEYS.has(currentKey)) return true; + if (!EDITABLE_FRAME_KEYS.has(currentKey)) return false; + } + if (rootKey === '最终提示词' && path.length === 2) { + return !EDITABLE_FINAL_PROMPT_KEYS.has(currentKey); + } + if ((rootKey === '动作流程' || rootKey === '镜头流程') && currentKey === '时间段') { + return true; + } + + return false; +} + +function canAddOrRemoveArray(path: Array): boolean { + const rootKey = String(path[0] ?? ''); + if (LOCKED_TOP_LEVEL_KEYS.has(rootKey)) return false; + if (rootKey === '动作流程' || rootKey === '镜头流程') return false; + return true; +} + +function fieldTitle(key: string | number): string { + return typeof key === 'number' ? `第 ${key + 1} 项` : key; +} + +function ReadonlyBlock({ value }: { value: JsonValue }) { + const text = stringifyReadonly(value); + return shouldUseTextArea(value) ? ( +